├── pos-system ├── version.txt ├── src │ ├── test │ │ ├── resources │ │ │ ├── application.yml │ │ │ ├── application-dev.yml │ │ │ └── application-test.yml │ │ ├── .DS_Store │ │ └── java │ │ │ ├── .DS_Store │ │ │ ├── com │ │ │ ├── .DS_Store │ │ │ └── lifepill │ │ │ │ ├── .DS_Store │ │ │ │ └── possystem │ │ │ │ ├── .DS_Store │ │ │ │ ├── service │ │ │ │ ├── EmployerServiceTest.java │ │ │ │ └── ItemServiceIMPLTest.java │ │ │ │ ├── cucumberglue │ │ │ │ └── CucumbertestRunner.java │ │ │ │ ├── config │ │ │ │ ├── CucumberRunnerTest.java │ │ │ │ └── TestConfiguration.java │ │ │ │ ├── PosSystemApplicationTests.java │ │ │ │ ├── repo │ │ │ │ ├── ItemRepositoryTest.java │ │ │ │ ├── OrderDetailsRepositoryTest.java │ │ │ │ ├── OrderRepositoryTest.java │ │ │ │ └── EmployerRepositoryTests.java │ │ │ │ ├── controller │ │ │ │ ├── MedicineFindingControllerTest.java │ │ │ │ └── BranchManagerControllerTest.java │ │ │ │ └── cucumber │ │ │ │ ├── auth.feature │ │ │ │ └── supplier │ │ │ │ └── supplier.feature │ │ │ ├── features │ │ │ └── medicine_finding.feature │ │ │ └── stepDefinition │ │ │ └── MedicineFindingStepDefinitions.java │ ├── .DS_Store │ └── main │ │ ├── .DS_Store │ │ ├── java │ │ ├── .DS_Store │ │ └── com │ │ │ ├── .DS_Store │ │ │ └── lifepill │ │ │ ├── .DS_Store │ │ │ └── possystem │ │ │ ├── .DS_Store │ │ │ ├── dto │ │ │ ├── LogoutRequestDTO.java │ │ │ ├── VerifyPinRequestDTO.java │ │ │ ├── responseDTO │ │ │ │ ├── DailySalesSummaryDTO.java │ │ │ │ ├── ChangeManagerResponseDTO.java │ │ │ │ ├── CachedEmployerDetailsResponseDTO.java │ │ │ │ ├── AllPharmacySummaryResponseDTO.java │ │ │ │ ├── ItemGetResponseWithoutSupplierDetailsDTO.java │ │ │ │ ├── PharmacyBranchResponseDTO.java │ │ │ │ ├── OrderResponseDTO.java │ │ │ │ ├── AuthenticationResponseDTO.java │ │ │ │ ├── ItemGetIdResponseDTO.java │ │ │ │ ├── BranchS3DTO.java │ │ │ │ ├── MedicineGetResponseDTO.java │ │ │ │ ├── EmployerAuthDetailsResponseDTO.java │ │ │ │ ├── ItemGetResponseDTO.java │ │ │ │ ├── ItemSearchResponseDTO.java │ │ │ │ ├── ItemGetAllResponseDTO.java │ │ │ │ └── ItemGetIdOldResponseDTO.java │ │ │ ├── EmployerIdNameDTO.java │ │ │ ├── ItemCategoryDTO.java │ │ │ ├── requestDTO │ │ │ │ ├── EmployerUpdate │ │ │ │ │ ├── EmployerRecentPinUpdateDTO.java │ │ │ │ │ ├── EmployerPasswordResetDTO.java │ │ │ │ │ ├── EmployerUpdateDTO.java │ │ │ │ │ ├── EmployerUpdateBankAccountDTO.java │ │ │ │ │ ├── EmployerUpdateAccountDetailsDTO.java │ │ │ │ │ └── EmployerAllDetailsUpdateDTO.java │ │ │ │ ├── ChangeManagerDTO.java │ │ │ │ ├── AuthenticationRequestDTO.java │ │ │ │ ├── BranchDailySalesSummaryDTO.java │ │ │ │ ├── RequestOrderDetailsSaveDTO.java │ │ │ │ ├── RequestPaymentDetailsDTO.java │ │ │ │ ├── BranchUpdateDTO.java │ │ │ │ ├── RequestOrderSMSDTO.java │ │ │ │ ├── RequestOrderSaveDTO.java │ │ │ │ ├── RegisterRequestDTO.java │ │ │ │ ├── ItemSearchRequestDTO.java │ │ │ │ ├── ItemSaveRequestDTO.java │ │ │ │ ├── ItemUpdateDTO.java │ │ │ │ ├── ItemSaveRequestCategoryDTO.java │ │ │ │ └── ItemSearchDocument.java │ │ │ ├── UpdateManagerDTO.java │ │ │ ├── paginated │ │ │ │ └── PaginatedResponseItemDTO.java │ │ │ ├── GroupedOrderDetails.java │ │ │ ├── BranchNewUpdateDTO.java │ │ │ ├── EmployerBankDetailsDTO.java │ │ │ ├── SupplierDTO.java │ │ │ ├── BranchDTO.java │ │ │ ├── SupplierCompanyDTO.java │ │ │ ├── EmployerNewDTO.java │ │ │ ├── EmployerS3DTO.java │ │ │ ├── EmployerDTO.java │ │ │ ├── EmployerWithoutImageDTO.java │ │ │ ├── EmployerWithBankDTO.java │ │ │ └── ItemDTO.java │ │ │ ├── entity │ │ │ ├── enums │ │ │ │ ├── Gender.java │ │ │ │ ├── MeasuringUnitType.java │ │ │ │ ├── Permission.java │ │ │ │ └── Role.java │ │ │ ├── Authority.java │ │ │ ├── ItemCategory.java │ │ │ ├── PaymentDetails.java │ │ │ ├── OrderDetails.java │ │ │ ├── BaseEntity.java │ │ │ ├── EmployerBankDetails.java │ │ │ ├── Supplier.java │ │ │ ├── SupplierCompany.java │ │ │ ├── Order.java │ │ │ └── Branch.java │ │ │ ├── service │ │ │ ├── MedicineFindingService.java │ │ │ ├── S3Service.java │ │ │ ├── SupplierService.java │ │ │ ├── SupplierCompanyService.java │ │ │ ├── OrderService.java │ │ │ ├── EmailService.java │ │ │ ├── AuthService.java │ │ │ ├── SMSService.java │ │ │ ├── BranchService.java │ │ │ ├── impl │ │ │ │ ├── S3ServiceIMPL.java │ │ │ │ └── MedicineFindingServiceIMPL.java │ │ │ ├── ItemSearchService.java │ │ │ ├── RedisService.java │ │ │ ├── ItemService.java │ │ │ ├── EmployerService.java │ │ │ └── BranchSummaryService.java │ │ │ ├── repo │ │ │ ├── supplierRepository │ │ │ │ ├── SupplierCompanyRepository.java │ │ │ │ └── SupplierRepository.java │ │ │ ├── paymentRepository │ │ │ │ └── PaymentRepository.java │ │ │ ├── itemRepository │ │ │ │ ├── ItemCategoryRepository.java │ │ │ │ └── ItemRepository.java │ │ │ ├── orderRepository │ │ │ │ ├── OrderDetailsRepository.java │ │ │ │ └── OrderRepository.java │ │ │ ├── branchRepository │ │ │ │ └── BranchRepository.java │ │ │ └── employerRepository │ │ │ │ ├── EmployerBankDetailsRepository.java │ │ │ │ └── EmployerRepository.java │ │ │ ├── config │ │ │ ├── DotenvConfig.java │ │ │ ├── ModelMapperConfig.java │ │ │ ├── S3Config.java │ │ │ ├── SwaggerConfig.java │ │ │ ├── RedisConfig.java │ │ │ └── ApplicationConfig.java │ │ │ ├── controller │ │ │ ├── TestControllerNew.java │ │ │ ├── secured │ │ │ │ ├── testController.java │ │ │ │ ├── CashierControllerTest.java │ │ │ │ └── AdminController.java │ │ │ ├── NoticesController.java │ │ │ ├── ContactUsController.java │ │ │ ├── OwnerController.java │ │ │ ├── MedicineFindingController.java │ │ │ ├── CashierController.java │ │ │ ├── ItemCategoryController.java │ │ │ └── SupplierController.java │ │ │ ├── exception │ │ │ ├── InsufficientItemQuantityException.java │ │ │ ├── ForbiddenException.java │ │ │ ├── NotFoundException.java │ │ │ ├── BadRequestException.java │ │ │ ├── UnauthorizedException.java │ │ │ ├── EntityNotFoundException.java │ │ │ ├── InvalidRequestException.java │ │ │ ├── InternalServerErrorException.java │ │ │ ├── UnprocessableEntityException.java │ │ │ ├── EntityDuplicationException.java │ │ │ └── AuthenticationException.java │ │ │ ├── util │ │ │ ├── StandardResponse.java │ │ │ ├── mappers │ │ │ │ ├── ItemMapper.java │ │ │ │ ├── EmployerBankDetailsMapper.java │ │ │ │ ├── EmployerAuthDetailsResponseDTOToStringConverter.java │ │ │ │ ├── EmployerMapper.java │ │ │ │ └── OrderMapper.java │ │ │ └── AuthUtils.java │ │ │ ├── audit │ │ │ └── AuditAwareImpl.java │ │ │ ├── helper │ │ │ ├── ActiveStatusHelper.java │ │ │ └── SaveImageHelper.java │ │ │ ├── security │ │ │ └── EmployerUserDetails.java │ │ │ ├── PosSystemApplication.java │ │ │ ├── filter │ │ │ └── JwtAuthFilter.java │ │ │ └── advisor │ │ │ └── AppWideExceptionHandler.java │ │ └── resources │ │ └── application.yml ├── qodana.yaml ├── .DS_Store ├── .mvn │ ├── .DS_Store │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── uploads │ └── .DS_Store ├── data │ ├── grafana │ │ └── grafana.db │ └── prometheus │ │ └── config │ │ └── prometheus.yml ├── .gitignore ├── .dockerignore ├── Dockerfile ├── update_and_deploy.sh ├── .env.docker ├── .env.example ├── deploy_manually.md └── Jenkinsfile ├── .github ├── FUNDING.yml └── workflows │ └── build.yaml └── README.md /pos-system/version.txt: -------------------------------------------------------------------------------- 1 | 0.0.2 2 | -------------------------------------------------------------------------------- /pos-system/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pos-system/src/test/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pos-system/qodana.yaml: -------------------------------------------------------------------------------- 1 | version: "1.0" 2 | profile: 3 | name: qodana.starter 4 | -------------------------------------------------------------------------------- /pos-system/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/.DS_Store -------------------------------------------------------------------------------- /pos-system/.mvn/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/.mvn/.DS_Store -------------------------------------------------------------------------------- /pos-system/src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/src/.DS_Store -------------------------------------------------------------------------------- /pos-system/uploads/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/uploads/.DS_Store -------------------------------------------------------------------------------- /pos-system/src/main/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/src/main/.DS_Store -------------------------------------------------------------------------------- /pos-system/src/test/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/src/test/.DS_Store -------------------------------------------------------------------------------- /pos-system/data/grafana/grafana.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/data/grafana/grafana.db -------------------------------------------------------------------------------- /pos-system/src/main/java/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/src/main/java/.DS_Store -------------------------------------------------------------------------------- /pos-system/src/test/java/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/src/test/java/.DS_Store -------------------------------------------------------------------------------- /pos-system/src/main/java/com/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/src/main/java/com/.DS_Store -------------------------------------------------------------------------------- /pos-system/src/test/java/com/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/src/test/java/com/.DS_Store -------------------------------------------------------------------------------- /pos-system/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/src/main/java/com/lifepill/.DS_Store -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/src/test/java/com/lifepill/.DS_Store -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/src/main/java/com/lifepill/possystem/.DS_Store -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/possystem/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Life-Pill/pharmacy-pos-main-backend/HEAD/pos-system/src/test/java/com/lifepill/possystem/.DS_Store -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/possystem/service/EmployerServiceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | package com.lifepill.possystem.service; 3 | 4 | public class EmployerServiceTest { 5 | 6 | } 7 | */ 8 | -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/possystem/cucumberglue/CucumbertestRunner.java: -------------------------------------------------------------------------------- 1 | //package com.lifepill.possystem.cucumberglue; 2 | // 3 | // 4 | // 5 | //public class CucumbertestRunner { 6 | //} 7 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/LogoutRequestDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class LogoutRequestDTO { 7 | private String username; 8 | } 9 | -------------------------------------------------------------------------------- /pos-system/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 3 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/entity/enums/Gender.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.entity.enums; 2 | 3 | /** 4 | * The enum Gender. 5 | */ 6 | public enum Gender { 7 | /** 8 | * Male gender. 9 | */ 10 | MALE, 11 | /** 12 | * Female gender. 13 | */ 14 | FEMALE 15 | } 16 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/MedicineFindingService.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.service; 2 | 3 | import com.lifepill.possystem.dto.responseDTO.MedicineGetResponseDTO; 4 | 5 | 6 | import java.util.List; 7 | 8 | public interface MedicineFindingService { 9 | List getItemByName(String itemName); 10 | } 11 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/VerifyPinRequestDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class VerifyPinRequestDTO { 11 | private String username; 12 | private int pin; 13 | } 14 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/S3Service.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.service; 2 | 3 | import com.amazonaws.services.s3.model.S3Object; 4 | import org.springframework.web.multipart.MultipartFile; 5 | 6 | import java.io.IOException; 7 | 8 | public interface S3Service { 9 | String uploadFile(String keyName, MultipartFile file) throws IOException; 10 | S3Object getFile(String keyName); 11 | } 12 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/repo/supplierRepository/SupplierCompanyRepository.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.repo.supplierRepository; 2 | 3 | import com.lifepill.possystem.entity.SupplierCompany; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * The interface Supplier company repository. 8 | */ 9 | public interface SupplierCompanyRepository extends JpaRepository { 10 | } -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/possystem/config/CucumberRunnerTest.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.config; 2 | 3 | import io.cucumber.junit.Cucumber; 4 | import io.cucumber.junit.CucumberOptions; 5 | import org.junit.runner.RunWith; 6 | 7 | @RunWith(Cucumber.class) 8 | @CucumberOptions( 9 | features = "src/test/resources/features", 10 | glue = "com.example.cucumber.stepdefinitions" 11 | ) 12 | public class CucumberRunnerTest { 13 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/DailySalesSummaryDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | 3 | import lombok.*; 4 | 5 | import java.time.LocalDate; 6 | import java.util.List; 7 | 8 | @Getter 9 | @Setter 10 | @ToString 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class DailySalesSummaryDTO { 14 | private LocalDate date; 15 | private long orders; 16 | private double sales; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/EmployerIdNameDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | @Getter 9 | @Setter 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class EmployerIdNameDTO { 13 | private long employerId; 14 | private String employerFirstName; 15 | private String employerLastName; 16 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/ItemCategoryDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | import lombok.*; 4 | 5 | /** 6 | * The type Item category dto. 7 | */ 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | @Getter 11 | @Setter 12 | @ToString 13 | public class ItemCategoryDTO { 14 | private long categoryId; 15 | private String categoryName; 16 | private String categoryDescription; 17 | private String categoryImage; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/possystem/config/TestConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.config; 2 | 3 | import com.lifepill.possystem.util.mappers.EmployerMapper; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | public class TestConfiguration { 9 | 10 | 11 | public EmployerMapper employerMapper() { 12 | return new EmployerMapper(); 13 | } 14 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/ChangeManagerResponseDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | 3 | import com.lifepill.possystem.dto.UpdateManagerDTO; 4 | import lombok.*; 5 | 6 | @Getter 7 | @Setter 8 | @ToString 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class ChangeManagerResponseDTO { 12 | private long branchId; 13 | private UpdateManagerDTO newManager; 14 | private UpdateManagerDTO formerManager; 15 | } 16 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/CachedEmployerDetailsResponseDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class CachedEmployerDetailsResponseDTO { 11 | private AuthenticationResponseDTO authenticationResponse; 12 | private EmployerAuthDetailsResponseDTO employerDetails; 13 | } 14 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/config/DotenvConfig.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.config; 2 | 3 | import io.github.cdimascio.dotenv.Dotenv; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | @Configuration 8 | public class DotenvConfig { 9 | @Bean 10 | public Dotenv dotenv() { 11 | return Dotenv.configure() 12 | .ignoreIfMissing() 13 | .load(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/EmployerUpdate/EmployerRecentPinUpdateDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO.EmployerUpdate; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * The type Employer recent pin update dto. 9 | */ 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | @Data 13 | public class EmployerRecentPinUpdateDTO { 14 | private long employerId; 15 | private int pin; 16 | } 17 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/AllPharmacySummaryResponseDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | import lombok.AllArgsConstructor; 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @NoArgsConstructor 7 | @AllArgsConstructor 8 | @Data 9 | public class AllPharmacySummaryResponseDTO { 10 | private Double totalSales; 11 | private Integer totalOrders; 12 | private Integer totalEmployees; 13 | private Integer totalBranches; 14 | } 15 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/ItemGetResponseWithoutSupplierDetailsDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | 3 | import com.lifepill.possystem.dto.ItemCategoryDTO; 4 | import lombok.*; 5 | 6 | @AllArgsConstructor 7 | @NoArgsConstructor 8 | @Getter 9 | @Setter 10 | @ToString 11 | public class ItemGetResponseWithoutSupplierDetailsDTO { 12 | private ItemGetAllResponseDTO itemGetAllResponseDTO; 13 | private ItemCategoryDTO itemCategoryDTO; 14 | } 15 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/EmployerUpdate/EmployerPasswordResetDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO.EmployerUpdate; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * The type Employer password reset dto. 9 | */ 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | @Data 13 | public class EmployerPasswordResetDTO { 14 | private long employerId; 15 | private String employerPassword; 16 | } 17 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/controller/TestControllerNew.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.controller; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequestMapping("/test2") 9 | public class TestControllerNew { 10 | 11 | @GetMapping("/test") 12 | public String test() { 13 | return "Test"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/ChangeManagerDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO; 2 | 3 | import com.lifepill.possystem.entity.enums.Role; 4 | import lombok.*; 5 | 6 | @Getter 7 | @Setter 8 | @ToString 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class ChangeManagerDTO { 12 | private long formerManagerId; 13 | private long branchId; 14 | private long newManagerId; 15 | private Role currentManagerNewRole; 16 | private Role newManagerRole; 17 | } 18 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/AuthenticationRequestDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * The type Authentication request dto. 10 | */ 11 | @Data 12 | @Builder 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class AuthenticationRequestDTO { 16 | 17 | private String employerEmail; 18 | private String employerPassword; 19 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/exception/InsufficientItemQuantityException.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.exception; 2 | 3 | /** 4 | * The type Insufficient item quantity exception. 5 | */ 6 | public class InsufficientItemQuantityException extends RuntimeException { 7 | /** 8 | * Instantiates a new Insufficient item quantity exception. 9 | * 10 | * @param message the message 11 | */ 12 | public InsufficientItemQuantityException(String message) { 13 | super(message); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/controller/secured/testController.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.controller.secured; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequestMapping("/lifepill/v1") 9 | public class testController { 10 | 11 | @GetMapping("/test") 12 | public String test() { 13 | return "Test Controller"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/SupplierService.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.service; 2 | 3 | import com.lifepill.possystem.dto.SupplierDTO; 4 | 5 | import java.util.List; 6 | 7 | public interface SupplierService { 8 | List getAllSuppliers(); 9 | 10 | SupplierDTO saveSupplier(SupplierDTO supplierDTO); 11 | 12 | SupplierDTO updateSupplierById(long id, SupplierDTO updatedSupplierDTO); 13 | 14 | void deleteSupplierById(long id); 15 | 16 | SupplierDTO getSupplierById(long id); 17 | } 18 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/UpdateManagerDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | import com.lifepill.possystem.entity.enums.Role; 4 | import lombok.*; 5 | 6 | @Getter 7 | @Setter 8 | @ToString 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class UpdateManagerDTO { 12 | private long branchId; 13 | private String employerFirstName; 14 | private String employerLastName; 15 | private String employerEmail; 16 | private String employerPassword; 17 | private Role role; 18 | private int pin; 19 | } 20 | -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/possystem/PosSystemApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.junit.jupiter.api.extension.ExtendWith; 5 | import org.mockito.junit.jupiter.MockitoExtension; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | import org.springframework.test.context.ActiveProfiles; 8 | 9 | @SpringBootTest 10 | @ActiveProfiles("test") 11 | @ExtendWith(MockitoExtension.class) 12 | class PosSystemApplicationTests { 13 | @Test 14 | void contextLoads() { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pos-system/data/prometheus/config/prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 15s 3 | evaluation_interval: 15s 4 | 5 | scrape_configs: 6 | # Prometheus self-monitoring 7 | - job_name: 'prometheus' 8 | static_configs: 9 | - targets: ['localhost:9090'] 10 | 11 | # LifePill POS System Application 12 | - job_name: 'lifepill-pos-system' 13 | metrics_path: "/actuator/prometheus" 14 | scrape_interval: 5s 15 | static_configs: 16 | - targets: ['app:8080'] 17 | labels: 18 | application: "LifePill POS System" 19 | environment: "docker" -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/BranchDailySalesSummaryDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO; 2 | 3 | import com.lifepill.possystem.dto.responseDTO.DailySalesSummaryDTO; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.List; 10 | 11 | @Data 12 | @Builder 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | public class BranchDailySalesSummaryDTO { 16 | private long branchId; 17 | private List dailySalesSummary; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/PharmacyBranchResponseDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | 3 | import com.lifepill.possystem.dto.BranchDTO; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * The type Pharmacy branch response dto. 10 | */ 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | @Data 14 | public class PharmacyBranchResponseDTO { 15 | 16 | private Double sales; 17 | private Integer orders; 18 | private String manager; 19 | private BranchDTO branchDTO; 20 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/repo/paymentRepository/PaymentRepository.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.repo.paymentRepository; 2 | 3 | import com.lifepill.possystem.entity.PaymentDetails; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 6 | import org.springframework.stereotype.Repository; 7 | 8 | /** 9 | * The interface Payment repository. 10 | */ 11 | @Repository 12 | @EnableJpaRepositories 13 | public interface PaymentRepository extends JpaRepository { 14 | } 15 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/OrderResponseDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | 3 | import com.lifepill.possystem.dto.GroupedOrderDetails; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.Date; 9 | 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class OrderResponseDTO { 14 | private long employerId; 15 | private long branchId; 16 | private Date orderDate; 17 | private Double total; 18 | private GroupedOrderDetails groupedOrderDetails; 19 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/RequestOrderDetailsSaveDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | 8 | /** 9 | * The type Request order details save dto. 10 | */ 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | @Data 14 | public class RequestOrderDetailsSaveDTO { 15 | private String name; // TODO: Change name to itemName 16 | private Double amount; // TODO: Change amount to itemAmount 17 | private long id; // TODO: Change id to itemId 18 | 19 | } 20 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/AuthenticationResponseDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | /** 10 | * The type Authentication response dto. 11 | */ 12 | @Data 13 | @Builder 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class AuthenticationResponseDTO { 17 | 18 | @JsonProperty("access_token") 19 | private String accessToken; 20 | private String message; 21 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/exception/ForbiddenException.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | /** 7 | * The type Forbidden exception. 8 | */ 9 | @ResponseStatus(value = HttpStatus.FORBIDDEN) 10 | public class ForbiddenException extends RuntimeException { 11 | /** 12 | * Instantiates a new Forbidden exception. 13 | * 14 | * @param message the message 15 | */ 16 | public ForbiddenException(String message) { 17 | super(message); 18 | } 19 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/exception/NotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | /** 7 | * The type Not found exception. 8 | */ 9 | @ResponseStatus(value = HttpStatus.NOT_FOUND) 10 | public class NotFoundException extends RuntimeException{ 11 | /** 12 | * Instantiates a new Not found exception. 13 | * 14 | * @param message the message 15 | */ 16 | public NotFoundException(String message){ 17 | super(message); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/paginated/PaginatedResponseItemDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.paginated; 2 | 3 | import com.lifepill.possystem.dto.responseDTO.ItemGetResponseDTO; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * The type Paginated response item dto. 12 | */ 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | @Data 16 | public class PaginatedResponseItemDTO { 17 | /** 18 | * The List. 19 | */ 20 | List list; 21 | private long dataCount; 22 | } 23 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/exception/BadRequestException.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | /** 7 | * The type Bad request exception. 8 | */ 9 | @ResponseStatus(value = HttpStatus.BAD_REQUEST) 10 | public class BadRequestException extends RuntimeException { 11 | /** 12 | * Instantiates a new Bad request exception. 13 | * 14 | * @param message the message 15 | */ 16 | public BadRequestException(String message) { 17 | super(message); 18 | } 19 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/GroupedOrderDetails.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | import com.lifepill.possystem.dto.requestDTO.RequestOrderDetailsSaveDTO; 3 | import com.lifepill.possystem.dto.requestDTO.RequestPaymentDetailsDTO; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.List; 9 | 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class GroupedOrderDetails { 14 | private List orderDetails; 15 | private RequestPaymentDetailsDTO paymentDetails; 16 | private int orderCount; 17 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/exception/UnauthorizedException.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | /** 7 | * The type Unauthorized exception. 8 | */ 9 | @ResponseStatus(value = HttpStatus.UNAUTHORIZED) 10 | public class UnauthorizedException extends RuntimeException { 11 | /** 12 | * Instantiates a new Unauthorized exception. 13 | * 14 | * @param message the message 15 | */ 16 | public UnauthorizedException(String message) { 17 | super(message); 18 | } 19 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/SupplierCompanyService.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.service; 2 | 3 | import com.lifepill.possystem.dto.SupplierCompanyDTO; 4 | 5 | import java.util.List; 6 | 7 | public interface SupplierCompanyService { 8 | List getAllSupplierCompanies(); 9 | 10 | SupplierCompanyDTO saveSupplierCompany(SupplierCompanyDTO supplierCompanyDTO); 11 | 12 | SupplierCompanyDTO updateSupplierCompanyById(long id, SupplierCompanyDTO updatedCompanyDTO); 13 | 14 | void deleteSupplierCompanyById(long id); 15 | 16 | SupplierCompanyDTO getSupplierCompanyById(long id); 17 | } 18 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/util/StandardResponse.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.util; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * A standard response object containing a code, message, and data. 9 | */ 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | @Data 13 | public class StandardResponse { 14 | /** The status code of the response. */ 15 | private int code; 16 | /** The message associated with the response. */ 17 | private String message; 18 | /** The data associated with the response. */ 19 | private Object data; 20 | } 21 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/exception/EntityNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | /** 7 | * The type Entity not found exception. 8 | */ 9 | @ResponseStatus(value = HttpStatus.NOT_FOUND) 10 | public class EntityNotFoundException extends RuntimeException { 11 | /** 12 | * Instantiates a new Entity not found exception. 13 | * 14 | * @param message the message 15 | */ 16 | public EntityNotFoundException(String message) { 17 | super(message); 18 | } 19 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/exception/InvalidRequestException.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | /** 7 | * The type Invalid request exception. 8 | */ 9 | @ResponseStatus(value = HttpStatus.BAD_REQUEST) 10 | public class InvalidRequestException extends RuntimeException { 11 | /** 12 | * Instantiates a new Invalid request exception. 13 | * 14 | * @param message the message 15 | */ 16 | public InvalidRequestException(String message) { 17 | super(message); 18 | } 19 | } -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/possystem/repo/ItemRepositoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | package com.lifepill.possystem.repo; 3 | 4 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 5 | 6 | @DataJpaTest 7 | class ItemRepositoryTest { 8 | 9 | */ 10 | /* @Autowired 11 | private TestEntityManager entityManager; 12 | 13 | @Autowired 14 | private ItemRepository itemRepository; 15 | 16 | @Test 17 | void testSaveItem() { 18 | // Create test data 19 | 20 | 21 | // Call repository method 22 | 23 | 24 | // Assert result 25 | 26 | }*//* 27 | 28 | }*/ 29 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/EmployerUpdate/EmployerUpdateDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO.EmployerUpdate; 2 | 3 | import com.lifepill.possystem.entity.enums.Role; 4 | import lombok.*; 5 | 6 | /** 7 | * The type Employer update dto. 8 | */ 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Data 12 | public class EmployerUpdateDTO { 13 | private long employerId; 14 | // private int branchId; 15 | private String employerNicName; 16 | private String employerEmail; 17 | private String employerNic; 18 | private String employerPhone; 19 | private double employerSalary; 20 | private Role role; 21 | 22 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/RequestPaymentDetailsDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Date; 8 | 9 | /** 10 | * The type Request payment details dto. 11 | */ 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | @Data 15 | public class RequestPaymentDetailsDTO { 16 | 17 | private String paymentMethod; 18 | private double paymentAmount; 19 | private Date paymentDate; 20 | private String paymentNotes; 21 | private double paymentDiscount; 22 | private double payedAmount; 23 | } 24 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/BranchNewUpdateDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | import lombok.*; 4 | 5 | @Getter 6 | @Setter 7 | @NoArgsConstructor 8 | @AllArgsConstructor 9 | @ToString 10 | public class BranchNewUpdateDTO { 11 | private long branchId; 12 | private String branchName; 13 | private String branchAddress; 14 | private String branchContact; 15 | private String branchFax; 16 | private String branchEmail; 17 | private String branchDescription; 18 | private boolean branchStatus; 19 | private String branchLocation; 20 | private String branchCreatedOn; 21 | private String branchCreatedBy; 22 | } 23 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/ItemGetIdResponseDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | 3 | import com.lifepill.possystem.dto.ItemCategoryDTO; 4 | import com.lifepill.possystem.dto.SupplierCompanyDTO; 5 | import com.lifepill.possystem.dto.SupplierDTO; 6 | import lombok.*; 7 | 8 | 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | @Getter 12 | @Setter 13 | @ToString 14 | public class ItemGetIdResponseDTO { 15 | private ItemGetAllResponseDTO itemGetAllResponseDTO; 16 | private ItemCategoryDTO itemCategoryDTO; 17 | private SupplierDTO supplierDTO; 18 | private SupplierCompanyDTO supplierCompanyDTO; 19 | } 20 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/exception/InternalServerErrorException.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | /** 7 | * The type Internal server error exception. 8 | */ 9 | @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) 10 | public class InternalServerErrorException extends RuntimeException { 11 | /** 12 | * Instantiates a new Internal server error exception. 13 | * 14 | * @param message the message 15 | */ 16 | public InternalServerErrorException(String message) { 17 | super(message); 18 | } 19 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/exception/UnprocessableEntityException.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | /** 7 | * The type Unprocessable entity exception. 8 | */ 9 | @ResponseStatus(value = HttpStatus.UNPROCESSABLE_ENTITY) 10 | public class UnprocessableEntityException extends RuntimeException { 11 | /** 12 | * Instantiates a new Unprocessable entity exception. 13 | * 14 | * @param message the message 15 | */ 16 | public UnprocessableEntityException(String message) { 17 | super(message); 18 | } 19 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/EmployerBankDetailsDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @AllArgsConstructor 8 | @NoArgsConstructor 9 | @Data 10 | public class EmployerBankDetailsDTO { 11 | 12 | private long employerBankDetailsId; 13 | private String bankName; 14 | private String bankBranchName; 15 | private String bankAccountNumber; 16 | private String employerDescription; 17 | private double monthlyPayment; 18 | private Boolean monthlyPaymentStatus; 19 | private long employerId; 20 | // private Set employers; 21 | } 22 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/SupplierDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * The type Supplier dto. 9 | */ 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | @Data 13 | public class SupplierDTO { 14 | private long supplierId; 15 | private long companyId; 16 | private String supplierName; 17 | private String supplierAddress; 18 | private String supplierPhone; 19 | private String supplierEmail; 20 | private String supplierDescription; 21 | private String supplierImage; 22 | private String supplierRating; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/repo/itemRepository/ItemCategoryRepository.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.repo.itemRepository; 2 | 3 | import com.lifepill.possystem.entity.ItemCategory; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 6 | import org.springframework.stereotype.Repository; 7 | 8 | /** 9 | * The interface Item category repository. 10 | */ 11 | //@RepositoryRestResource(collectionResourceRel = "itemCategory", path = "item-Category") 12 | @Repository 13 | @EnableJpaRepositories 14 | public interface ItemCategoryRepository extends JpaRepository { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/repo/orderRepository/OrderDetailsRepository.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.repo.orderRepository; 2 | 3 | import com.lifepill.possystem.entity.Order; 4 | import com.lifepill.possystem.entity.OrderDetails; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 7 | import org.springframework.stereotype.Repository; 8 | 9 | /** 10 | * The interface Order details repository. 11 | */ 12 | @Repository 13 | @EnableJpaRepositories 14 | public interface OrderDetailsRepository extends JpaRepository { 15 | 16 | 17 | Object findByOrders(Order order); 18 | } 19 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/exception/EntityDuplicationException.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | /** 7 | * The type Entity duplication exception. 8 | */ 9 | @ResponseStatus(value = HttpStatus.CONFLICT) // Use HttpStatus.CONFLICT for entity duplication 10 | public class EntityDuplicationException extends RuntimeException { 11 | /** 12 | * Instantiates a new Entity duplication exception. 13 | * 14 | * @param message the message 15 | */ 16 | public EntityDuplicationException(String message) { 17 | super(message); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /pos-system/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea/ 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | 23 | ### NetBeans ### 24 | /nbproject/private/ 25 | /nbbuild/ 26 | /dist/ 27 | /nbdist/ 28 | /.nb-gradle/ 29 | build/ 30 | !**/src/main/**/build/ 31 | !**/src/test/**/build/ 32 | 33 | ### VS Code ### 34 | .vscode/ 35 | 36 | ### Mac ### 37 | .DS_Store 38 | 39 | # Ignore dotenv files 40 | *.env 41 | *.env.local 42 | *.env.development.local 43 | *.env.test.local 44 | *.env.production.local 45 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/controller/NoticesController.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.controller; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | /** 8 | * Controller class for managing notices-related endpoints. 9 | */ 10 | @RestController 11 | @RequestMapping("lifepill/v1/notices") 12 | public class NoticesController { 13 | 14 | /** 15 | * Retrieves notices. 16 | * 17 | * @return A string indicating notices. 18 | */ 19 | @GetMapping("/notices") 20 | public String getNotices() { 21 | return "Notices"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/BranchDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | import lombok.*; 4 | 5 | /** 6 | * The type Branch dto. 7 | */ 8 | @Getter 9 | @Setter 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | @ToString 13 | public class BranchDTO { 14 | private long branchId; 15 | private String branchName; 16 | private String branchAddress; 17 | private String branchContact; 18 | private String branchFax; 19 | private String branchEmail; 20 | private String branchDescription; 21 | private byte[] branchImage; 22 | private boolean branchStatus; 23 | private String branchLocation; 24 | private String branchCreatedOn; 25 | private String branchCreatedBy; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/entity/Authority.java: -------------------------------------------------------------------------------- 1 | /* 2 | package com.lifepill.possystem.entity; 3 | 4 | 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | import org.hibernate.annotations.GenericGenerator; 9 | 10 | import javax.persistence.*; 11 | 12 | @Entity 13 | @Getter 14 | @Setter 15 | @ToString 16 | @Table(name = "authorities") 17 | public class Authority { 18 | 19 | @Id 20 | @GeneratedValue(strategy= GenerationType.AUTO,generator="native") 21 | @GenericGenerator(name = "native",strategy = "native") 22 | private Long id; 23 | 24 | private String name; 25 | 26 | @ManyToOne 27 | @JoinColumn(name = "employer_id") 28 | private Employer employer; 29 | 30 | 31 | }*/ 32 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/audit/AuditAwareImpl.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.audit; 2 | 3 | import org.springframework.data.domain.AuditorAware; 4 | import org.springframework.stereotype.Component; 5 | 6 | import java.util.Optional; 7 | 8 | /** 9 | * Implementation of AuditorAware interface to provide the current auditor of the application. 10 | */ 11 | @Component("auditorAwareImpl") 12 | public class AuditAwareImpl implements AuditorAware { 13 | 14 | /** 15 | * This method is used to get the current auditor of the application 16 | * @return the current auditor 17 | */ 18 | @Override 19 | public Optional getCurrentAuditor() { 20 | return Optional.of("PosSystem"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.service; 2 | 3 | import com.lifepill.possystem.dto.requestDTO.RequestOrderSMSDTO; 4 | import com.lifepill.possystem.dto.requestDTO.RequestOrderSaveDTO; 5 | import com.lifepill.possystem.dto.responseDTO.OrderResponseDTO; 6 | 7 | import java.util.List; 8 | 9 | public interface OrderService { 10 | String addOrder(RequestOrderSaveDTO requestOrderSaveDTO); 11 | 12 | String addOrderWithSMS(RequestOrderSMSDTO requestOrderSaveDTO) ; 13 | 14 | List getAllOrdersWithDetails(); 15 | 16 | OrderResponseDTO getOrderWithDetailsById(long orderId); 17 | 18 | List getOrderWithDetailsByBranchId(long branchId); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/EmployerUpdate/EmployerUpdateBankAccountDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO.EmployerUpdate; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * The type Employer update bank account dto. 9 | */ 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | @Data 13 | public class EmployerUpdateBankAccountDTO { 14 | private long employerBankDetailsId; 15 | private String bankName; 16 | private String bankBranchName; 17 | private String bankAccountNumber; 18 | private String employerDescription; 19 | private double monthlyPayment; 20 | private boolean monthlyPaymentStatus; 21 | private long employerId; 22 | } 23 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/controller/secured/CashierControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.controller.secured; 2 | 3 | 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.PostMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @RequestMapping("/lifepill/v1/cashierNew") 11 | public class CashierControllerTest { 12 | @GetMapping 13 | public String getCashier() { 14 | return "Secured Endpoint :: GET - Cashier controller"; 15 | } 16 | 17 | @PostMapping 18 | public String post() { 19 | return "POST:: Cashier controller"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/BranchUpdateDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO; 2 | 3 | import lombok.*; 4 | 5 | /** 6 | * The type Branch update dto. 7 | */ 8 | @Getter 9 | @Setter 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | @ToString 13 | public class BranchUpdateDTO { 14 | private int branchId; 15 | private String branchName; 16 | private String branchAddress; 17 | private String branchContact; 18 | private String branchFax; 19 | private String branchEmail; 20 | private String branchDescription; 21 | private byte[] branchImage; 22 | private boolean branchStatus; 23 | private String branchLocation; 24 | private String branchCreatedOn; 25 | private String branchCreatedBy; 26 | } 27 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/exception/AuthenticationException.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.exception; 2 | 3 | /** 4 | * The type Authentication exception. 5 | */ 6 | public class AuthenticationException extends RuntimeException { 7 | 8 | /** 9 | * Instantiates a new Authentication exception. 10 | * 11 | * @param message the message 12 | */ 13 | public AuthenticationException(String message) { 14 | super(message); 15 | } 16 | 17 | /** 18 | * Instantiates a new Authentication exception. 19 | * 20 | * @param message the message 21 | * @param cause the cause 22 | */ 23 | public AuthenticationException(String message, Throwable cause) { 24 | super(message, cause); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/controller/ContactUsController.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.controller; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | /** 8 | * Controller class for handling contact us related operations. 9 | */ 10 | @RestController 11 | @RequestMapping("lifepill/v1/contact") 12 | public class ContactUsController { 13 | 14 | /** 15 | * Retrieves the contact information. 16 | * 17 | * @return A string representing the contact information. 18 | */ 19 | @GetMapping("/contact-us") 20 | public String getContactUs() { 21 | return "Contact Us"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/RequestOrderSMSDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Date; 8 | import java.util.List; 9 | 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | @Data 13 | public class RequestOrderSMSDTO { 14 | private long employerId; 15 | private long orderId; 16 | private long branchId; 17 | private Date orderDate; 18 | private String customerPhoneNumber; 19 | private String customerEmail; 20 | private Double total; // TODO Change total to orderTotal 21 | private List orderDetails; 22 | private RequestPaymentDetailsDTO paymentDetails; 23 | } 24 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/BranchS3DTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | 3 | import lombok.*; 4 | 5 | /** 6 | * The type Branch dto. 7 | */ 8 | @Getter 9 | @Setter 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | @ToString 13 | public class BranchS3DTO { 14 | private long branchId; 15 | private String branchName; 16 | private String branchAddress; 17 | private String branchContact; 18 | private String branchFax; 19 | private String branchEmail; 20 | private String branchDescription; 21 | private boolean branchStatus; 22 | private String branchLocation; 23 | private String branchCreatedOn; 24 | private String branchCreatedBy; 25 | private String branchProfileImageUrl; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/SupplierCompanyDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * The type Supplier company dto. 9 | */ 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | @Data 13 | public class SupplierCompanyDTO { 14 | private long companyId; 15 | private String companyName; 16 | private String companyAddress; 17 | private String companyContact; 18 | private String companyEmail; 19 | private String companyDescription; 20 | private String companyImage; 21 | private String companyStatus; 22 | private String companyRating; 23 | private String companyBank; 24 | private String companyAccountNumber; 25 | } 26 | -------------------------------------------------------------------------------- /pos-system/src/test/java/features/medicine_finding.feature: -------------------------------------------------------------------------------- 1 | ## features/medicine_finding.feature 2 | # 3 | #Feature: Medicine Finding 4 | # 5 | # Scenario: Find medicine by name successfully 6 | # Given a list of existing medicines 7 | # When the client requests to find medicines by name "Paracetamol" 8 | # Then the response should contain a list of medicines with the name "Paracetamol" 9 | # And the response should have a success status code 10 | # 11 | # Scenario: Find medicine by name when no medicine is found 12 | # Given a list of existing medicines 13 | # When the client requests to find medicines by name "NonExistingMedicine" 14 | # Then the response should contain an error message "No item found with the name NonExistingMedicine" 15 | # And the response should have an error status code -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/repo/supplierRepository/SupplierRepository.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.repo.supplierRepository; 2 | 3 | import com.lifepill.possystem.entity.Supplier; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 6 | import org.springframework.stereotype.Repository; 7 | 8 | /** 9 | * The interface Supplier repository. 10 | */ 11 | @Repository 12 | @EnableJpaRepositories 13 | public interface SupplierRepository extends JpaRepository { 14 | /** 15 | * Exists all by supplier email boolean. 16 | * 17 | * @param supplierEmail the supplier email 18 | * @return the boolean 19 | */ 20 | boolean existsAllBySupplierEmail(String supplierEmail); 21 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/util/mappers/ItemMapper.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.util.mappers; 2 | 3 | import com.lifepill.possystem.dto.responseDTO.ItemGetAllResponseDTO; 4 | import com.lifepill.possystem.dto.responseDTO.ItemGetResponseDTO; 5 | import com.lifepill.possystem.entity.Item; 6 | import org.mapstruct.Mapper; 7 | import org.springframework.data.domain.Page; 8 | 9 | import java.util.List; 10 | 11 | @Mapper(componentModel = "spring") 12 | public interface ItemMapper { 13 | // itemList ----> ItemResponseDTO 14 | List entityListToDTOList(List items); 15 | List entityListAllItemToDTO(List items); 16 | //Page items ---> List list; 17 | ListListDTOToPage(Page items); 18 | } 19 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/util/AuthUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | package com.lifepill.possystem.util; 3 | 4 | import javax.servlet.http.HttpSession; 5 | 6 | public class AuthUtils { 7 | 8 | // Method to check if the user is logged in based on the session 9 | public static boolean isLoggedIn(String request) { 10 | // Get the session from the request, create a new session if it doesn't exist 11 | HttpSession session = request.getSession(false); 12 | 13 | // Check if the session exists and contains an attribute indicating the user is logged in 14 | if (session != null && session.getAttribute("loggedInUser") != null) { 15 | return true; // User is logged in 16 | } else { 17 | return false; // User is not logged in 18 | } 19 | } 20 | } 21 | */ 22 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/repo/branchRepository/BranchRepository.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.repo.branchRepository; 2 | 3 | import com.lifepill.possystem.entity.Branch; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * The interface Branch repository. 12 | */ 13 | @Repository 14 | @EnableJpaRepositories 15 | public interface BranchRepository extends JpaRepository { 16 | /** 17 | * Exists by branch email boolean. 18 | * 19 | * @param branchEmail the branch email 20 | * @return the boolean 21 | */ 22 | boolean existsByBranchEmail(String branchEmail); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/EmailService.java: -------------------------------------------------------------------------------- 1 | /* 2 | package com.lifepill.possystem.service; 3 | 4 | import org.springframework.mail.SimpleMailMessage; 5 | import org.springframework.mail.javamail.JavaMailSender; 6 | import org.springframework.stereotype.Service; 7 | 8 | @Service 9 | public class EmailService { 10 | 11 | private final JavaMailSender javaMailSender; 12 | 13 | public EmailService(JavaMailSender javaMailSender) { 14 | this.javaMailSender = javaMailSender; 15 | } 16 | 17 | public void sendEmail(String to, String subject, String text) { 18 | SimpleMailMessage message = new SimpleMailMessage(); 19 | message.setTo(to); 20 | message.setSubject(subject); 21 | message.setText(text); 22 | javaMailSender.send(message); 23 | } 24 | } 25 | */ 26 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/helper/ActiveStatusHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | package com.lifepill.possystem.helper; 3 | 4 | import com.lifepill.possystem.repo.employerRepository.EmployerRepository; 5 | import lombok.*; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | 8 | @Setter 9 | @Getter 10 | @ToString 11 | @AllArgsConstructor 12 | @RequiredArgsConstructor 13 | public class ActiveStatusHelper { 14 | 15 | final EmployerRepository employerRepository; 16 | 17 | private void updateActiveStatus(String username) { 18 | // Implement your logic to update the active status in the database 19 | // For example, you can call a method in the repository to update the active status for the given username 20 | employerRepository.updateActiveStatusByEmail(username, true); 21 | } 22 | } 23 | */ 24 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/RequestOrderSaveDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO; 2 | 3 | import com.lifepill.possystem.entity.OrderDetails; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.Date; 9 | import java.util.List; 10 | import java.util.Set; 11 | 12 | /** 13 | * The type Request order save dto. 14 | */ 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Data 18 | public class RequestOrderSaveDTO { 19 | 20 | private long employerId; 21 | private long orderId; 22 | private long branchId; 23 | private Date orderDate; 24 | private Double total; // TODO Change total to orderTotal 25 | private List orderDetails; 26 | private RequestPaymentDetailsDTO paymentDetails; 27 | 28 | } -------------------------------------------------------------------------------- /pos-system/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | jpa: 3 | hibernate: 4 | ddl-auto: create-drop 5 | properties: 6 | hibernate: 7 | dialect: org.hibernate.dialect.H2Dialect 8 | jdbc: 9 | lob: 10 | non_contextual_creation: true 11 | show-sql: true 12 | 13 | security: 14 | user: 15 | name: ${SPRING_SECURITY_USERNAME} 16 | password: ${SPRING_SECURITY_PASSWORD} 17 | 18 | server: 19 | port: 0 # Random port 20 | 21 | logging: 22 | level: 23 | org.springframework.security: TRACE 24 | 25 | aws: 26 | access.key: ${AWS_ACCESS_KEY} 27 | secret.key: ${AWS_SECRET_KEY} 28 | s3.bucket: ${AWS_S3_BUCKET} 29 | region: ${AWS_REGION} 30 | # 31 | #twilio: 32 | # accountSid: ${TWILIO_ACCOUNT_SID} 33 | # authToken: ${TWILIO_AUTH_TOKEN} 34 | # fromPhoneNumber: ${TWILIO_FROM_PHONE_NUMBER} -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/repo/employerRepository/EmployerBankDetailsRepository.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.repo.employerRepository; 2 | 3 | import com.lifepill.possystem.entity.EmployerBankDetails; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 6 | import org.springframework.stereotype.Repository; 7 | 8 | /** 9 | * The interface Employer bank details repository. 10 | */ 11 | @Repository 12 | @EnableJpaRepositories 13 | public interface EmployerBankDetailsRepository extends JpaRepository { 14 | 15 | /** 16 | * Find by employer id employer bank details. 17 | * 18 | * @param employerId the employer id 19 | * @return the employer bank details 20 | */ 21 | EmployerBankDetails findByEmployerId(long employerId); 22 | } 23 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/util/mappers/EmployerBankDetailsMapper.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.util.mappers; 2 | 3 | import com.lifepill.possystem.dto.EmployerBankDetailsDTO; 4 | import com.lifepill.possystem.entity.EmployerBankDetails; 5 | 6 | public class EmployerBankDetailsMapper { 7 | 8 | public static EmployerBankDetailsDTO toDTO(EmployerBankDetails employerBankDetails) { 9 | // Map fields from EmployerBankDetails to EmployerBankDetailsDTO 10 | EmployerBankDetailsDTO dto = new EmployerBankDetailsDTO(); 11 | dto.setBankName(employerBankDetails.getBankName()); 12 | return dto; 13 | } 14 | 15 | public static EmployerBankDetails toEntity(EmployerBankDetailsDTO dto) { 16 | 17 | EmployerBankDetails entity = new EmployerBankDetails(); 18 | entity.setBankName(dto.getBankName()); 19 | return entity; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/AuthService.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.service; 2 | 3 | import com.lifepill.possystem.dto.requestDTO.AuthenticationRequestDTO; 4 | import com.lifepill.possystem.dto.requestDTO.RegisterRequestDTO; 5 | import com.lifepill.possystem.dto.responseDTO.AuthenticationResponseDTO; 6 | import com.lifepill.possystem.dto.responseDTO.EmployerAuthDetailsResponseDTO; 7 | 8 | public interface AuthService { 9 | 10 | AuthenticationResponseDTO register(RegisterRequestDTO registerRequest); 11 | 12 | AuthenticationResponseDTO authenticate(AuthenticationRequestDTO request); 13 | 14 | EmployerAuthDetailsResponseDTO getEmployerDetails(String username); 15 | 16 | AuthenticationResponseDTO generateAuthenticationResponse(String employerEmail); 17 | 18 | AuthenticationResponseDTO authenticateWithCachedPin(String username, int pin); 19 | 20 | void setActiveStatus(String username, boolean b); 21 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/EmployerUpdate/EmployerUpdateAccountDetailsDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO.EmployerUpdate; 2 | 3 | import com.lifepill.possystem.entity.enums.Gender; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * The type Employer update account details dto. 12 | */ 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | @Data 16 | public class EmployerUpdateAccountDetailsDTO { 17 | private long employerId; 18 | private String employerFirstName; 19 | private String employerLastName; 20 | private Gender gender; 21 | private String employerAddress; 22 | private Date dateOfBirth; 23 | 24 | // private String cashierAddressLine1; 25 | // private String cashierAddressLine2; 26 | // private String cashierAddressCity; 27 | // private String cashierAddressZipCode; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/entity/ItemCategory.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.entity; 2 | 3 | import lombok.*; 4 | 5 | import javax.persistence.*; 6 | import java.util.Set; 7 | 8 | /** 9 | * The type Item category. 10 | */ 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | @Getter 14 | @Setter 15 | @Entity 16 | @Table(name = "item_category") 17 | public class ItemCategory { 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | @Column(name = "category_id") 21 | private long categoryId; 22 | 23 | @Column(name = "category_name", length = 100, nullable = false) 24 | private String categoryName; 25 | 26 | @Column(name = "category_description", length = 100) 27 | private String categoryDescription; 28 | 29 | @Column(name = "category_image") 30 | private String categoryImage; 31 | 32 | @OneToMany(cascade = CascadeType.ALL, mappedBy = "itemCategory") 33 | private Set items; 34 | } 35 | -------------------------------------------------------------------------------- /pos-system/.dockerignore: -------------------------------------------------------------------------------- 1 | # ============================================ 2 | # Docker Ignore File 3 | # ============================================ 4 | 5 | # Git 6 | .git 7 | .gitignore 8 | 9 | # IDE 10 | .idea/ 11 | *.iml 12 | .vscode/ 13 | *.swp 14 | *.swo 15 | 16 | # Build outputs 17 | target/ 18 | !target/*.jar 19 | 20 | # Logs 21 | *.log 22 | logs/ 23 | 24 | # Environment files (use docker-compose environment instead) 25 | .env 26 | .env.local 27 | .env.*.local 28 | 29 | # Docker 30 | Dockerfile* 31 | docker-compose*.yml 32 | .docker/ 33 | 34 | # Documentation 35 | *.md 36 | !README.md 37 | docs/ 38 | 39 | # Test files 40 | src/test/ 41 | 42 | # Maven wrapper (we use Maven image) 43 | .mvn/ 44 | mvnw 45 | mvnw.cmd 46 | 47 | # Temporary files 48 | *.tmp 49 | *.temp 50 | .DS_Store 51 | Thumbs.db 52 | 53 | # CI/CD 54 | .github/ 55 | .gitlab-ci.yml 56 | Jenkinsfile 57 | qodana.* 58 | 59 | # Data directories 60 | data/ 61 | uploads/ 62 | 63 | # Other 64 | *.bak 65 | *.orig 66 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/EmployerNewDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | 4 | import com.lifepill.possystem.entity.enums.Gender; 5 | import com.lifepill.possystem.entity.enums.Role; 6 | import lombok.*; 7 | 8 | import java.util.Date; 9 | 10 | @Getter 11 | @Setter 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | @ToString 15 | public class EmployerNewDTO { 16 | private String employerNicName; 17 | private String employerFirstName; 18 | private String employerLastName; 19 | private String employerPassword; 20 | private String employerEmail; 21 | private String employerPhone; 22 | private String employerAddress; 23 | private double employerSalary; 24 | private String employerNic; 25 | private boolean isActiveStatus; 26 | private Gender gender; 27 | private Date dateOfBirth; 28 | private Role role; 29 | private int pin; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [pramithamj] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: lpramithamm # Replace with a single Buy Me a Coffee username 14 | thanks_dev: # Replace with a single thanks.dev username 15 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 16 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/helper/SaveImageHelper.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.helper; 2 | 3 | import org.springframework.util.StringUtils; 4 | import org.springframework.web.multipart.MultipartFile; 5 | 6 | import java.io.IOException; 7 | import java.util.Objects; 8 | 9 | /** 10 | * The type Save image helper. 11 | */ 12 | public class SaveImageHelper { 13 | 14 | /** 15 | * Save image byte [ ]. 16 | * 17 | * @param image the image 18 | * @return the byte [ ] 19 | */ 20 | public static byte[] saveImage(MultipartFile image) { 21 | if (image != null && !image.isEmpty()) { 22 | try { 23 | String fileName = StringUtils.cleanPath(Objects.requireNonNull(image.getOriginalFilename())); 24 | return image.getBytes(); 25 | } catch (IOException e) { 26 | throw new RuntimeException("Failed to save image", e); 27 | } 28 | } 29 | return null; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/controller/secured/AdminController.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.controller.secured; 2 | import org.springframework.security.access.prepost.PreAuthorize; 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @RequestMapping("/lifepill/v1/admin") 10 | @PreAuthorize("hasRole('OWNER')") 11 | public class AdminController { 12 | 13 | @GetMapping("/owner") 14 | // @PreAuthorize("hasAuthority('owner:read')") 15 | public String TestOwner() { 16 | return "Secured Endpoint :: GET - Owner controller"; 17 | } 18 | 19 | @PostMapping("/post") 20 | // @PreAuthorize("hasAuthority('owner:create')") 21 | public String TestPostOwner() { 22 | return "Secured Endpoint :: POST - Owner controller"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/EmployerS3DTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | import com.lifepill.possystem.entity.enums.Gender; 4 | import com.lifepill.possystem.entity.enums.Role; 5 | import lombok.*; 6 | 7 | import java.util.Date; 8 | 9 | @Getter 10 | @Setter 11 | @ToString 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class EmployerS3DTO { 15 | private long employerId; 16 | private long branchId; 17 | private String employerNicName; 18 | private String employerFirstName; 19 | private String employerLastName; 20 | private String employerPassword; 21 | private String employerEmail; 22 | private String employerPhone; 23 | private String employerAddress; 24 | private double employerSalary; 25 | private String employerNic; 26 | private boolean isActiveStatus; 27 | private Gender gender; 28 | private Date dateOfBirth; 29 | private Role role; 30 | private int pin; 31 | private String profileImageUrl; 32 | } 33 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/SMSService.java: -------------------------------------------------------------------------------- 1 | /* 2 | package com.lifepill.possystem.service; 3 | 4 | import com.twilio.Twilio; 5 | import com.twilio.rest.api.v2010.account.Message; 6 | import com.twilio.type.PhoneNumber; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.stereotype.Service; 9 | 10 | import javax.annotation.PostConstruct; 11 | 12 | @Service 13 | public class SMSService { 14 | 15 | @Value("${twilio.accountSid}") 16 | private String accountSid; 17 | 18 | @Value("${twilio.authToken}") 19 | private String authToken; 20 | 21 | @Value("${twilio.fromPhoneNumber}") 22 | private String fromPhoneNumber; 23 | 24 | @PostConstruct 25 | public void init() { 26 | Twilio.init(accountSid, authToken); 27 | } 28 | 29 | public void sendSms(String toPhoneNumber, String message) { 30 | Message.creator(new PhoneNumber(toPhoneNumber), new PhoneNumber(fromPhoneNumber), message).create(); 31 | } 32 | } 33 | */ 34 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/MedicineGetResponseDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | 3 | import com.lifepill.possystem.dto.BranchDTO; 4 | import com.lifepill.possystem.dto.ItemCategoryDTO; 5 | import com.lifepill.possystem.entity.enums.MeasuringUnitType; 6 | import lombok.*; 7 | 8 | /** 9 | * The type Medicine get response dto. 10 | */ 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | public class MedicineGetResponseDTO { 17 | private long itemId; 18 | private BranchDTO branchDTO; 19 | private String itemName; 20 | private double sellingPrice; 21 | private String itemBarCode; 22 | private MeasuringUnitType measuringUnitType; 23 | private ItemCategoryDTO itemCategoryDTO; // Added ItemCategoryDTO field 24 | private String itemImage; 25 | private String itemDescription; 26 | private boolean isStock; 27 | private boolean isOpen; // branch open or closed 28 | private long Rate; // out of 5 29 | 30 | } 31 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/EmployerDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | import com.lifepill.possystem.entity.enums.Gender; 4 | import com.lifepill.possystem.entity.enums.Role; 5 | import lombok.*; 6 | 7 | import java.util.Date; 8 | 9 | /** 10 | * The type Employer dto. 11 | */ 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | @Data 15 | public class EmployerDTO { 16 | private long employerId; 17 | private long branchId; 18 | private String employerNicName; 19 | private String employerFirstName; 20 | private String employerLastName; 21 | private String employerPassword; 22 | private String employerEmail; 23 | private String employerPhone; 24 | private String employerAddress; 25 | private double employerSalary; 26 | private String employerNic; 27 | private boolean isActiveStatus; 28 | private Gender gender; 29 | private Date dateOfBirth; 30 | private Role role; 31 | private int pin; 32 | private byte[] profileImage; 33 | //private Order order; 34 | 35 | } -------------------------------------------------------------------------------- /pos-system/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM maven:3.9.6-eclipse-temurin-17-alpine AS builder 2 | 3 | WORKDIR /build 4 | 5 | COPY pom.xml . 6 | 7 | RUN mvn dependency:go-offline -B 8 | 9 | COPY src ./src 10 | 11 | RUN mvn clean package -DskipTests -B 12 | 13 | FROM eclipse-temurin:17-jre-alpine AS runtime 14 | 15 | LABEL maintainer="LifePill Development Team" 16 | LABEL version="1.0.0" 17 | LABEL description="LifePill POS System Backend Service" 18 | 19 | RUN addgroup -g 1001 -S appgroup && \ 20 | adduser -u 1001 -S appuser -G appgroup 21 | 22 | WORKDIR /app 23 | 24 | RUN mkdir -p /app/uploads /app/logs && \ 25 | chown -R appuser:appgroup /app 26 | 27 | COPY --from=builder --chown=appuser:appgroup /build/target/*.jar app.jar 28 | 29 | USER appuser 30 | 31 | EXPOSE 8080 32 | 33 | HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ 34 | CMD wget --no-verbose --tries=1 --spider http://localhost:8080/actuator/health || exit 1 35 | 36 | ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -XX:+UseG1GC" 37 | 38 | ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"] -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/EmployerAuthDetailsResponseDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | 3 | import com.lifepill.possystem.entity.enums.Gender; 4 | import com.lifepill.possystem.entity.enums.Role; 5 | import lombok.*; 6 | 7 | import java.util.Date; 8 | 9 | /** 10 | * The type Employer auth details response dto. 11 | */ 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | @Getter 15 | @Setter 16 | @ToString 17 | public class EmployerAuthDetailsResponseDTO { 18 | private long employerId; 19 | private int branchId; 20 | private String employerNicName; 21 | private String employerFirstName; 22 | private String employerLastName; 23 | private String employerEmail; 24 | private String employerPhone; 25 | private String employerAddress; 26 | private double employerSalary; 27 | private String employerNic; 28 | private boolean isActiveStatus; 29 | private Gender gender; 30 | private Date dateOfBirth; 31 | private Role role; 32 | private int pin; 33 | private byte[] profileImage; 34 | } 35 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/EmployerWithoutImageDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | import com.lifepill.possystem.entity.enums.Gender; 4 | import com.lifepill.possystem.entity.enums.Role; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.Date; 10 | 11 | /** 12 | * The type Employer without image dto. 13 | */ 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @Data 17 | public class EmployerWithoutImageDTO { 18 | private long employerId; 19 | private long branchId; 20 | private String employerNicName; 21 | private String employerFirstName; 22 | private String employerLastName; 23 | private String employerPassword; 24 | private String employerEmail; 25 | private String employerPhone; 26 | private String employerAddress; 27 | private double employerSalary; 28 | private String employerNic; 29 | private boolean isActiveStatus; 30 | private Gender gender; 31 | private Date dateOfBirth; 32 | private Role role; 33 | private int pin; 34 | //private Order order; 35 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/entity/enums/MeasuringUnitType.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.entity.enums; 2 | 3 | /** 4 | * The enum Measuring unit type. 5 | */ 6 | public enum MeasuringUnitType { 7 | /** 8 | * Kilo gram measuring unit type. 9 | */ 10 | KILO_GRAM, 11 | /** 12 | * Gram measuring unit type. 13 | */ 14 | GRAM, 15 | /** 16 | * Milli gram measuring unit type. 17 | */ 18 | MILLI_GRAM, 19 | /** 20 | * Liter measuring unit type. 21 | */ 22 | LITER, 23 | /** 24 | * Milli liter measuring unit type. 25 | */ 26 | MILLI_LITER, 27 | /** 28 | * Micro gram measuring unit type. 29 | */ 30 | MICRO_GRAM, 31 | /** 32 | * Drops measuring unit type. 33 | */ 34 | DROPS, 35 | /** 36 | * Tablets measuring unit type. 37 | */ 38 | TABLETS, 39 | /** 40 | * Capsule measuring unit type. 41 | */ 42 | CAPSULE, 43 | /** 44 | * Spray measuring unit type. 45 | */ 46 | SPRAY, 47 | /** 48 | * Number measuring unit type. 49 | */ 50 | NUMBER 51 | } 52 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/EmployerWithBankDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | import com.lifepill.possystem.entity.EmployerBankDetails; 4 | import com.lifepill.possystem.entity.enums.Gender; 5 | import com.lifepill.possystem.entity.enums.Role; 6 | import lombok.*; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * The type Employer dto. 12 | */ 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | @Getter 16 | @Setter 17 | @ToString 18 | public class EmployerWithBankDTO { 19 | private long employerId; 20 | private long branchId; 21 | private String employerNicName; 22 | private String employerFirstName; 23 | private String employerLastName; 24 | private String employerEmail; 25 | private String employerPhone; 26 | private String employerAddress; 27 | private double employerSalary; 28 | private String employerNic; 29 | private boolean isActiveStatus; 30 | private Gender gender; 31 | private Date dateOfBirth; 32 | private Role role; 33 | private int pin; 34 | private byte[] profileImage; 35 | 36 | private EmployerBankDetails employerBankDetails; 37 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/RegisterRequestDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO; 2 | 3 | import com.lifepill.possystem.entity.enums.Gender; 4 | import com.lifepill.possystem.entity.enums.Role; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import java.util.Date; 11 | 12 | /** 13 | * The type Register request dto. 14 | */ 15 | @Data 16 | @Builder 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | public class RegisterRequestDTO { 20 | private long employerId; 21 | private long branchId; 22 | private String employerNicName; 23 | private String employerFirstName; 24 | private String employerLastName; 25 | private String employerPassword; 26 | private String employerEmail; 27 | private String employerPhone; 28 | private String employerAddress; 29 | private double employerSalary; 30 | private String employerNic; 31 | private boolean isActiveStatus; 32 | private Gender gender; 33 | private Date dateOfBirth; 34 | private Role role; 35 | private int pin; 36 | } 37 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/EmployerUpdate/EmployerAllDetailsUpdateDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO.EmployerUpdate; 2 | 3 | import com.lifepill.possystem.entity.enums.Gender; 4 | import com.lifepill.possystem.entity.enums.Role; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.Date; 10 | 11 | /** 12 | * The type Employer all details update dto. 13 | */ 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @Data 17 | public class EmployerAllDetailsUpdateDTO { 18 | // private long cashierId; 19 | private long branchId; 20 | private String employerNicName; 21 | private String employerFirstName; 22 | private String employerLastName; 23 | private String employerPassword; 24 | private String employerEmail; 25 | private String employerPhone; 26 | private String employerAddress; 27 | private double employerSalary; 28 | private String employerNic; 29 | private boolean isActiveStatus; 30 | private Gender gender; 31 | private Date dateOfBirth; 32 | private Role role; 33 | private int pin; 34 | 35 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/entity/enums/Permission.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.entity.enums; 2 | 3 | 4 | import lombok.Getter; 5 | import lombok.RequiredArgsConstructor; 6 | 7 | /** 8 | * The enum Permission. 9 | */ 10 | @Getter 11 | @RequiredArgsConstructor 12 | public enum Permission { 13 | 14 | /** 15 | * Owner read permission. 16 | */ 17 | OWNER_READ("owner:read"), 18 | /** 19 | * Owner create permission. 20 | */ 21 | OWNER_CREATE("owner:create"), 22 | /** 23 | * Cashier read permission. 24 | */ 25 | CASHIER_READ("cashier:read"), 26 | /** 27 | * Cashier create permission. 28 | */ 29 | CASHIER_CREATE("cashier:create"), 30 | /** 31 | * Manager read permission. 32 | */ 33 | MANAGER_READ("manager:read"), 34 | /** 35 | * Manager create permission. 36 | */ 37 | MANAGER_CREATE("manager:create"), 38 | /** 39 | * Other read permission. 40 | */ 41 | OTHER_READ("other:read"), 42 | /** 43 | * Other create permission. 44 | */ 45 | OTHER_CREATE("other:create") 46 | ; 47 | 48 | private final String permission; 49 | } -------------------------------------------------------------------------------- /pos-system/update_and_deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Function to increment the version number 4 | increment_version() { 5 | local version=$1 6 | local major minor patch 7 | IFS='.' read -r major minor patch <<< "$version" 8 | patch=$((patch + 1)) 9 | echo "$major.$minor.$patch" 10 | } 11 | 12 | # Read the current version from a file or set it manually 13 | version_file="version.txt" 14 | if [[ -f $version_file ]]; then 15 | current_version=$(cat $version_file) 16 | else 17 | current_version="0.0.0" # Default version if no file is found 18 | fi 19 | 20 | # Increment the version 21 | new_version=$(increment_version $current_version) 22 | echo "Updating version from $current_version to $new_version" 23 | 24 | # Save the new version to the file 25 | echo $new_version > $version_file 26 | 27 | # Build the new Docker image with the new tag 28 | docker build -t pos-system:$new_version . 29 | 30 | # Update the docker-compose.yml file with the new tag 31 | sed -i "s/pos-system:.*$/pos-system:$new_version/" docker-compose.yml 32 | 33 | # Bring up the services with Docker Compose 34 | docker-compose down 35 | docker-compose up -d --build 36 | 37 | echo "Deployment complete with tag pos-system:$new_version" -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/util/mappers/EmployerAuthDetailsResponseDTOToStringConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | package com.lifepill.possystem.util.mappers; 3 | 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import com.lifepill.possystem.dto.responseDTO.EmployerAuthDetailsResponseDTO; 7 | import org.springframework.core.convert.converter.Converter; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class EmployerAuthDetailsResponseDTOToStringConverter implements Converter { 12 | 13 | private final ObjectMapper objectMapper; 14 | 15 | public EmployerAuthDetailsResponseDTOToStringConverter(ObjectMapper objectMapper) { 16 | this.objectMapper = objectMapper; 17 | } 18 | 19 | @Override 20 | public String convert(EmployerAuthDetailsResponseDTO source) { 21 | try { 22 | return objectMapper.writeValueAsString(source); 23 | } catch (JsonProcessingException e) { 24 | throw new RuntimeException("Error converting EmployerAuthDetailsResponseDTO to JSON string", e); 25 | } 26 | } 27 | } 28 | */ 29 | -------------------------------------------------------------------------------- /pos-system/.env.docker: -------------------------------------------------------------------------------- 1 | # LifePill POS System - Docker Environment Variables 2 | # Copy this file and customize for your environment 3 | # Usage: docker-compose --env-file .env.docker up --build -d 4 | 5 | # PostgreSQL Configuration 6 | POSTGRES_DB=lifepill 7 | POSTGRES_USER=postgres 8 | POSTGRES_PASSWORD=postgres123 9 | 10 | # Spring Security 11 | SPRING_SECURITY_USERNAME=admin 12 | SPRING_SECURITY_PASSWORD=admin123 13 | 14 | # JWT Configuration 15 | JWT_SECRET=jwt-secret 16 | JWT_EXPIRATION=86400000 17 | 18 | # Mail Configuration 19 | SPRING_MAIL_HOST=smtp.gmail.com 20 | SPRING_MAIL_PORT=587 21 | SPRING_USER_NAME=your-email@gmail.com 22 | SPRING_PASSWORD=your-app-password 23 | 24 | # AWS S3 Configuration 25 | AWS_ACCESS_KEY=your-aws-access-key 26 | AWS_SECRET_KEY=your-aws-secret-key 27 | AWS_S3_BUCKET=your-bucket-name 28 | AWS_REGION=us-east-1 29 | 30 | # CORS Configuration 31 | CORS_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:5173,http://localhost:80 32 | CORS_ALLOWED_METHODS=GET,POST,PUT,DELETE,OPTIONS 33 | CORS_ALLOWED_HEADERS=Authorization,Cache-Control,Content-Type 34 | CORS_ALLOW_CREDENTIALS=true 35 | CORS_MAX_AGE=3600 36 | 37 | # Grafana Configuration 38 | GRAFANA_USER=admin 39 | GRAFANA_PASSWORD=admin123 40 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/ItemSearchRequestDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Request DTO for item search operations. 10 | */ 11 | @Data 12 | @Builder 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class ItemSearchRequestDTO { 16 | 17 | private String query; // Main search query 18 | private String categoryName; // Filter by category 19 | private String supplierName; // Filter by supplier 20 | private Long branchId; // Filter by branch 21 | private Boolean inStock; // Filter by stock status 22 | private Boolean isDiscounted; // Filter by discount status 23 | private Double minPrice; // Minimum price filter 24 | private Double maxPrice; // Maximum price filter 25 | 26 | @Builder.Default 27 | private int page = 0; 28 | 29 | @Builder.Default 30 | private int size = 20; 31 | 32 | @Builder.Default 33 | private String sortBy = "itemName"; 34 | 35 | @Builder.Default 36 | private String sortOrder = "asc"; 37 | } 38 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/entity/PaymentDetails.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.persistence.*; 8 | import java.util.Date; 9 | 10 | /** 11 | * The type Payment details. 12 | */ 13 | @Entity 14 | @Table(name = "payment_details") 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Data 18 | public class PaymentDetails { 19 | 20 | @Id 21 | @Column(name = "payment_id") 22 | @GeneratedValue(strategy = GenerationType.AUTO) 23 | private long paymentId; 24 | @Column(name = "payment_method") 25 | private String paymentMethod; 26 | @Column(name = "payment_amount") 27 | private double paymentAmount; 28 | @Column(name = "payment_date") 29 | private Date paymentDate; 30 | @Column(name = "payment_notes",nullable = true) 31 | private String paymentNotes; 32 | @Column(name = "payment_discount",nullable = true) 33 | private double paymentDiscount; 34 | @Column(name = "paid_amount") 35 | private double paidAmount; 36 | 37 | @ManyToOne 38 | @JoinColumn(name = "order_id", nullable = false) 39 | private Order orders; 40 | } 41 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/config/ModelMapperConfig.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.config; 2 | 3 | import com.lifepill.possystem.dto.requestDTO.ItemSaveRequestCategoryDTO; 4 | import com.lifepill.possystem.entity.ItemCategory; 5 | import org.modelmapper.ModelMapper; 6 | import org.modelmapper.convention.MatchingStrategies; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | /** 11 | * Configuration class for ModelMapper. 12 | */ 13 | @Configuration 14 | public class ModelMapperConfig { 15 | 16 | /** 17 | * Configures and initializes the ModelMapper bean. 18 | * 19 | * @return Initialized ModelMapper instance. 20 | */ 21 | @Bean 22 | public ModelMapper modelMapper() { 23 | ModelMapper modelMapper = new ModelMapper(); 24 | modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); 25 | 26 | // Add explicit mapping for categoryId 27 | modelMapper.typeMap(ItemSaveRequestCategoryDTO.class, ItemCategory.class) 28 | .addMapping(ItemSaveRequestCategoryDTO::getCategoryId, ItemCategory::setCategoryId); 29 | 30 | return modelMapper; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/entity/OrderDetails.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.entity; 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeId; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import org.hibernate.annotations.TypeDef; 8 | import org.hibernate.annotations.TypeDefs; 9 | 10 | import javax.persistence.*; 11 | 12 | /** 13 | * The type Order details. 14 | */ 15 | @Entity 16 | @Table(name = "order_details") 17 | @TypeDefs({ 18 | @TypeDef(name = "json",typeClass = JsonTypeId.class) 19 | }) 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | @Data 23 | public class OrderDetails { 24 | @Id 25 | @Column(name = "order_details_id",length = 45) 26 | @GeneratedValue(strategy = GenerationType.AUTO) 27 | private int orderDetailsId; 28 | 29 | @Column(name = "name",length = 100,nullable = false) 30 | private String name; 31 | 32 | @Column(name = "amount",length = 100,nullable = false) 33 | private Double amount; 34 | 35 | @ManyToOne 36 | @JoinColumn(name = "order_id", nullable = false) 37 | private Order orders; 38 | 39 | @ManyToOne 40 | @JoinColumn(name = "item_id",nullable = false) 41 | private Item items; 42 | 43 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/entity/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.entity; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.ToString; 6 | import org.springframework.data.annotation.CreatedBy; 7 | import org.springframework.data.annotation.CreatedDate; 8 | import org.springframework.data.annotation.LastModifiedBy; 9 | import org.springframework.data.annotation.LastModifiedDate; 10 | import org.springframework.data.jpa.domain.support.AuditingEntityListener; 11 | 12 | import javax.persistence.Column; 13 | import javax.persistence.EntityListeners; 14 | import javax.persistence.MappedSuperclass; 15 | import java.time.LocalDateTime; 16 | 17 | /** 18 | * The type Base entity. 19 | */ 20 | @MappedSuperclass 21 | @EntityListeners(AuditingEntityListener.class) 22 | @Getter 23 | @Setter 24 | @ToString 25 | public class BaseEntity { 26 | 27 | @CreatedDate 28 | @Column(updatable = false) 29 | private LocalDateTime createdAt; 30 | 31 | @CreatedBy 32 | @Column(updatable = false) 33 | private String createdBy; 34 | 35 | @LastModifiedDate 36 | @Column(insertable = false) 37 | private LocalDateTime updatedAt; 38 | 39 | @LastModifiedBy 40 | @Column(insertable = false) 41 | private String updatedBy; 42 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/config/S3Config.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.config; 2 | 3 | import com.amazonaws.auth.AWSStaticCredentialsProvider; 4 | import com.amazonaws.auth.BasicAWSCredentials; 5 | import com.amazonaws.regions.Regions; 6 | import com.amazonaws.services.s3.AmazonS3; 7 | import com.amazonaws.services.s3.AmazonS3ClientBuilder; 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | @Configuration 13 | public class S3Config { 14 | 15 | @Value("${aws.access.key}") 16 | private String awsAccessKey; 17 | 18 | @Value("${aws.secret.key}") 19 | private String awsSecretKey; 20 | 21 | @Value("${aws.region}") 22 | private String awsRegion; 23 | 24 | @Bean 25 | public AmazonS3 s3client() { 26 | 27 | BasicAWSCredentials awsCredentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey); 28 | 29 | return AmazonS3ClientBuilder.standard() 30 | .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) 31 | .withRegion(Regions.fromName(awsRegion)) // This field if not exist throws an exception 32 | .build(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/ItemDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto; 2 | 3 | import com.lifepill.possystem.entity.enums.MeasuringUnitType; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * The type Item dto. 12 | */ 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | @Data 16 | public class ItemDTO { 17 | private int itemId; 18 | private String itemName; 19 | private double sellingPrice; 20 | private String itemBarCode; 21 | private Date supplyDate; 22 | private double supplierPrice; 23 | private boolean isFreeIssued; 24 | private boolean isDiscounted; 25 | private String itemManufacture; 26 | private double itemQuantity; 27 | private String itemCategory; 28 | private boolean isStock; 29 | private MeasuringUnitType measuringUnitType; 30 | private Date manufactureDate; 31 | private Date expireDate; 32 | private Date purchaseDate; 33 | private String warrantyPeriod; 34 | private String rackNumber; 35 | private double discountedPrice; 36 | private double discountedPercentage; 37 | private String warehouseName; 38 | private boolean isSpecialCondition; 39 | private String itemImage; 40 | private String itemDescription; 41 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/ItemSaveRequestDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO; 2 | 3 | import com.lifepill.possystem.entity.enums.MeasuringUnitType; 4 | import lombok.*; 5 | 6 | import java.util.Date; 7 | 8 | /** 9 | * The type Item save request dto. 10 | */ 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | @Data 14 | public class ItemSaveRequestDTO { 15 | private long itemId; 16 | private long branchId; 17 | private String itemName; 18 | private double sellingPrice; 19 | private String itemBarCode; 20 | private Date supplyDate; 21 | private double supplierPrice; 22 | private boolean isFreeIssued; 23 | private boolean isDiscounted; 24 | private String itemManufacture; 25 | private double itemQuantity; 26 | private boolean isStock; 27 | private MeasuringUnitType measuringUnitType; 28 | private Date manufactureDate; 29 | private Date expireDate; 30 | private Date purchaseDate; 31 | private String warrantyPeriod; 32 | private String rackNumber; 33 | private double discountedPrice; 34 | private double discountedPercentage; 35 | private String warehouseName; 36 | private boolean isSpecialCondition; 37 | private String itemImage; 38 | private String itemDescription; 39 | private long categoryId; 40 | private long supplierId; 41 | } 42 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/ItemUpdateDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO; 2 | 3 | import com.lifepill.possystem.entity.enums.MeasuringUnitType; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * The type Item update dto. 12 | */ 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | @Data 16 | public class ItemUpdateDTO { 17 | private long itemId; 18 | private String itemName; 19 | private double sellingPrice; 20 | private String itemBarCode; 21 | private Date supplyDate; 22 | private double supplierPrice; 23 | private boolean isFreeIssued; 24 | private boolean isDiscounted; 25 | private String itemManufacture; 26 | private double itemQuantity; 27 | // private String itemCategory; 28 | private boolean isStock; 29 | private MeasuringUnitType measuringUnitType; 30 | private Date manufactureDate; 31 | private Date expireDate; 32 | private Date purchaseDate; 33 | private String warrantyPeriod; 34 | private String rackNumber; 35 | private double discountedPrice; 36 | private double discountedPercentage; 37 | private String warehouseName; 38 | private boolean isSpecialCondition; 39 | private String itemImage; 40 | private String itemDescription; 41 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/entity/EmployerBankDetails.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.persistence.*; 8 | import java.util.Set; 9 | 10 | /** 11 | * The type Employer bank details. 12 | */ 13 | @Entity 14 | @Data 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | @Table(name = "employer_bankdetails") 18 | public class EmployerBankDetails { 19 | @Id 20 | @GeneratedValue(strategy = GenerationType.IDENTITY) 21 | @Column(name = "employer_bank_details_id") 22 | private long employerBankDetailsId; 23 | @Column(name = "bank_name") 24 | private String bankName; 25 | @Column(name = "bank_branch_name",nullable = true) 26 | private String bankBranchName; 27 | @Column(name = "bank_account_number") 28 | private String bankAccountNumber; 29 | @Column(name = "employer_description") 30 | private String employerDescription; 31 | @Column(name = "cashier_monthly_payment") 32 | private double monthlyPayment; 33 | @Column(name = "payment_status",nullable = true) 34 | private Boolean monthlyPaymentStatus; 35 | @Column(name = "employeer_id") 36 | private long employerId; 37 | @OneToMany(cascade = CascadeType.ALL, mappedBy = "employerBankDetails") 38 | private Set employers; 39 | } 40 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/ItemGetResponseDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | 3 | import com.lifepill.possystem.entity.enums.MeasuringUnitType; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * The type Item get response dto. 12 | */ 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | @Data 16 | public class ItemGetResponseDTO { 17 | 18 | private long itemId; 19 | private long branchId; 20 | private String itemName; 21 | private double sellingPrice; 22 | private String itemBarCode; 23 | private Date supplyDate; 24 | private double supplierPrice; 25 | private boolean isFreeIssued; 26 | private boolean isDiscounted; 27 | private String itemManufacture; 28 | private double itemQuantity; 29 | private String itemCategoryName; 30 | private boolean isStock; 31 | private MeasuringUnitType measuringUnitType; 32 | private Date manufactureDate; 33 | private Date expireDate; 34 | private Date purchaseDate; 35 | private String warrantyPeriod; 36 | private String rackNumber; 37 | private double discountedPrice; 38 | private double discountedPercentage; 39 | private String warehouseName; 40 | private boolean isSpecialCondition; 41 | private String itemImage; 42 | private String itemDescription; 43 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/util/mappers/EmployerMapper.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.util.mappers; 2 | 3 | import com.lifepill.possystem.dto.EmployerBankDetailsDTO; 4 | import com.lifepill.possystem.entity.EmployerBankDetails; 5 | import org.springframework.stereotype.Component; 6 | 7 | @Component 8 | public class EmployerMapper { 9 | public EmployerBankDetails mapBankDetailsDTOToEntity(EmployerBankDetailsDTO bankDetailsDTO) { 10 | if (bankDetailsDTO == null) { 11 | return null; 12 | } 13 | EmployerBankDetails employerBankDetails = new EmployerBankDetails(); 14 | employerBankDetails.setBankName(bankDetailsDTO.getBankName()); 15 | employerBankDetails.setBankBranchName(bankDetailsDTO.getBankBranchName()); 16 | employerBankDetails.setBankAccountNumber(bankDetailsDTO.getBankAccountNumber()); 17 | employerBankDetails.setEmployerDescription(bankDetailsDTO.getEmployerDescription()); 18 | employerBankDetails.setMonthlyPayment(bankDetailsDTO.getMonthlyPayment()); 19 | employerBankDetails.setMonthlyPaymentStatus(bankDetailsDTO.getMonthlyPaymentStatus()); 20 | employerBankDetails.setEmployerId(bankDetailsDTO.getEmployerId()); 21 | employerBankDetails.setEmployerBankDetailsId(bankDetailsDTO.getEmployerBankDetailsId()); 22 | // employerBankDetails.setEmployers(bankDetailsDTO.getEmployers()); 23 | return employerBankDetails; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/ItemSearchResponseDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Response DTO for OpenSearch search results. 12 | */ 13 | @Data 14 | @Builder 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | public class ItemSearchResponseDTO { 18 | 19 | private List hits; 20 | private long totalHits; 21 | private long took; // time in milliseconds 22 | private int page; 23 | private int size; 24 | private int totalPages; 25 | 26 | @Data 27 | @Builder 28 | @NoArgsConstructor 29 | @AllArgsConstructor 30 | public static class ItemSearchHit { 31 | private Long itemId; 32 | private String itemName; 33 | private String itemBarCode; 34 | private String itemManufacture; 35 | private String itemDescription; 36 | private double sellingPrice; 37 | private double itemQuantity; 38 | private boolean stock; 39 | private boolean discounted; 40 | private double discountedPrice; 41 | private String categoryName; 42 | private String supplierName; 43 | private String itemImage; 44 | private Long branchId; 45 | private double score; // relevance score from OpenSearch 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/ItemGetAllResponseDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | 3 | import com.lifepill.possystem.entity.enums.MeasuringUnitType; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * The type Item get all response dto. 12 | */ 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | @Data 16 | public class ItemGetAllResponseDTO { 17 | private long itemId; 18 | private long brandId; 19 | private String itemName; 20 | private double sellingPrice; 21 | private String itemBarCode; 22 | private Date supplyDate; 23 | private double supplierPrice; 24 | private boolean isFreeIssued; 25 | private boolean isDiscounted; 26 | private String itemManufacture; 27 | private double itemQuantity; 28 | private String itemCategoryName; 29 | private long itemCategoryId; 30 | private boolean isStock; 31 | private MeasuringUnitType measuringUnitType; 32 | private Date manufactureDate; 33 | private Date expireDate; 34 | private Date purchaseDate; 35 | private String warrantyPeriod; 36 | private String rackNumber; 37 | private double discountedPrice; 38 | private double discountedPercentage; 39 | private String warehouseName; 40 | private boolean isSpecialCondition; 41 | private String itemImage; 42 | private String itemDescription; 43 | } 44 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/entity/Supplier.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.entity; 2 | 3 | import lombok.*; 4 | 5 | import javax.persistence.*; 6 | import java.util.Set; 7 | 8 | /** 9 | * The type Supplier. 10 | */ 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | @Getter 14 | @Setter 15 | @Entity 16 | @ToString 17 | @Builder 18 | @Table(name = "supplier") 19 | public class Supplier extends BaseEntity { 20 | @Id 21 | @Column(name = "supplier_id", length = 45) 22 | @GeneratedValue(strategy = GenerationType.AUTO) 23 | private long supplierId; 24 | 25 | @Column(name = "supplier_name", length = 100) 26 | private String supplierName; 27 | 28 | @Column(name = "supplier_address", length = 100) 29 | private String supplierAddress; 30 | 31 | @Column(name = "supplier_phone", length = 12) 32 | private String supplierPhone; 33 | 34 | @Column(name = "supplier_email", length = 50) 35 | private String supplierEmail; 36 | 37 | @Column(name = "supplier_description", length = 100) 38 | private String supplierDescription; 39 | 40 | @Column(name = "supplier_image") 41 | private String supplierImage; 42 | 43 | @OneToMany(cascade = CascadeType.ALL, mappedBy = "supplier") 44 | private Set items; 45 | 46 | @Column(name = "supplier_rating") 47 | private String supplierRating; 48 | 49 | @ManyToOne 50 | @JoinColumn(name = "company_id", nullable = true) 51 | private SupplierCompany supplierCompany; 52 | 53 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/controller/OwnerController.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.controller; 2 | 3 | import com.lifepill.possystem.dto.EmployerDTO; 4 | import com.lifepill.possystem.entity.enums.Role; 5 | import com.lifepill.possystem.service.EmployerService; 6 | import lombok.AllArgsConstructor; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.PathVariable; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * Controller class for managing owner-related endpoints. 18 | */ 19 | @RestController 20 | @RequestMapping("lifepill/v1/owner") 21 | @AllArgsConstructor 22 | public class OwnerController { 23 | 24 | private EmployerService employerService; 25 | 26 | /** 27 | * Retrieves all employers by role. 28 | * 29 | * @param role The role of the employers to retrieve. 30 | * @return ResponseEntity containing a list of EmployerDTOs with the specified role. 31 | */ 32 | @GetMapping("/byRole/{role}") 33 | public ResponseEntity> getAllEmployerByRole(@PathVariable Role role) { 34 | List cashiers = employerService.getAllEmployerByRole(role); 35 | return new ResponseEntity<>(cashiers, HttpStatus.OK); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/entity/SupplierCompany.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.entity; 2 | 3 | import lombok.*; 4 | 5 | import javax.persistence.*; 6 | import java.util.Set; 7 | 8 | /** 9 | * The type Supplier company. 10 | */ 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | @Getter 14 | @Setter 15 | @ToString 16 | @Entity 17 | @Table(name = "supplierCompany") 18 | public class SupplierCompany extends BaseEntity{ 19 | 20 | @Id 21 | @Column(name = "company_id", length = 45) 22 | @GeneratedValue(strategy = GenerationType.AUTO) 23 | private long CompanyId; 24 | @Column(name = "company_name", length = 100) 25 | private String CompanyName; 26 | @Column(name = "company_address", length = 100) 27 | private String CompanyAddress; 28 | @Column(name = "company_contact", length = 12) 29 | private String CompanyContact; 30 | @Column(name = "company_email", length = 50) 31 | private String CompanyEmail; 32 | @Column(name = "company_description") 33 | private String CompanyDescription; 34 | @Column(name = "company_image") 35 | private String CompanyStatus; 36 | @Column(name = "company_status") 37 | private String CompanyRating; 38 | @Column(name = "company_bank") 39 | private String CompanyBank; 40 | @Column(name = "company_account_number") 41 | private String CompanyAccountNumber; 42 | 43 | @OneToMany(cascade = CascadeType.ALL, mappedBy = "supplierCompany") 44 | private Set suppliers; 45 | } 46 | -------------------------------------------------------------------------------- /pos-system/.env.example: -------------------------------------------------------------------------------- 1 | # Server Port Configuration 2 | SERVER_PORT=8080 3 | 4 | # Spring Security Configuration 5 | SPRING_SECURITY_USERNAME=admin 6 | SPRING_SECURITY_PASSWORD=admin_password 7 | 8 | # Mail Configuration 9 | SPRING_MAIL_HOST=smtp.gmail.com 10 | SPRING_MAIL_PORT=587 11 | 12 | # Sender Email Configuration 13 | SPRING_USER_NAME=your-email-password 14 | SPRING_PASSWORD=email-app-password 15 | 16 | # Database Configuration 17 | DATABASE_URL=jdbc:postgresql://:/ 18 | DATABASE_USERNAME=postgres 19 | DATABASE_PASSWORD=db-password 20 | 21 | # Hibernate Configuration 22 | JDBC_SHOW_SQL=true 23 | HIBERNATE_DDL_AUTO=update 24 | HIBERNATE_OPEN_IN_VIEW=false 25 | 26 | # Redis Configuration 27 | REDIS_HOST=localhost 28 | REDIS_PORT=6379 29 | 30 | # AWS S3 Configuration 31 | AWS_ACCESS_KEY=aws-access-key-id 32 | AWS_SECRET_KEY=aws-secret-access-key 33 | AWS_S3_BUCKET=s3-bucket-name 34 | AWS_REGION=us-east-1 35 | 36 | # JWT/Security 37 | JWT_SECRET=your-256-bit-secret 38 | JWT_EXPIRATION=86400000 39 | 40 | # Health Endpoint Enable/Disable 41 | MAIL_HEALTH=true 42 | REDIS_HEALTH=true 43 | 44 | # Prometheus Metrics Export Enable/Disable 45 | PROMETHEUS_METRICS_EXPORT=true 46 | 47 | # Security Configurations 48 | SECURITY_DEBUG=DEBUG 49 | 50 | # CORS Configuration 51 | CORS_ALLOWED_ORIGINS=http://localhost,http://localhost:3000,http://localhost:5173 52 | CORS_ALLOWED_METHODS=GET,POST,PUT,DELETE,OPTIONS 53 | CORS_ALLOWED_HEADERS=Authorization,Cache-Control,Content-Type 54 | CORS_ALLOW_CREDENTIALS=true 55 | CORS_MAX_AGE=3600 56 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/security/EmployerUserDetails.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.security; 2 | 3 | import com.lifepill.possystem.entity.Employer; 4 | import org.springframework.security.core.GrantedAuthority; 5 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | 8 | import java.util.Collection; 9 | import java.util.Collections; 10 | 11 | public class EmployerUserDetails implements UserDetails { 12 | 13 | private final Employer employer; 14 | 15 | public EmployerUserDetails(Employer employer) { 16 | this.employer = employer; 17 | } 18 | 19 | @Override 20 | public Collection getAuthorities() { 21 | return Collections.singleton(new SimpleGrantedAuthority(employer.getRole().toString())); 22 | } 23 | 24 | @Override 25 | public String getPassword() { 26 | return employer.getEmployerPassword(); 27 | } 28 | 29 | @Override 30 | public String getUsername() { 31 | return employer.getEmployerEmail(); 32 | } 33 | 34 | @Override 35 | public boolean isAccountNonExpired() { 36 | return true; 37 | } 38 | 39 | @Override 40 | public boolean isAccountNonLocked() { 41 | return true; 42 | } 43 | 44 | @Override 45 | public boolean isCredentialsNonExpired() { 46 | return true; 47 | } 48 | 49 | @Override 50 | public boolean isEnabled() { 51 | return true; 52 | } 53 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/BranchService.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.service; 2 | 3 | import com.lifepill.possystem.dto.BranchDTO; 4 | import com.lifepill.possystem.dto.BranchNewUpdateDTO; 5 | import com.lifepill.possystem.dto.requestDTO.BranchUpdateDTO; 6 | import com.lifepill.possystem.dto.responseDTO.BranchS3DTO; 7 | import org.springframework.core.io.InputStreamResource; 8 | import org.springframework.web.multipart.MultipartFile; 9 | 10 | import java.io.IOException; 11 | import java.util.List; 12 | 13 | public interface BranchService { 14 | 15 | void saveBranch(BranchDTO branchDTO, MultipartFile image); 16 | 17 | byte[] getImageData(long branchId); 18 | 19 | List getAllBranches(); 20 | 21 | BranchDTO getBranchById(long branchId); 22 | 23 | String deleteBranch(long branchId); 24 | 25 | void updateBranch(long branchId, BranchUpdateDTO branchUpdateDTO, MultipartFile image); 26 | 27 | void updateBranchImage(long branchId, MultipartFile image); 28 | 29 | // void updateBranchWithoutImage(long branchId, BranchNewUpdateDTO branchUpdateDTO); 30 | 31 | BranchS3DTO createBranch(BranchS3DTO branchS3DTO, MultipartFile file) throws IOException; 32 | 33 | BranchS3DTO getBranchS3ById(long branchId); 34 | 35 | InputStreamResource getBranchProfileImage(String branchProfileImageUrl); 36 | 37 | void updateBranchProfileImage(long branchId, MultipartFile file) throws IOException; 38 | 39 | BranchNewUpdateDTO updateBranchWithoutImage(long branchId, BranchNewUpdateDTO branchUpdateDTO); 40 | } 41 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/entity/Order.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.entity; 2 | 3 | import lombok.*; 4 | 5 | import javax.persistence.*; 6 | import java.time.OffsetDateTime; 7 | import java.util.Date; 8 | import java.util.Set; 9 | 10 | /** 11 | * The type Order. 12 | */ 13 | @Entity 14 | @Table(name = "orders") 15 | @AllArgsConstructor 16 | @Getter 17 | @Setter 18 | @RequiredArgsConstructor 19 | public class Order { 20 | @Id 21 | @Column(name = "order_id", length = 45) 22 | @GeneratedValue(strategy = GenerationType.AUTO) 23 | private long orderId; 24 | 25 | @ManyToOne 26 | @JoinColumn(name = "employer_id",nullable = false) 27 | private Employer employer; 28 | 29 | @Column(name = "branch_id",nullable = false) 30 | private long branchId; 31 | 32 | @Column(name = "order_date", columnDefinition = "TIMESTAMP") 33 | private Date orderDate; 34 | 35 | @Column(name = "total",nullable = false) 36 | private Double total; 37 | 38 | @OneToMany(mappedBy = "orders") 39 | private Set orderDetails; 40 | 41 | @OneToMany(mappedBy = "orders") 42 | private Set paymentDetails; 43 | 44 | /** 45 | * Instantiates a new Order. 46 | * 47 | * @param employers the employers 48 | * @param orderDate the order date 49 | * @param total the total 50 | */ 51 | public Order(Employer employers, Date orderDate, Double total) { 52 | this.employer = employers; 53 | this.orderDate = orderDate; 54 | this.total = total; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/repo/orderRepository/OrderRepository.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.repo.orderRepository; 2 | 3 | import com.lifepill.possystem.entity.Branch; 4 | import com.lifepill.possystem.entity.Order; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.jpa.repository.Query; 7 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.util.Date; 11 | import java.util.Collection; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * The interface Order repository. 17 | */ 18 | @Repository 19 | @EnableJpaRepositories 20 | public interface OrderRepository extends JpaRepository { 21 | /** 22 | * Find by branch id list. 23 | * 24 | * @param branchId the branch id 25 | * @return the list 26 | */ 27 | List findByBranchId(Long branchId); 28 | 29 | /** 30 | * Find by order date between list. 31 | * 32 | * @param truncate the truncate 33 | * @param date Order date 34 | * @return the list 35 | */ 36 | List findByOrderDateBetween(Date truncate, Date date); 37 | 38 | /** 39 | * Retrieves the total sales by summing up the total attribute of all orders. 40 | * 41 | * @return Total sales amount. 42 | */ 43 | /** 44 | * Retrieves the total sales by summing up the total attribute of all orders. 45 | * 46 | * @return Total sales amount. 47 | */ 48 | @Query("SELECT SUM(o.total) FROM Order o") 49 | Double getTotalSales(); 50 | 51 | List findAllByBranchId(long branchId); 52 | } -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/possystem/repo/OrderDetailsRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.repo; 2 | 3 | 4 | import com.lifepill.possystem.repo.orderRepository.OrderDetailsRepository; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 7 | import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; 8 | 9 | 10 | @DataJpaTest 11 | class OrderDetailsRepositoryTest { 12 | 13 | @Autowired 14 | private TestEntityManager entityManager; 15 | 16 | @Autowired 17 | private OrderDetailsRepository orderDetailsRepository; 18 | 19 | /*@Test 20 | void testSaveOrderDetails() { 21 | // Create test data 22 | Order order = new Order(*//* Set order details *//*); 23 | order = entityManager.persist(order); 24 | 25 | OrderDetails orderDetails = new OrderDetails(*//* Set order details *//*); 26 | orderDetails.setOrders(order); 27 | orderDetails = entityManager.persist(orderDetails); 28 | entityManager.flush(); 29 | 30 | // Call repository method 31 | OrderDetails savedOrderDetails = orderDetailsRepository.findById(orderDetails.getOrderDetailsId()).orElse(null); 32 | 33 | // Assert result 34 | assertNotNull(savedOrderDetails); 35 | assertEquals(orderDetails.getOrderDetailsId(), savedOrderDetails.getOrderDetailsId()); 36 | assertEquals(orderDetails.getName(), savedOrderDetails.getName()); 37 | assertEquals(orderDetails.getAmount(), savedOrderDetails.getAmount()); 38 | assertEquals(order.getOrderId(), savedOrderDetails.getOrders().getOrderId()); 39 | }*/ 40 | } 41 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/controller/MedicineFindingController.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.controller; 2 | 3 | import com.lifepill.possystem.dto.responseDTO.MedicineGetResponseDTO; 4 | import com.lifepill.possystem.service.MedicineFindingService; 5 | import com.lifepill.possystem.util.StandardResponse; 6 | import lombok.AllArgsConstructor; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RequestParam; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * The type Medicine finding controller. 18 | */ 19 | @RestController 20 | @RequestMapping("/lifepill/v1/medicine-finding") 21 | @AllArgsConstructor 22 | public class MedicineFindingController { 23 | 24 | private MedicineFindingService medicineFindingService; 25 | 26 | 27 | /** 28 | * Find medicine by name response entity. 29 | * 30 | * @param itemName the item name 31 | * @return the response entity 32 | */ 33 | @GetMapping(path = "/find-medicine",params = "itemName") 34 | public ResponseEntity findMedicineByName( 35 | @RequestParam(value = "itemName") String itemName 36 | ){ 37 | List medicineGetResponseDTOS = medicineFindingService.getItemByName(itemName); 38 | return new ResponseEntity<>( 39 | new StandardResponse(200, "Successfully fetched", medicineGetResponseDTOS), 40 | HttpStatus.OK 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/responseDTO/ItemGetIdOldResponseDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.responseDTO; 2 | 3 | import com.lifepill.possystem.dto.ItemCategoryDTO; 4 | import com.lifepill.possystem.dto.SupplierCompanyDTO; 5 | import com.lifepill.possystem.dto.SupplierDTO; 6 | import com.lifepill.possystem.entity.enums.MeasuringUnitType; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Data; 9 | import lombok.NoArgsConstructor; 10 | 11 | import java.util.Date; 12 | 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | @Data 16 | public class ItemGetIdOldResponseDTO { 17 | 18 | private long itemId; 19 | private long brandId; 20 | private String itemName; 21 | private double sellingPrice; 22 | private String itemBarCode; 23 | private Date supplyDate; 24 | private double supplierPrice; 25 | private boolean isFreeIssued; 26 | private boolean isDiscounted; 27 | private String itemManufacture; 28 | private double itemQuantity; 29 | private String itemCategoryName; 30 | private long itemCategoryId; 31 | private boolean isStock; 32 | private MeasuringUnitType measuringUnitType; 33 | private Date manufactureDate; 34 | private Date expireDate; 35 | private Date purchaseDate; 36 | private String warrantyPeriod; 37 | private String rackNumber; 38 | private double discountedPrice; 39 | private double discountedPercentage; 40 | private String warehouseName; 41 | private boolean isSpecialCondition; 42 | private String itemImage; 43 | private String itemDescription; 44 | private ItemCategoryDTO itemCategoryDTO; 45 | private SupplierDTO supplierDTO; 46 | private SupplierCompanyDTO supplierCompanyDTO; 47 | } 48 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/impl/S3ServiceIMPL.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.service.impl; 2 | 3 | import com.amazonaws.regions.Regions; 4 | import com.amazonaws.services.s3.AmazonS3; 5 | import com.amazonaws.services.s3.model.S3Object; 6 | import com.lifepill.possystem.service.S3Service; 7 | import lombok.AllArgsConstructor; 8 | import lombok.extern.log4j.Log4j2; 9 | import org.springframework.beans.factory.annotation.Value; 10 | import org.springframework.stereotype.Service; 11 | import org.springframework.web.multipart.MultipartFile; 12 | 13 | import javax.transaction.Transactional; 14 | import java.io.IOException; 15 | 16 | @Service 17 | @Transactional 18 | @Log4j2 19 | public class S3ServiceIMPL implements S3Service { 20 | 21 | private final AmazonS3 s3client; 22 | 23 | @Value("${aws.s3.bucket}") 24 | private String bucketName; 25 | 26 | @Value("${aws.region}") 27 | private String awsRegion; 28 | 29 | public S3ServiceIMPL(AmazonS3 s3client) { 30 | this.s3client = s3client; 31 | } 32 | 33 | public String uploadFile(String keyName, MultipartFile file) throws IOException { 34 | log.info("Uploading file with key: " + keyName); 35 | s3client.putObject(bucketName, keyName, file.getInputStream(), null); 36 | String fileUrl = String.format("https://%s.s3.%s.amazonaws.com/%s", 37 | bucketName, Regions.fromName(awsRegion).getName(), keyName); 38 | log.info("File uploaded to: " + fileUrl); 39 | return fileUrl; 40 | } 41 | 42 | public S3Object getFile(String keyName) { 43 | log.info("Retrieving file with key: " + keyName); 44 | return s3client.getObject(bucketName, keyName); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/ItemSaveRequestCategoryDTO.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO; 2 | 3 | import com.lifepill.possystem.entity.enums.MeasuringUnitType; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.Date; 9 | 10 | /** 11 | * The type Item save request category dto. 12 | */ 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | @Data 16 | public class ItemSaveRequestCategoryDTO { 17 | 18 | private long itemId; 19 | private long branchId; 20 | private String itemName; 21 | private double sellingPrice; 22 | private String itemBarCode; 23 | private Date supplyDate; 24 | private double supplierPrice; 25 | private boolean isFreeIssued; 26 | private boolean isDiscounted; 27 | private String itemManufacture; 28 | private double itemQuantity; 29 | // private String itemCategory; 30 | 31 | private boolean isStock; 32 | private MeasuringUnitType measuringUnitType; 33 | private Date manufactureDate; 34 | private Date expireDate; 35 | private Date purchaseDate; 36 | private String warrantyPeriod; 37 | private String rackNumber; 38 | private double discountedPrice; 39 | private double discountedPercentage; 40 | private String warehouseName; 41 | private boolean isSpecialCondition; 42 | private String itemImage; 43 | private String itemDescription; 44 | 45 | private long categoryId; 46 | private long supplierId; 47 | 48 | 49 | // private String categoryName; 50 | // private String categoryDescription; 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/possystem/repo/OrderRepositoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | package com.lifepill.possystem.repo; 3 | 4 | import com.lifepill.possystem.entity.Employer; 5 | import com.lifepill.possystem.entity.Order; 6 | import com.lifepill.possystem.repo.orderRepository.OrderRepository; 7 | import org.junit.jupiter.api.Test; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 10 | import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; 11 | import java.util.Date; 12 | import static org.junit.jupiter.api.Assertions.assertEquals; 13 | import static org.junit.jupiter.api.Assertions.assertNotNull; 14 | 15 | @DataJpaTest 16 | class OrderRepositoryTest { 17 | 18 | @Autowired 19 | private TestEntityManager entityManager; 20 | 21 | @Autowired 22 | private OrderRepository orderRepository; 23 | 24 | @Test 25 | void testSaveOrder() { 26 | // Create test data 27 | Employer employer = new Employer(*/ 28 | /* Set employer details *//* 29 | ); 30 | employer = entityManager.persist(employer); 31 | 32 | Order order = new Order(employer, new Date(), 1000.0); 33 | order = entityManager.persist(order); 34 | entityManager.flush(); 35 | 36 | // Call repository method 37 | Order savedOrder = orderRepository.findById(order.getOrderId()).orElse(null); 38 | 39 | // Assert result 40 | assertNotNull(savedOrder); 41 | assertEquals(order.getOrderId(), savedOrder.getOrderId()); 42 | assertEquals(order.getEmployer().getEmployerId(), savedOrder.getEmployer().getEmployerId()); 43 | assertEquals(order.getOrderDate(), savedOrder.getOrderDate()); 44 | assertEquals(order.getTotal(), savedOrder.getTotal()); 45 | } 46 | } 47 | */ 48 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/ItemSearchService.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.service; 2 | 3 | import com.lifepill.possystem.dto.requestDTO.ItemSearchDocument; 4 | import com.lifepill.possystem.dto.requestDTO.ItemSearchRequestDTO; 5 | import com.lifepill.possystem.dto.responseDTO.ItemSearchResponseDTO; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Service interface for OpenSearch item operations. 11 | */ 12 | public interface ItemSearchService { 13 | 14 | /** 15 | * Search for items based on the search request. 16 | * 17 | * @param request Search parameters 18 | * @return Search results 19 | */ 20 | ItemSearchResponseDTO searchItems(ItemSearchRequestDTO request); 21 | 22 | /** 23 | * Get autocomplete suggestions for item names. 24 | * 25 | * @param prefix Prefix to search for 26 | * @param size Maximum number of suggestions 27 | * @return List of suggested item names 28 | */ 29 | List getSuggestions(String prefix, int size); 30 | 31 | /** 32 | * Index a single item in OpenSearch. 33 | * 34 | * @param itemId ID of the item to index 35 | * @return true if indexing was successful 36 | */ 37 | boolean indexItem(Long itemId); 38 | 39 | /** 40 | * Index all items from the database to OpenSearch. 41 | * 42 | * @return Number of items indexed 43 | */ 44 | int indexAllItems(); 45 | 46 | /** 47 | * Delete an item from the OpenSearch index. 48 | * 49 | * @param itemId ID of the item to delete 50 | * @return true if deletion was successful 51 | */ 52 | boolean deleteItemFromIndex(Long itemId); 53 | 54 | /** 55 | * Reindex all items (delete index and recreate). 56 | * 57 | * @return Number of items indexed 58 | */ 59 | int reindexAll(); 60 | } 61 | -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/possystem/controller/MedicineFindingControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.controller; 2 | 3 | import com.lifepill.possystem.dto.responseDTO.MedicineGetResponseDTO; 4 | import com.lifepill.possystem.service.MedicineFindingService; 5 | import com.lifepill.possystem.util.StandardResponse; 6 | import org.junit.jupiter.api.BeforeEach; 7 | import org.junit.jupiter.api.Test; 8 | import org.mockito.InjectMocks; 9 | import org.mockito.Mock; 10 | import org.mockito.MockitoAnnotations; 11 | import org.springframework.http.HttpStatus; 12 | import org.springframework.http.ResponseEntity; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | import static org.junit.jupiter.api.Assertions.assertEquals; 18 | import static org.mockito.Mockito.when; 19 | 20 | class MedicineFindingControllerTest { 21 | 22 | @InjectMocks 23 | private MedicineFindingController medicineFindingController; 24 | 25 | @Mock 26 | private MedicineFindingService medicineFindingService; 27 | 28 | private List medicineGetResponseDTOS; 29 | 30 | @BeforeEach 31 | void setUp() { 32 | MockitoAnnotations.openMocks(this); 33 | medicineGetResponseDTOS = new ArrayList<>(); 34 | medicineGetResponseDTOS.add(new MedicineGetResponseDTO()); 35 | } 36 | 37 | @Test 38 | void testFindMedicineByName() { 39 | String itemName = "Paracetamol"; 40 | when(medicineFindingService.getItemByName(itemName)).thenReturn(medicineGetResponseDTOS); 41 | 42 | ResponseEntity response = medicineFindingController.findMedicineByName(itemName); 43 | 44 | assertEquals(HttpStatus.OK, response.getStatusCode()); 45 | assertEquals(200, response.getBody().getCode()); 46 | assertEquals("Successfully fetched", response.getBody().getMessage()); 47 | assertEquals(medicineGetResponseDTOS, response.getBody().getData()); 48 | } 49 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/entity/Branch.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.entity; 2 | 3 | import lombok.*; 4 | 5 | import javax.persistence.*; 6 | import java.util.Set; 7 | 8 | /** 9 | * The type Branch. 10 | */ 11 | @Entity 12 | @Getter 13 | @Setter 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @Table(name = "branch") 17 | @Builder 18 | public class Branch { 19 | @Id 20 | @Column(name = "branch_id") 21 | @GeneratedValue(strategy = GenerationType.AUTO) 22 | private long branchId; 23 | @Column(name = "branch_name", length = 20, nullable = false) 24 | private String branchName; 25 | @Column(name = "branch_address", length = 100, nullable = false) 26 | private String branchAddress; 27 | @Column(name = "branch_contact", length = 12) 28 | private String branchContact; 29 | @Column(name = "branch_fax", length = 12) 30 | private String branchFax; 31 | @Column(name = "branch_email", length = 50) 32 | private String branchEmail; 33 | @Column(name = "branch_description", length = 100) 34 | private String branchDescription; 35 | @Lob 36 | @Column(name = "branch_image") 37 | private byte[] branchImage; 38 | @Column(name = "branch_status", columnDefinition = "BOOLEAN default false") 39 | private boolean branchStatus; 40 | @Column(name = "branch_location", length = 100) 41 | private String branchLocation; 42 | @Column(name = "branch_created_on") 43 | private String branchCreatedOn; 44 | @Column(name = "branch_created_by") 45 | private String branchCreatedBy; 46 | @Column(name = "branch_profile_image_url") 47 | private String branchProfileImageUrl; 48 | 49 | @OneToMany(cascade = CascadeType.ALL, mappedBy = "branch", fetch = FetchType.EAGER) 50 | private Set employers; 51 | 52 | @ManyToMany 53 | @JoinTable( 54 | name = "branch_item", 55 | joinColumns = @JoinColumn(name = "branch_id"), 56 | inverseJoinColumns = @JoinColumn(name = "item_id") 57 | ) 58 | private Set items; 59 | } 60 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/controller/CashierController.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.controller; 2 | 3 | import com.lifepill.possystem.dto.requestDTO.EmployerUpdate.EmployerPasswordResetDTO; 4 | import com.lifepill.possystem.dto.requestDTO.EmployerUpdate.EmployerRecentPinUpdateDTO; 5 | import com.lifepill.possystem.service.EmployerService; 6 | import lombok.AllArgsConstructor; 7 | import org.springframework.transaction.annotation.Transactional; 8 | import org.springframework.web.bind.annotation.PutMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | /** 14 | * Controller class for managing cashier-related operations. 15 | */ 16 | @RestController 17 | @RequestMapping("lifepill/v1/cashier") 18 | @AllArgsConstructor 19 | public class CashierController { 20 | 21 | private EmployerService employerService; 22 | 23 | /** 24 | * Updates the password of a cashier. 25 | * 26 | * @param cashierPasswordResetDTO DTO containing details necessary for resetting the password. 27 | * @return A message indicating the success or failure of the password update operation. 28 | */ 29 | @PutMapping("/updatePassword") 30 | @Transactional 31 | public String updateEmployerPassword(@RequestBody EmployerPasswordResetDTO cashierPasswordResetDTO) { 32 | return employerService.updateEmployerPassword(cashierPasswordResetDTO); 33 | } 34 | 35 | /** 36 | * Updates the recent PIN of a cashier. 37 | * 38 | * @param cashierRecentPinUpdateDTO DTO containing details necessary for updating the recent PIN. 39 | * @return A message indicating the success or failure of the recent PIN update operation. 40 | */ 41 | @PutMapping("/updateRecentPin") 42 | @Transactional 43 | public String updateRecentPin(@RequestBody EmployerRecentPinUpdateDTO cashierRecentPinUpdateDTO) { 44 | return employerService.updateRecentPin(cashierRecentPinUpdateDTO); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /pos-system/deploy_manually.md: -------------------------------------------------------------------------------- 1 | 2 | ### `update_and_deploy.sh` 3 | 4 | ```bash 5 | #!/bin/bash 6 | 7 | # Function to increment the version number 8 | increment_version() { 9 | local version=$1 10 | local major minor patch 11 | IFS='.' read -r major minor patch <<< "$version" 12 | patch=$((patch + 1)) 13 | echo "$major.$minor.$patch" 14 | } 15 | 16 | # Read the current version from a file or set it manually 17 | version_file="version.txt" 18 | if [[ -f $version_file ]]; then 19 | current_version=$(cat $version_file) 20 | else 21 | current_version="0.0.0" # Default version if no file is found 22 | fi 23 | 24 | # Increment the version 25 | new_version=$(increment_version $current_version) 26 | echo "Updating version from $current_version to $new_version" 27 | 28 | # Save the new version to the file 29 | echo $new_version > $version_file 30 | 31 | # Build the new Docker image with the new tag 32 | docker build -t pos-system:$new_version . 33 | 34 | # Update the docker-compose.yml file with the new tag 35 | sed -i "s/pos-system:.*$/pos-system:$new_version/" docker-compose.yml 36 | 37 | # Bring up the services with Docker Compose 38 | docker-compose down 39 | docker-compose up -d --build 40 | 41 | echo "Deployment complete with tag pos-system:$new_version" 42 | ``` 43 | 44 | ### Steps to Use the Script 45 | 46 | 1. **Save the Script**: Save the above script to a file named `update_and_deploy.sh` in your project directory (`~/pharmacy-pos-main-backend/pos-system`). 47 | 48 | 2. **Make the Script Executable**: Make the script executable by running the following command: 49 | 50 | ```bash 51 | chmod +x update_and_deploy.sh 52 | ``` 53 | 54 | 3. **Create a `version.txt` File**: Create a file named `version.txt` in the same directory, and add the initial version number (e.g., `0.0.0`): 55 | 56 | ```bash 57 | echo "0.0.0" > version.txt 58 | ``` 59 | 60 | 4. **Run the Script**: Execute the script whenever you make changes to your code and need to update the Docker tag, rebuild the Docker image, and bring up the services: 61 | 62 | ```bash 63 | ./update_and_deploy.sh 64 | ``` 65 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/PosSystemApplication.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem; 2 | 3 | import io.github.cdimascio.dotenv.Dotenv; 4 | import io.swagger.v3.oas.annotations.ExternalDocumentation; 5 | import io.swagger.v3.oas.annotations.OpenAPIDefinition; 6 | import io.swagger.v3.oas.annotations.info.Contact; 7 | import io.swagger.v3.oas.annotations.info.Info; 8 | import io.swagger.v3.oas.annotations.info.License; 9 | import lombok.extern.log4j.Log4j2; 10 | import org.springframework.boot.SpringApplication; 11 | import org.springframework.boot.autoconfigure.SpringBootApplication; 12 | import org.springframework.cache.annotation.EnableCaching; 13 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 14 | 15 | @OpenAPIDefinition( 16 | info = @Info( 17 | title = "LifePill POS -System API Documentation", 18 | description = "LIFEPILL", 19 | version = "v1", 20 | contact = @Contact( 21 | name = "LifePIll", 22 | email = "lifepillinfo@gmail.com", 23 | url = "https://github.com/Life-Pill" 24 | ), 25 | license = @License( 26 | name = "Apache 2.0", 27 | url = "https://github.com/Life-Pill" 28 | ) 29 | ), 30 | externalDocs = @ExternalDocumentation( 31 | description = "LifePill POS System REST API Documentation", 32 | url = "http://localhost:8081/swagger-ui/index.html#/" 33 | ) 34 | ) 35 | @SpringBootApplication 36 | @EnableJpaAuditing(auditorAwareRef = "auditorAwareImpl") // Enable JPA Auditing 37 | @Log4j2 38 | @EnableCaching 39 | public class PosSystemApplication { 40 | 41 | /** 42 | * Entry point of the application. 43 | * @param args Command-line arguments. 44 | */ 45 | public static void main(String[] args) { 46 | 47 | try { 48 | Dotenv dotenv = Dotenv.configure() 49 | .ignoreIfMissing() 50 | .load(); 51 | dotenv.entries().forEach(entry -> System.setProperty(entry.getKey(), entry.getValue())); 52 | } catch (Exception e) { 53 | log.info("No .env file found, using environment variables directly"); 54 | } 55 | SpringApplication.run(PosSystemApplication.class, args); 56 | } 57 | 58 | } 59 | 60 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/repo/itemRepository/ItemRepository.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.repo.itemRepository; 2 | import com.lifepill.possystem.entity.Item; 3 | import org.springframework.data.domain.Page; 4 | import org.springframework.data.domain.Pageable; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * The interface Item repository. 13 | */ 14 | @Repository 15 | @EnableJpaRepositories 16 | public interface ItemRepository extends JpaRepository { 17 | /** 18 | * Find all by item name equals and stock equals list. 19 | * 20 | * @param itemName the item name 21 | * @param b the b 22 | * @return the list 23 | */ 24 | List findAllByItemNameEqualsAndStockEquals(String itemName, boolean b); 25 | 26 | /** 27 | * Find all by stock equals list. 28 | * 29 | * @param activeStatus the active status 30 | * @return the list 31 | */ 32 | List findAllByStockEquals(boolean activeStatus); 33 | 34 | /** 35 | * Find all by stock equals page. 36 | * 37 | * @param activeStatus the active status 38 | * @param pageable the pageable 39 | * @return the page 40 | */ 41 | Page findAllByStockEquals(boolean activeStatus, Pageable pageable); 42 | 43 | /** 44 | * Count all by stock equals int. 45 | * 46 | * @param activeStatus the active status 47 | * @return the int 48 | */ 49 | int countAllByStockEquals(boolean activeStatus); 50 | 51 | /** 52 | * Find all by item bar code equals list. 53 | * 54 | * @param itemBarCode the item bar code 55 | * @return the list 56 | */ 57 | List findAllByItemBarCodeEquals(String itemBarCode); 58 | 59 | List findAllByItemName(String itemName); 60 | 61 | List findAllByItemNameAndStock(String itemName, boolean stock); 62 | 63 | List findAllByBranchId(long branchId); 64 | } 65 | -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/possystem/cucumber/auth.feature: -------------------------------------------------------------------------------- 1 | #Feature: Authentication Feature 2 | # 3 | # Scenario: Successful registration 4 | # Given a register request with valid data 5 | # When the register endpoint is called 6 | # Then the response status code should be 200 7 | # And the authentication response should be returned 8 | # 9 | # Scenario: Testing the authentication endpoint 10 | # When the test endpoint is called 11 | # Then the response should be "Authenticated" 12 | # 13 | # Scenario: Successful authentication 14 | # Given an authentication request with valid credentials 15 | # When the authenticate endpoint is called 16 | # Then the response status code should be 200 17 | # And the authentication response should be returned 18 | # And the access token should be set as a cookie 19 | # 20 | # Scenario: Authentication failure due to invalid credentials 21 | # Given an authentication request with invalid credentials 22 | # When the authenticate endpoint is called 23 | # Then the response status code should be 401 24 | # And the error message "Authentication failed: Incorrect username or password" should be returned 25 | # 26 | # Scenario: Setting access token as a cookie on authentication 27 | # Given an authentication request with valid credentials 28 | # When the authenticate endpoint is called 29 | # Then the access token should be set as a cookie in the response 30 | # 31 | # Scenario: Retrieving employer details on authentication 32 | # Given an authentication request with a valid employer email 33 | # When the authenticate endpoint is called 34 | # Then the response status code should be 200 35 | # And the authentication response should be returned 36 | # And the employer details should be included in the response body 37 | # 38 | # Scenario: Authentication exception handling 39 | # Given an authentication request 40 | # When the authenticate endpoint is called and an authentication exception occurs 41 | # Then the response status code should be 401 42 | # And the error message "Authentication failed: Incorrect username or password" should be returned -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/possystem/cucumber/supplier/supplier.feature: -------------------------------------------------------------------------------- 1 | #Feature: Supplier Management 2 | # 3 | # Scenario: Get all suppliers 4 | # Given there are suppliers in the system 5 | # When the user requests to get all suppliers 6 | # Then the system should return a list of suppliers 7 | # 8 | # Scenario: Get a supplier by ID 9 | # Given there is a supplier with ID 1 10 | # When the user requests to get the supplier with ID 1 11 | # Then the system should return the supplier with ID 1 12 | # 13 | # Scenario: Save a new supplier 14 | # Given there is no supplier with email "test@example.com" 15 | # When the user requests to save a new supplier with email "test@example.com" 16 | # Then the system should save the new supplier 17 | # 18 | # Scenario: Update an existing supplier 19 | # Given there is a supplier with ID 1 20 | # When the user requests to update the supplier with ID 1 21 | # Then the system should update the supplier with ID 1 22 | # 23 | # Scenario: Delete a supplier 24 | # Given there is a supplier with ID 1 25 | # When the user requests to delete the supplier with ID 1 26 | # Then the system should delete the supplier with ID 1 27 | # 28 | # Scenario: Get all suppliers when no suppliers exist 29 | # Given there are no suppliers in the system 30 | # When the user requests to get all suppliers 31 | # Then the system should return an empty list of suppliers 32 | # 33 | # Scenario: Save a new supplier with a duplicate email 34 | # Given there is a supplier with email "test@example.com" 35 | # When the user requests to save a new supplier with email "test@example.com" 36 | # Then the system should throw an EntityDuplicationException 37 | # 38 | # Scenario: Update a non-existing supplier 39 | # Given there is no supplier with ID 1 40 | # When the user requests to update the supplier with ID 1 41 | # Then the system should throw a NotFoundException 42 | # 43 | # Scenario: Delete a non-existing supplier 44 | # Given there is no supplier with ID 1 45 | # When the user requests to delete the supplier with ID 1 46 | # Then the system should throw a NotFoundException -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/entity/enums/Role.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.entity.enums; 2 | 3 | import lombok.Getter; 4 | import lombok.RequiredArgsConstructor; 5 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 6 | 7 | import java.util.List; 8 | import java.util.Set; 9 | import java.util.stream.Collectors; 10 | 11 | import static com.lifepill.possystem.entity.enums.Permission.*; 12 | 13 | /** 14 | * The enum Role. 15 | */ 16 | @RequiredArgsConstructor 17 | public enum Role { 18 | /** 19 | * Owner role. 20 | */ 21 | // CASHIER,MANAGER,OWNER,OTHER 22 | OWNER( 23 | Set.of( 24 | OWNER_READ, 25 | OWNER_CREATE, 26 | CASHIER_READ, 27 | CASHIER_CREATE, 28 | OTHER_READ, 29 | OTHER_CREATE 30 | ) 31 | ), 32 | 33 | /** 34 | * Manager role. 35 | */ 36 | MANAGER( 37 | Set.of( 38 | MANAGER_READ, 39 | MANAGER_CREATE, 40 | CASHIER_READ, 41 | CASHIER_CREATE, 42 | OTHER_READ, 43 | OTHER_CREATE 44 | ) 45 | ), 46 | /** 47 | * Cashier role. 48 | */ 49 | CASHIER( 50 | Set.of( 51 | CASHIER_READ, 52 | CASHIER_CREATE 53 | ) 54 | ), 55 | 56 | /** 57 | * Other role. 58 | */ 59 | OTHER( 60 | Set.of( 61 | OTHER_READ, 62 | OTHER_CREATE 63 | ) 64 | ) 65 | ; 66 | 67 | @Getter 68 | private final Set permissions; 69 | 70 | /** 71 | * Gets authorities. 72 | * 73 | * @return the authorities 74 | */ 75 | public List getAuthorities() { 76 | var authorities = getPermissions() 77 | .stream() 78 | .map(authority -> new SimpleGrantedAuthority(authority.getPermission())) 79 | .collect(Collectors.toList()); 80 | authorities.add(new SimpleGrantedAuthority("ROLE_"+ this.name())); 81 | return authorities; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/config/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.config; 2 | 3 | import io.swagger.v3.oas.models.Components; 4 | import io.swagger.v3.oas.models.OpenAPI; 5 | import io.swagger.v3.oas.models.info.Contact; 6 | import io.swagger.v3.oas.models.info.Info; 7 | import io.swagger.v3.oas.models.info.License; 8 | import io.swagger.v3.oas.models.security.SecurityRequirement; 9 | import io.swagger.v3.oas.models.security.SecurityScheme; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | 13 | /** 14 | * Swagger/OpenAPI configuration with JWT Bearer token authentication. 15 | */ 16 | @Configuration 17 | public class SwaggerConfig { 18 | 19 | private static final String SECURITY_SCHEME_NAME = "Bearer Authentication"; 20 | 21 | @Bean 22 | public OpenAPI openAPI() { 23 | return new OpenAPI() 24 | .info(new Info() 25 | .title("LifePill POS System API") 26 | .description("REST API documentation for LifePill Pharmacy POS System") 27 | .version("v1.0.0") 28 | .contact(new Contact() 29 | .name("LifePill Team") 30 | .email("support@lifepill.com") 31 | .url("https://lifepill.com")) 32 | .license(new License() 33 | .name("MIT License") 34 | .url("https://opensource.org/licenses/MIT"))) 35 | .addSecurityItem(new SecurityRequirement().addList(SECURITY_SCHEME_NAME)) 36 | .components(new Components() 37 | .addSecuritySchemes(SECURITY_SCHEME_NAME, new SecurityScheme() 38 | .name(SECURITY_SCHEME_NAME) 39 | .type(SecurityScheme.Type.HTTP) 40 | .scheme("bearer") 41 | .bearerFormat("JWT") 42 | .description("Enter JWT token. Get token from /lifepill/v1/auth/authenticate endpoint"))); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/RedisService.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.service; 2 | 3 | import com.lifepill.possystem.dto.responseDTO.EmployerAuthDetailsResponseDTO; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.data.redis.core.RedisTemplate; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.Collection; 9 | import java.util.HashSet; 10 | import java.util.Set; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | @Service 14 | public class RedisService { 15 | private static final String EMPLOYER_DETAILS_PREFIX = "employer_details::"; 16 | 17 | @Autowired 18 | private RedisTemplate redisTemplate; 19 | 20 | public void cacheEmployerDetails(EmployerAuthDetailsResponseDTO employerDetails) { 21 | String key = EMPLOYER_DETAILS_PREFIX + employerDetails.getEmployerEmail(); 22 | redisTemplate.opsForValue().set(key, employerDetails, 24, TimeUnit.HOURS); // Cache for 24 hours 23 | } 24 | 25 | public EmployerAuthDetailsResponseDTO getEmployerDetails(String username) { 26 | String key = EMPLOYER_DETAILS_PREFIX + username; 27 | return redisTemplate.opsForValue().get(key); 28 | } 29 | 30 | public void removeEmployerDetails(String username) { 31 | String key = EMPLOYER_DETAILS_PREFIX + username; 32 | redisTemplate.delete(key); 33 | } 34 | 35 | /** 36 | * Retrieves all cached employer details from Redis. 37 | * 38 | * @return A collection of EmployerAuthDetailsResponseDTO representing the cached employer details. 39 | */ 40 | public Collection getAllCachedEmployerDetails() { 41 | Set keys = redisTemplate.keys(EMPLOYER_DETAILS_PREFIX + "*"); 42 | Collection cachedEmployers = new HashSet<>(); 43 | for (String key : keys) { 44 | EmployerAuthDetailsResponseDTO employerDetails = redisTemplate.opsForValue().get(key); 45 | if (employerDetails != null) { 46 | cachedEmployers.add(employerDetails); 47 | } 48 | } 49 | return cachedEmployers; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/repo/employerRepository/EmployerRepository.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.repo.employerRepository; 2 | 3 | import com.lifepill.possystem.entity.Branch; 4 | import com.lifepill.possystem.entity.Employer; 5 | import com.lifepill.possystem.entity.enums.Role; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.util.List; 11 | import java.util.Optional; 12 | 13 | /** 14 | * The interface Employer repository. 15 | */ 16 | @Repository 17 | @EnableJpaRepositories 18 | public interface EmployerRepository extends JpaRepository { 19 | 20 | /** 21 | * Find by is active status equals list. 22 | * 23 | * @param activeState the active state 24 | * @return the list 25 | */ 26 | List findByIsActiveStatusEquals(boolean activeState); 27 | 28 | /** 29 | * Exists all by employer email boolean. 30 | * 31 | * @param employerEmail the employer email 32 | * @return the boolean 33 | */ 34 | boolean existsAllByEmployerEmail(String employerEmail); 35 | 36 | /** 37 | * Find all by branch list. 38 | * 39 | * @param branch the branch 40 | * @return the list 41 | */ 42 | List findAllByBranch(Branch branch); 43 | 44 | /** 45 | * Find all by role list. 46 | * 47 | * @param role the role 48 | * @return the list 49 | */ 50 | List findAllByRole(Role role); 51 | 52 | /** 53 | * Find by employer email optional. 54 | * 55 | * @param employerEmail the employer email 56 | * @return the optional 57 | */ 58 | Optional findByEmployerEmail(String employerEmail); 59 | 60 | /** 61 | * Find by branch id and role employer. 62 | * 63 | * @param branchId the branch id 64 | * @param role the role 65 | * @return the employer 66 | */ 67 | Employer findByBranch_BranchIdAndRole(Long branchId, Role role); 68 | 69 | List findAllByBranchAndRole(Branch branch, Role role); 70 | 71 | List findByBranch_BranchId(long branchId); 72 | } 73 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.config; 2 | 3 | 4 | import com.lifepill.possystem.dto.responseDTO.EmployerAuthDetailsResponseDTO; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.data.redis.connection.RedisStandaloneConfiguration; 9 | import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 10 | import org.springframework.data.redis.core.RedisTemplate; 11 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 12 | import org.springframework.data.redis.serializer.StringRedisSerializer; 13 | 14 | @Configuration 15 | public class RedisConfig { 16 | 17 | @Value("${spring.redis.host}") 18 | private String redisHost; 19 | 20 | @Value("${spring.redis.port}") 21 | private int redisPort; 22 | 23 | /** 24 | * Configures the Jedis connection factory for Redis. 25 | * 26 | * @return JedisConnectionFactory configured with Redis standalone configuration. 27 | */ 28 | @Bean 29 | public JedisConnectionFactory jedisConnectionFactory() { 30 | RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); 31 | redisStandaloneConfiguration.setHostName(redisHost); 32 | redisStandaloneConfiguration.setPort(redisPort); 33 | return new JedisConnectionFactory(redisStandaloneConfiguration); 34 | } 35 | 36 | /** 37 | * Configures the Redis template for key-value serialization. 38 | * 39 | * @return RedisTemplate configured with String key serializer and Jackson JSON value serializer. 40 | */ 41 | @Bean 42 | public RedisTemplate redisTemplate() { 43 | RedisTemplate redisTemplate = new RedisTemplate<>(); 44 | redisTemplate.setConnectionFactory(jedisConnectionFactory()); 45 | redisTemplate.setKeySerializer(new StringRedisSerializer()); 46 | redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(EmployerAuthDetailsResponseDTO.class)); 47 | return redisTemplate; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/possystem/service/ItemServiceIMPLTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | package com.lifepill.possystem.service; 3 | 4 | import com.lifepill.possystem.exception.NotFoundException; 5 | import com.lifepill.possystem.repo.itemRepository.ItemRepository; 6 | import com.lifepill.possystem.service.impl.ItemServiceIMPL; 7 | import org.junit.jupiter.api.BeforeEach; 8 | import org.junit.jupiter.api.Test; 9 | import org.mockito.InjectMocks; 10 | import org.mockito.Mock; 11 | import org.mockito.MockitoAnnotations; 12 | 13 | import java.util.List; 14 | 15 | import static org.junit.jupiter.api.Assertions.*; 16 | import static org.mockito.Mockito.*; 17 | 18 | */ 19 | /** 20 | * The type Item service impl test. 21 | *//* 22 | 23 | public class ItemServiceIMPLTest { 24 | 25 | @Mock 26 | private ItemRepository itemRepository; 27 | 28 | @InjectMocks 29 | private ItemServiceIMPL itemService; 30 | 31 | */ 32 | /** 33 | * Sets up. 34 | *//* 35 | 36 | @BeforeEach 37 | public void setUp() { 38 | MockitoAnnotations.initMocks(this); 39 | } 40 | 41 | */ 42 | /** 43 | * Gets item by name and stock item not found exception thrown. 44 | *//* 45 | 46 | @Test 47 | public void getItemByNameAndStock_ItemNotFound_ExceptionThrown() { 48 | // Arrange 49 | String itemName = "Non-existent Item"; 50 | // Mocking behavior of the repository to return an empty list, indicating no item found 51 | when(itemRepository.findAllByItemNameEqualsAndStockEquals(anyString(), anyBoolean())).thenReturn(List.of()); 52 | 53 | // Act and Assert 54 | assertThrows(NotFoundException.class, () -> itemService.getItemByName(itemName)); 55 | } 56 | 57 | */ 58 | /** 59 | * Gets item by stock status no active items found exception thrown. 60 | *//* 61 | 62 | @Test 63 | public void getItemByStockStatus_NoActiveItemsFound_ExceptionThrown() { 64 | // Arrange 65 | // Mocking behavior of the repository to return an empty list, indicating no active items found 66 | when(itemRepository.findAllByStockEquals(anyBoolean())).thenReturn(List.of()); 67 | 68 | // Act and Assert 69 | assertThrows(NotFoundException.class, () -> itemService.getItemByStockStatus(true)); 70 | } 71 | 72 | } 73 | */ 74 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/ItemService.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.service; 2 | 3 | import com.lifepill.possystem.dto.ItemCategoryDTO; 4 | import com.lifepill.possystem.dto.paginated.PaginatedResponseItemDTO; 5 | import com.lifepill.possystem.dto.requestDTO.ItemSaveRequestCategoryDTO; 6 | import com.lifepill.possystem.dto.requestDTO.ItemSaveRequestDTO; 7 | import com.lifepill.possystem.dto.requestDTO.ItemUpdateDTO; 8 | import com.lifepill.possystem.dto.responseDTO.*; 9 | import org.springframework.core.io.InputStreamResource; 10 | import org.springframework.web.multipart.MultipartFile; 11 | 12 | import java.io.IOException; 13 | import java.util.List; 14 | 15 | public interface ItemService { 16 | String saveItems(ItemSaveRequestDTO itemSaveRequestDTO); 17 | 18 | List getItemByNameAndStatusBymapstruct(String itemName); 19 | 20 | List getItemByName(String itemName); 21 | 22 | List getItemByStockStatus(boolean activeStatus); 23 | 24 | String updateItem(ItemUpdateDTO itemUpdateDTO); 25 | 26 | String deleteItem(long itemId); 27 | 28 | List getAllItems(); 29 | 30 | PaginatedResponseItemDTO getItemByStockStatusWithPaginateed(boolean activeStatus, int page, int size); 31 | 32 | List getItemByBarCode(String itemBarCode); 33 | 34 | String saveCategory(ItemCategoryDTO categoryDTO); 35 | 36 | String saveItemWithCategory(ItemSaveRequestCategoryDTO itemSaveRequestCategoryDTO); 37 | 38 | List getAllCategories(); 39 | 40 | String updateCategoryDetails(long categoryId, ItemCategoryDTO categoryDTO); 41 | 42 | String deleteCategory(long categoryId); 43 | 44 | ItemGetResponseWithoutSupplierDetailsDTO getItemById(long itemId); 45 | 46 | ItemGetIdResponseDTO getAllDetailsItemById(long itemId); 47 | 48 | ItemSaveRequestCategoryDTO createItemWithImage(MultipartFile file, ItemSaveRequestCategoryDTO itemSaveRequestCategoryDTO) throws IOException; 49 | 50 | InputStreamResource getItemImage(String itemImage); 51 | 52 | void updateItemImage(long itemId, MultipartFile file) throws IOException;; 53 | 54 | ItemGetIdOldResponseDTO getAllDetailsItemByIdOld(long itemId); 55 | 56 | List getItemByBranchId(long branchId); 57 | } 58 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/dto/requestDTO/ItemSearchDocument.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.dto.requestDTO; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.lifepill.possystem.entity.enums.MeasuringUnitType; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import java.util.Date; 11 | 12 | /** 13 | * Document class representing an Item in OpenSearch index. 14 | * This is used for full-text search capabilities. 15 | */ 16 | @Data 17 | @Builder 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class ItemSearchDocument { 21 | 22 | private Long itemId; 23 | private String itemName; 24 | private String itemBarCode; 25 | private String itemManufacture; 26 | private String itemDescription; 27 | private double sellingPrice; 28 | private double supplierPrice; 29 | private double itemQuantity; 30 | private boolean stock; 31 | private boolean freeIssued; 32 | private boolean discounted; 33 | private double discountedPrice; 34 | private double discountedPercentage; 35 | private String measuringUnitType; 36 | private String warehouseName; 37 | private String rackNumber; 38 | private boolean specialCondition; 39 | private String itemImage; 40 | 41 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") 42 | private Date manufactureDate; 43 | 44 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") 45 | private Date expireDate; 46 | 47 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") 48 | private Date supplyDate; 49 | 50 | // Category info 51 | private Long categoryId; 52 | private String categoryName; 53 | 54 | // Supplier info 55 | private Long supplierId; 56 | private String supplierName; 57 | private String supplierCompanyName; 58 | 59 | // Branch info 60 | private Long branchId; 61 | 62 | // Timestamps 63 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") 64 | private Date dateCreated; 65 | 66 | @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") 67 | private Date lastUpdatedDate; 68 | 69 | // Computed field for search boosting 70 | private String searchKeywords; 71 | } 72 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/util/mappers/OrderMapper.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.util.mappers; 2 | 3 | import com.lifepill.possystem.dto.GroupedOrderDetails; 4 | import com.lifepill.possystem.dto.requestDTO.RequestOrderDetailsSaveDTO; 5 | import com.lifepill.possystem.dto.requestDTO.RequestPaymentDetailsDTO; 6 | import com.lifepill.possystem.dto.responseDTO.OrderResponseDTO; 7 | import com.lifepill.possystem.entity.Order; 8 | import com.lifepill.possystem.entity.PaymentDetails; 9 | import lombok.AllArgsConstructor; 10 | import org.modelmapper.ModelMapper; 11 | import org.springframework.stereotype.Component; 12 | 13 | import java.util.List; 14 | import java.util.stream.Collectors; 15 | 16 | @Component 17 | @AllArgsConstructor 18 | public class OrderMapper { 19 | 20 | private ModelMapper modelMapper; 21 | 22 | /** 23 | * Maps an Order entity to an OrderResponseDTO. 24 | * 25 | * @param order The Order entity to map. 26 | * @return The mapped OrderResponseDTO. 27 | */ 28 | public OrderResponseDTO mapOrderToResponseDTO(Order order) { 29 | OrderResponseDTO orderResponseDTO = new OrderResponseDTO(); 30 | orderResponseDTO.setEmployerId(order.getEmployer().getEmployerId()); 31 | orderResponseDTO.setBranchId(order.getBranchId()); 32 | orderResponseDTO.setOrderDate(order.getOrderDate()); 33 | orderResponseDTO.setTotal(order.getTotal()); 34 | 35 | GroupedOrderDetails groupedOrderDetails = new GroupedOrderDetails(); 36 | List orderDetails = order.getOrderDetails().stream() 37 | .map(orderDetail -> { 38 | RequestOrderDetailsSaveDTO dto = modelMapper.map(orderDetail, RequestOrderDetailsSaveDTO.class); 39 | dto.setId(orderDetail.getItems().getItemId()); 40 | return dto; 41 | }) 42 | .collect(Collectors.toList()); 43 | groupedOrderDetails.setOrderDetails(orderDetails); 44 | 45 | if (order.getPaymentDetails() != null && !order.getPaymentDetails().isEmpty()) { 46 | PaymentDetails paymentDetails = order.getPaymentDetails().iterator().next(); 47 | RequestPaymentDetailsDTO paymentDetailsDTO = modelMapper.map(paymentDetails, RequestPaymentDetailsDTO.class); 48 | paymentDetailsDTO.setPayedAmount(paymentDetails.getPaidAmount()); 49 | groupedOrderDetails.setPaymentDetails(paymentDetailsDTO); 50 | } 51 | groupedOrderDetails.setOrderCount(1); // Since we're retrieving a single order 52 | orderResponseDTO.setGroupedOrderDetails(groupedOrderDetails); 53 | return orderResponseDTO; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /pos-system/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: MAIN-POS-BACKEND 4 | datasource: 5 | driver-class-name: org.postgresql.Driver 6 | url: ${DATABASE_URL} 7 | username: ${DATABASE_USERNAME} 8 | password: ${DATABASE_PASSWORD} 9 | jpa: 10 | hibernate: 11 | ddl-auto: ${HIBERNATE_DDL_AUTO:update} 12 | properties: 13 | hibernate: 14 | dialect: org.hibernate.dialect.PostgreSQLDialect 15 | jdbc: 16 | lob: 17 | non_contextual_creation: true 18 | show-sql: ${JDBC_SHOW_SQL} 19 | open-in-view: ${HIBERNATE_OPEN_IN_VIEW:false} 20 | security: 21 | user: 22 | name: ${SPRING_SECURITY_USERNAME} 23 | password: ${SPRING_SECURITY_PASSWORD} 24 | redis: 25 | host: ${REDIS_HOST} 26 | port: ${REDIS_PORT} 27 | mail: 28 | host: ${SPRING_MAIL_HOST} 29 | port: ${SPRING_MAIL_PORT} 30 | username: ${SPRING_USER_NAME} 31 | password: ${SPRING_PASSWORD} 32 | properties: 33 | mail: 34 | smtp: 35 | auth: true 36 | starttls: 37 | enable: true 38 | 39 | # OpenSearch Configuration 40 | opensearch: 41 | enabled: ${OPENSEARCH_ENABLED:false} 42 | host: ${OPENSEARCH_HOST:localhost} 43 | port: ${OPENSEARCH_PORT:9200} 44 | scheme: ${OPENSEARCH_SCHEME:http} 45 | username: ${OPENSEARCH_USERNAME:admin} 46 | password: ${OPENSEARCH_PASSWORD:admin} 47 | 48 | server: 49 | port: ${SERVER_PORT} 50 | 51 | logging: 52 | level: 53 | org.springframework.security: ${SECURITY_DEBUG:DEBUG} 54 | 55 | aws: 56 | access.key: ${AWS_ACCESS_KEY} 57 | secret.key: ${AWS_SECRET_KEY} 58 | s3.bucket: ${AWS_S3_BUCKET} 59 | region: ${AWS_REGION} 60 | 61 | # CORS Configuration - All settings loaded from environment variables 62 | # See CorsFilter.java in filter package for implementation 63 | cors: 64 | allowed-origins: ${CORS_ALLOWED_ORIGINS:http://localhost:3000} 65 | allowed-methods: ${CORS_ALLOWED_METHODS:GET,POST,PUT,DELETE,OPTIONS} 66 | allowed-headers: ${CORS_ALLOWED_HEADERS:Authorization,Cache-Control,Content-Type} 67 | allow-credentials: ${CORS_ALLOW_CREDENTIALS:true} 68 | max-age: ${CORS_MAX_AGE:3600} 69 | 70 | jwt: 71 | secret: ${JWT_SECRET} 72 | expiration: ${JWT_EXPIRATION:86400000} 73 | 74 | management: 75 | endpoints: 76 | web: 77 | exposure: 78 | include: "*" 79 | health: 80 | mail: 81 | enabled: ${MAIL_HEALTH} 82 | redis: 83 | enabled: ${REDIS_HEALTH} 84 | metrics: 85 | export: 86 | prometheus: 87 | enabled: ${PROMETHEUS_METRICS_EXPORT} 88 | 89 | #twilio: 90 | # accountSid: ${TWILIO_ACCOUNT_SID} 91 | # authToken: ${TWILIO_AUTH_TOKEN} 92 | # fromPhoneNumber: ${TWILIO_FROM_PHONE_NUMBER} -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/impl/MedicineFindingServiceIMPL.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.service.impl; 2 | 3 | import com.lifepill.possystem.dto.BranchDTO; 4 | import com.lifepill.possystem.dto.ItemCategoryDTO; 5 | import com.lifepill.possystem.dto.responseDTO.MedicineGetResponseDTO; 6 | import com.lifepill.possystem.entity.Branch; 7 | import com.lifepill.possystem.entity.Item; 8 | import com.lifepill.possystem.exception.NotFoundException; 9 | import com.lifepill.possystem.repo.branchRepository.BranchRepository; 10 | import com.lifepill.possystem.repo.itemRepository.ItemRepository; 11 | import com.lifepill.possystem.service.MedicineFindingService; 12 | import lombok.AllArgsConstructor; 13 | import org.modelmapper.ModelMapper; 14 | import org.springframework.stereotype.Service; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | /** 20 | * Implementation of the MedicineFindingService interface. 21 | * Provides methods to find items (medicines) by name. 22 | */ 23 | @Service 24 | @AllArgsConstructor 25 | public class MedicineFindingServiceIMPL implements MedicineFindingService { 26 | 27 | private ItemRepository itemRepository; 28 | private BranchRepository branchRepository; 29 | private ModelMapper modelMapper; 30 | 31 | /** 32 | * Retrieves a list of MedicineGetResponseDTO objects representing items with the given name. 33 | * 34 | * @param itemName the name of the item to search for 35 | * @return a list of MedicineGetResponseDTO objects representing the found items 36 | * @throws NotFoundException if no items are found with the given name 37 | */ 38 | @Override 39 | public List getItemByName(String itemName) { 40 | List items = itemRepository.findAllByItemName(itemName); 41 | 42 | if (items.isEmpty()) { 43 | throw new NotFoundException("No item found with the name " + itemName); 44 | } 45 | 46 | List medicineGetResponseDTOS = new ArrayList<>(); 47 | 48 | for (Item item : items) { 49 | MedicineGetResponseDTO medicineGetResponseDTO = modelMapper.map(item, MedicineGetResponseDTO.class); 50 | medicineGetResponseDTO.setItemCategoryDTO(modelMapper.map(item.getItemCategory(), ItemCategoryDTO.class)); 51 | 52 | Branch branch = branchRepository.findById(item.getBranchId()).orElse(null); 53 | if (branch != null) { 54 | medicineGetResponseDTO.setBranchDTO(modelMapper.map(branch, BranchDTO.class)); 55 | } 56 | medicineGetResponseDTOS.add(medicineGetResponseDTO); 57 | } 58 | return medicineGetResponseDTOS; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Spring Boot Build and Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | types: [opened, synchronize, reopened] 9 | 10 | jobs: 11 | build: 12 | name: Build and Release 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: write # Ensure the token has permission to write releases 16 | 17 | steps: 18 | # Step 1: Checkout the repository 19 | - name: Checkout code 20 | uses: actions/checkout@v3 21 | with: 22 | fetch-depth: 0 # Fetch all history for SonarCloud analysis 23 | 24 | # Step 2: Set up JDK 17 for Spring Boot 25 | - name: Set up JDK 17 26 | uses: actions/setup-java@v3 27 | with: 28 | java-version: 17 29 | distribution: 'zulu' # Change this to any distribution you prefer 30 | 31 | # Step 3: Cache SonarCloud packages (optional) 32 | - name: Cache SonarCloud packages 33 | uses: actions/cache@v3 34 | with: 35 | path: ~/.sonar/cache 36 | key: ${{ runner.os }}-sonar 37 | restore-keys: ${{ runner.os }}-sonar 38 | 39 | # Step 4: Cache Maven packages for faster builds 40 | - name: Cache Maven packages 41 | uses: actions/cache@v3 42 | with: 43 | path: ~/.m2 44 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 45 | restore-keys: ${{ runner.os }}-m2 46 | 47 | # Step 5: Build and analyze the code with Maven 48 | - name: Build and analyze the Spring Boot project 49 | working-directory: pos-system # Adjust if your backend is in a subdirectory 50 | run: mvn -B clean verify -DskipTests 51 | 52 | # Step 6: Get the version from pom.xml (requires jq) 53 | - name: Get Version from pom.xml 54 | id: get_version 55 | run: | 56 | VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) 57 | echo "VERSION=${VERSION}" >> $GITHUB_ENV 58 | 59 | # Step 7: Generate a unique tag name with timestamp 60 | - name: Generate unique tag name 61 | id: generate_tag 62 | run: | 63 | UNIQUE_TAG="${{ env.VERSION }}-$(date +'%Y%m%d%H%M%S')" 64 | echo "UNIQUE_TAG=${UNIQUE_TAG}" >> $GITHUB_ENV 65 | 66 | # Step 8: Create a new GitHub release 67 | - name: Create GitHub Release 68 | id: create_release 69 | uses: actions/create-release@v1 70 | with: 71 | tag_name: v${{ env.UNIQUE_TAG }} # Use unique tag with version and timestamp 72 | release_name: "Release v${{ env.UNIQUE_TAG }}" # Use unique release name 73 | draft: false 74 | prerelease: false 75 | body: "Automated release created by GitHub Actions" 76 | env: 77 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Use the default GITHUB_TOKEN 78 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/config/ApplicationConfig.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.config; 2 | 3 | import com.lifepill.possystem.repo.employerRepository.EmployerRepository; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | import lombok.RequiredArgsConstructor; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.security.authentication.AuthenticationManager; 9 | import org.springframework.security.authentication.AuthenticationProvider; 10 | import org.springframework.security.authentication.dao.DaoAuthenticationProvider; 11 | import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; 12 | import org.springframework.security.core.userdetails.UserDetailsService; 13 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 14 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 15 | import org.springframework.security.crypto.password.PasswordEncoder; 16 | 17 | /** 18 | * Configuration class for application settings. 19 | */ 20 | @Configuration 21 | @RequiredArgsConstructor 22 | public class ApplicationConfig { 23 | 24 | private final EmployerRepository employerRepository; 25 | 26 | /** 27 | * Provides an instance of BCryptPasswordEncoder for password encoding. 28 | * 29 | * @return BCryptPasswordEncoder instance 30 | */ 31 | @Bean 32 | public PasswordEncoder passwordEncoder() { 33 | return new BCryptPasswordEncoder(); 34 | } 35 | 36 | /** 37 | * Retrieves a user details service based on the employer's email. 38 | * 39 | * @return UserDetailsService implementation 40 | */ 41 | @Bean 42 | public UserDetailsService userDetailsService() { 43 | return username -> employerRepository.findByEmployerEmail(username) 44 | .orElseThrow(() -> new UsernameNotFoundException("Employer not found")); 45 | } 46 | 47 | /** 48 | * Provides an authentication provider using DaoAuthenticationProvider. 49 | * 50 | * @return AuthenticationProvider implementation 51 | */ 52 | @Bean 53 | public AuthenticationProvider authenticationProvider() { 54 | DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); 55 | authProvider.setUserDetailsService(userDetailsService()); 56 | authProvider.setPasswordEncoder(passwordEncoder()); 57 | return authProvider; 58 | } 59 | 60 | /** 61 | * Retrieves an authentication manager based on the authentication configuration. 62 | * 63 | * @param config AuthenticationConfiguration instance 64 | * @return AuthenticationManager instance 65 | * @throws Exception if there is an issue retrieving the authentication manager 66 | */ 67 | @Bean 68 | public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { 69 | return config.getAuthenticationManager(); 70 | } 71 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/EmployerService.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.service; 2 | 3 | 4 | import com.lifepill.possystem.dto.*; 5 | import com.lifepill.possystem.dto.requestDTO.ChangeManagerDTO; 6 | import com.lifepill.possystem.dto.requestDTO.EmployerUpdate.*; 7 | import com.lifepill.possystem.dto.responseDTO.ChangeManagerResponseDTO; 8 | import com.lifepill.possystem.entity.Employer; 9 | import com.lifepill.possystem.entity.enums.Role; 10 | import org.springframework.core.io.InputStreamResource; 11 | import org.springframework.web.multipart.MultipartFile; 12 | 13 | import java.io.IOException; 14 | import java.util.List; 15 | 16 | public interface EmployerService { 17 | 18 | String saveEmployer(EmployerDTO employerDTO); 19 | 20 | String saveEmployerWithoutImage(EmployerWithoutImageDTO employerWithoutImageDTO); 21 | 22 | String updateEmployer(Long cashierId, EmployerAllDetailsUpdateDTO employerAllDetailsUpdateDTO); 23 | 24 | EmployerDTO getEmployerById(long cashierId); 25 | 26 | EmployerS3DTO getEmployerS3ById(long cashierId); 27 | 28 | String deleteEmployer(long cashierId); 29 | 30 | List getAllEmployer(); 31 | 32 | List getAllEmployerByActiveState(boolean activeState); 33 | 34 | String updateEmployerAccountDetails(EmployerUpdateAccountDetailsDTO employerUpdateAccountDetailsDTO); 35 | 36 | String updateEmployerPassword(EmployerPasswordResetDTO employerPasswordResetDTO); 37 | 38 | String updateRecentPin(EmployerRecentPinUpdateDTO employerRecentPinUpdateDTO); 39 | 40 | EmployerWithBankDTO updateEmployerBankAccountDetails(EmployerUpdateBankAccountDTO employerUpdateBankAccountDTO); 41 | 42 | List getAllEmployerBankDetails(); 43 | 44 | EmployerDTO getEmployerByIdWithImage(long employerId); 45 | 46 | byte[] getImageData(long cashierId); 47 | 48 | String updateEmployerBankAccountDetailsByCashierId(long employerId, EmployerUpdateBankAccountDTO employerUpdateBankAccountDTO); 49 | 50 | List getAllEmployerByBranchId(long branchId); 51 | 52 | List getAllEmployerByRole(Role role); 53 | 54 | EmployerDTO getEmployerByUsername(String username); 55 | 56 | EmployerBankDetailsDTO getEmployerBankDetailsById(long employerId); 57 | 58 | List getAllEmployersWithBankDetails(); 59 | 60 | EmployerWithBankDTO getEmployerWithBankDetailsById(long employerId); 61 | 62 | EmployerS3DTO createEmployer(MultipartFile file, Long branchId, EmployerNewDTO employerNewDTO) throws IOException; 63 | 64 | InputStreamResource getEmployerImage(String profileImageUrl); 65 | 66 | void updateEmployerImage(Long employerId, MultipartFile file) throws IOException; 67 | 68 | Employer findByUsername(String username); 69 | 70 | List getEmployersByBranchIdAndRole(long branchId, Role role); 71 | 72 | List getAllManagersByBranchId(long branchId); 73 | 74 | EmployerDTO updateOrCreateBranchManager(long branchId, UpdateManagerDTO employerDTO); 75 | 76 | ChangeManagerResponseDTO changeBranchManager(ChangeManagerDTO changeManagerDTO); 77 | 78 | List getEmployersByBranchId(long branchId); 79 | } 80 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/service/BranchSummaryService.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.service; 2 | 3 | import com.lifepill.possystem.dto.requestDTO.BranchDailySalesSummaryDTO; 4 | import com.lifepill.possystem.dto.responseDTO.AllPharmacySummaryResponseDTO; 5 | import com.lifepill.possystem.dto.responseDTO.DailySalesSummaryDTO; 6 | import com.lifepill.possystem.dto.responseDTO.PharmacyBranchResponseDTO; 7 | 8 | import java.util.Date; 9 | import java.util.List; 10 | 11 | /** 12 | * The interface Branch summary service. 13 | */ 14 | public interface BranchSummaryService { 15 | /** 16 | * Gets all branches with sales. 17 | * 18 | * @return the all branches with sales 19 | */ 20 | List getAllBranchesWithSales(); 21 | 22 | /** 23 | * Gets branch sales by id. 24 | * 25 | * @param branchId the branch id 26 | * @return the branch sales by id 27 | */ 28 | PharmacyBranchResponseDTO getBranchSalesById(long branchId); 29 | 30 | /** 31 | * Retrieves all pharmacy data for a selected date. 32 | * 33 | * @param date The selected date. 34 | * @return List of PharmacyBranchResponseDTO containing pharmacy data for the selected date. 35 | */ 36 | List getPharmacyDataByDate(Date date); 37 | 38 | /** 39 | * Retrieves pharmacy data within the given time period. 40 | * 41 | * @param startDate The start date of the time period. 42 | * @param endDate The end date of the time period. 43 | * @return List of PharmacyBranchResponseDTO containing pharmacy data within the time period. 44 | */ 45 | List getPharmacyDataByTimePeriod(Date startDate, Date endDate); 46 | 47 | /** 48 | * Retrieves monthly sales data. 49 | * 50 | * @return List of PharmacyBranchResponseDTO containing monthly sales data. 51 | */ 52 | List getMonthlySummary(int month, int year); 53 | 54 | /** 55 | * Retrieves a summary of sales for the given year. 56 | * 57 | * @param year The year for which to retrieve the summary. 58 | * @return A list of PharmacyBranchResponseDTO containing the summary of sales for the given year. 59 | */ 60 | List getYearlySummary(int year); 61 | /** 62 | * Retrieves total details of all pharmacy branches. 63 | * 64 | * @return AllPharmacySummaryResponseDTO containing total sales, total orders, total employees, and total branches. 65 | */ 66 | AllPharmacySummaryResponseDTO getAllPharmacySummary(); 67 | 68 | /** 69 | * Retrieves daily sales summary for a specific branch. 70 | * 71 | * This method is responsible for fetching the daily sales summary for a specific branch. 72 | * The summary includes the date, number of orders, and total sales for each day. 73 | * 74 | * @param branchId The ID of the branch for which the daily sales summary is to be fetched. 75 | * @return A list of DailySalesSummaryDTO objects, each representing the sales summary for a specific day. 76 | */ 77 | List getDailySalesSummary(long branchId); 78 | 79 | 80 | List getAllDailySalesSummary(); 81 | } 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build and Release Pharmacy POS System Backend](https://github.com/Life-Pill/pharmacy-pos-frontend/actions/workflows/build.yml/badge.svg)](https://github.com/Life-Pill/pharmacy-pos-frontend/actions/workflows/build.yml) 2 | [![Spring Boot Build and Release](https://github.com/Life-Pill/pharmacy-pos-main-backend/actions/workflows/build.yaml/badge.svg)](https://github.com/Life-Pill/pharmacy-pos-main-backend/actions/workflows/build.yaml) 3 | 4 | # Pharmacy POS System Backend 5 | 6 | ![logo](https://avatars.githubusercontent.com/u/149755096?s=200&v=4) 7 | 8 | ## Description 9 | 10 | The Pharmacy POS System Backend is the server-side component of our comprehensive pharmacy management software. It is developed using Spring Boot, Java, and integrates seamlessly with the frontend built on Electron, React, and Tailwind CSS. This backend system handles various critical functionalities such as database management, API endpoints for communication with the frontend, authentication, security, and business logic implementation. 11 | 12 | ## Features 13 | 14 | - **Database Management:** Utilizes Spring Data JPA for efficient database management, enabling CRUD operations and data manipulation. 15 | 16 | - **API Endpoints:** Provides RESTful API endpoints for communication with the frontend, facilitating seamless data exchange and interaction. 17 | 18 | - **Authentication:** Implements secure authentication mechanisms to ensure only authorized access to the system. 19 | 20 | - **Security:** Incorporates security measures such as input validation, encryption, and access control to protect sensitive data and prevent security breaches. 21 | 22 | - **Business Logic Implementation:** Implements business logic for various pharmacy operations including order processing, inventory management, sales tracking, and employee management. 23 | 24 | - **Integration with Frontend:** Integrates seamlessly with the frontend application, enabling smooth communication and synchronization of data between the frontend and backend systems. 25 | 26 | - **Scalability:** Built with scalability in mind, allowing the system to handle growing data volumes and increasing user demands effectively. 27 | 28 | - **Logging and Monitoring:** Implements logging and monitoring functionalities to track system activities, diagnose errors, and ensure smooth operation. 29 | 30 | - **Testing:** Includes unit tests and integration tests to verify the functionality and reliability of the backend components. 31 | 32 | ## Installation 33 | 34 | 1. Clone the repository: 35 | ```bash 36 | git clone [https://github.com/your-username/pharmacy-pos-system-backend.git](https://github.com/Life-Pill/pharmacy-pos-backend.git) 37 | 38 | 2. Install the dependencies: 39 | ```bash 40 | cd pharmacy-pos-system-backend 41 | mvn install 42 | 43 | 3. Start the application: 44 | ```bash 45 | mvn spring-boot:run 46 | 47 | ## Technologies Used 48 | - Spring 49 | - Spring Boot 50 | - AOP 51 | - Java 52 | - Spring Data JPA 53 | - Maven 54 | - Spring Security 6 55 | - Hibernate 56 | - RESTful API 57 | - RabbitMQ 58 | - Spring Cloud 59 | - Docker 60 | 61 | ## Contributing 62 | - Contributions are welcome! Please follow the contributing guidelines to contribute to this project. 63 | 64 | ## License 65 | - This project is licensed under the Apache License 66 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/filter/JwtAuthFilter.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.filter; 2 | 3 | import com.lifepill.possystem.config.JwtService; 4 | import lombok.NonNull; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 7 | import org.springframework.security.core.context.SecurityContextHolder; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | import org.springframework.security.core.userdetails.UserDetailsService; 10 | import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; 11 | import org.springframework.stereotype.Component; 12 | import org.springframework.web.filter.OncePerRequestFilter; 13 | 14 | import javax.servlet.FilterChain; 15 | import javax.servlet.ServletException; 16 | import javax.servlet.http.HttpServletRequest; 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.io.IOException; 19 | 20 | /** 21 | * The type Jwt auth filter. 22 | */ 23 | @Component 24 | @RequiredArgsConstructor 25 | //@Order(Ordered.HIGHEST_PRECEDENCE) 26 | public class JwtAuthFilter extends OncePerRequestFilter { 27 | private final JwtService jwtService; 28 | private final UserDetailsService userDetailsService; 29 | 30 | @Override 31 | protected void doFilterInternal 32 | (@NonNull HttpServletRequest request, 33 | @NonNull HttpServletResponse response, 34 | @NonNull FilterChain filterChain) 35 | throws ServletException, IOException { 36 | //Verify whether request has Authorization header and it has Bearer in it 37 | final String authHeader = request.getHeader("Authorization"); 38 | final String jwt; 39 | final String email; 40 | if (authHeader == null ||!authHeader.startsWith("Bearer ")) { 41 | filterChain.doFilter(request, response); 42 | return; 43 | } 44 | //Extract jwt from the Authorization 45 | jwt = authHeader.substring(7); 46 | //Verify whether user is present in db 47 | //Verify whether token is valid 48 | email = jwtService.extractUsername(jwt); 49 | //If user is present and no authentication object in securityContext 50 | if(email != null && SecurityContextHolder.getContext().getAuthentication() == null) { 51 | UserDetails userDetails = this.userDetailsService.loadUserByUsername(email); 52 | //If valid set to security context holder 53 | UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken( 54 | userDetails, 55 | null, 56 | userDetails.getAuthorities() 57 | ); 58 | authToken.setDetails( 59 | new WebAuthenticationDetailsSource().buildDetails(request) 60 | ); 61 | SecurityContextHolder.getContext().setAuthentication(authToken); 62 | } 63 | filterChain.doFilter(request, response); 64 | } 65 | 66 | //Verify if it is whitelisted path and if yes don't do anything 67 | @Override 68 | protected boolean shouldNotFilter(@NonNull HttpServletRequest request) throws ServletException { 69 | return request.getServletPath().contains("/lifepill/v1/auth"); 70 | } 71 | } -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/advisor/AppWideExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.advisor; 2 | 3 | import com.lifepill.possystem.exception.NotFoundException; 4 | import com.lifepill.possystem.util.StandardResponse; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.dao.DataIntegrityViolationException; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.web.bind.annotation.ExceptionHandler; 11 | import org.springframework.web.bind.annotation.RestControllerAdvice; 12 | 13 | /** 14 | * Global exception handler for handling application-wide exceptions. 15 | */ 16 | @RestControllerAdvice 17 | public class AppWideExceptionHandler { 18 | 19 | private static final Logger logger = LoggerFactory.getLogger(AppWideExceptionHandler.class); 20 | 21 | /** 22 | * Handles NotFoundException by returning a ResponseEntity with a corresponding error message. 23 | * @param e The NotFoundException that was thrown 24 | * @return ResponseEntity with a StandardResponse containing the error details 25 | */ 26 | @ExceptionHandler(NotFoundException.class) 27 | public ResponseEntity handleNotFoundException(NotFoundException e) { 28 | logger.warn("Resource not found: {}", e.getMessage()); 29 | 30 | return ResponseEntity.status(HttpStatus.NOT_FOUND) 31 | .body(new StandardResponse( 32 | HttpStatus.NOT_FOUND.value(), 33 | "Error", 34 | e.getMessage() 35 | )); 36 | } 37 | 38 | /** 39 | * Handles DataIntegrityViolationException by returning a ResponseEntity with a corresponding error message. 40 | * @param ex The DataIntegrityViolationException that was thrown 41 | * @return ResponseEntity with a StandardResponse containing the error details 42 | */ 43 | @ExceptionHandler(DataIntegrityViolationException.class) 44 | public ResponseEntity handleDataIntegrityViolationException(DataIntegrityViolationException ex) { 45 | logger.error("Data integrity violation: {}", ex.getMessage()); 46 | 47 | return ResponseEntity.status(HttpStatus.CONFLICT) 48 | .body(new StandardResponse( 49 | HttpStatus.CONFLICT.value(), 50 | "DATA_INTEGRITY_ERROR", 51 | "A conflict occurred while processing your request." 52 | )); 53 | } 54 | 55 | /** 56 | * Handles general exceptions by returning a ResponseEntity with a generic error message. 57 | * @param ex The exception that was thrown 58 | * @return ResponseEntity with a StandardResponse containing the error details 59 | */ 60 | @ExceptionHandler(Exception.class) 61 | public ResponseEntity handleGeneralException(Exception ex) { 62 | logger.error("Unhandled exception", ex); 63 | 64 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) 65 | .body(new StandardResponse( 66 | HttpStatus.INTERNAL_SERVER_ERROR.value(), 67 | "INTERNAL_SERVER_ERROR", 68 | "An unexpected error occurred. Please try again later." 69 | )); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/controller/ItemCategoryController.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.controller; 2 | 3 | import com.lifepill.possystem.dto.ItemCategoryDTO; 4 | import com.lifepill.possystem.service.ItemService; 5 | import com.lifepill.possystem.util.StandardResponse; 6 | import lombok.AllArgsConstructor; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * Controller class for managing item category-related operations. 15 | */ 16 | @RestController 17 | @RequestMapping("/lifepill/v1/item-Category") 18 | @AllArgsConstructor 19 | public class ItemCategoryController { 20 | 21 | private ItemService itemService; 22 | 23 | /** 24 | * Saves a new item category. 25 | * 26 | * @param categoryDTO The DTO containing details of the item category to be saved. 27 | * @return ResponseEntity containing a StandardResponse object with a success message. 28 | */ 29 | @PostMapping(path = "/save") 30 | public ResponseEntity saveCategory(@RequestBody ItemCategoryDTO categoryDTO) { 31 | 32 | String message = itemService.saveCategory(categoryDTO); 33 | return new ResponseEntity<>( 34 | new StandardResponse(201, "Success", message), 35 | HttpStatus.CREATED); 36 | } 37 | 38 | /** 39 | * Retrieves all item categories. 40 | * 41 | * @return ResponseEntity containing a StandardResponse object with a list of all item categories. 42 | */ 43 | @GetMapping("/all-category") 44 | public ResponseEntity getAllCategories() { 45 | List categories = itemService.getAllCategories(); 46 | return new ResponseEntity<>( 47 | new StandardResponse(200, "Success", categories), 48 | HttpStatus.OK 49 | ); 50 | } 51 | 52 | /** 53 | * Updates details of an item category. 54 | * 55 | * @param categoryId The ID of the category to update. 56 | * @param categoryDTO The DTO containing updated details of the category. 57 | * @return ResponseEntity containing a StandardResponse object with a success message. 58 | */ 59 | @PutMapping("/update/{categoryId}") 60 | public ResponseEntity updateCategoryDetails( 61 | @PathVariable long categoryId, 62 | @RequestBody ItemCategoryDTO categoryDTO 63 | ) { 64 | String message = itemService.updateCategoryDetails(categoryId, categoryDTO); 65 | return new ResponseEntity<>( 66 | new StandardResponse(200, "Success", message), 67 | HttpStatus.OK); 68 | } 69 | 70 | /** 71 | * Deletes an item category. 72 | * 73 | * @param categoryId The ID of the category to delete. 74 | * @return ResponseEntity containing a StandardResponse object with a success message. 75 | * */ 76 | @DeleteMapping("/delete/{categoryId}") 77 | public ResponseEntity deleteCategory(@PathVariable long categoryId) { 78 | String message = itemService.deleteCategory(categoryId); 79 | return new ResponseEntity<>( 80 | new StandardResponse(200, "Success", message), 81 | HttpStatus.OK); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /pos-system/src/test/java/stepDefinition/MedicineFindingStepDefinitions.java: -------------------------------------------------------------------------------- 1 | /* 2 | package stepDefinition; 3 | 4 | import com.lifepill.possystem.dto.responseDTO.MedicineGetResponseDTO; 5 | import com.lifepill.possystem.entity.Item; 6 | import com.lifepill.possystem.exception.NotFoundException; 7 | import com.lifepill.possystem.service.MedicineFindingService; 8 | import com.lifepill.possystem.util.StandardResponse; 9 | import io.cucumber.java.en.Given; 10 | import io.cucumber.java.en.Then; 11 | import io.cucumber.java.en.When; 12 | import org.junit.Before; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; 15 | import org.springframework.boot.test.context.SpringBootTest; 16 | import org.springframework.boot.test.web.client.TestRestTemplate; 17 | import org.springframework.http.HttpStatus; 18 | import org.springframework.http.ResponseEntity; 19 | import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 20 | import org.springframework.web.util.DefaultUriBuilderFactory; 21 | 22 | import java.util.List; 23 | 24 | import static org.junit.jupiter.api.Assertions.*; 25 | 26 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 27 | @AutoConfigureWebTestClient 28 | public class MedicineFindingStepDefinitions { 29 | 30 | @Autowired 31 | private TestRestTemplate restTemplate; 32 | 33 | private ResponseEntity responseEntity; 34 | 35 | 36 | 37 | @Given("a list of existing medicines") 38 | public void a_list_of_existing_medicines() { 39 | // the test database is pre-populated with medicines 40 | 41 | } 42 | 43 | @When("the client requests to find medicines by name {string}") 44 | public void the_client_requests_to_find_medicines_by_name(String itemName) { 45 | try { 46 | responseEntity = restTemplate.getForEntity("/lifepill/v1/medicine-finding/find-medicine?itemName=" + itemName, StandardResponse.class); 47 | } catch (NotFoundException e) { 48 | responseEntity = new ResponseEntity<>(new StandardResponse(404, e.getMessage(), null), HttpStatus.NOT_FOUND); 49 | } 50 | } 51 | 52 | @Then("the response should contain a list of medicines with the name {string}") 53 | public void the_response_should_contain_a_list_of_medicines_with_the_name(String itemName) { 54 | List medicines = (List) responseEntity.getBody().getData(); 55 | assertFalse(medicines.isEmpty()); 56 | for (MedicineGetResponseDTO medicine : medicines) { 57 | assertEquals(itemName, medicine.getItemName()); 58 | } 59 | } 60 | 61 | @Then("the response should contain an error message {string}") 62 | public void the_response_should_contain_an_error_message(String errorMessage) { 63 | assertEquals(errorMessage, responseEntity.getBody().getMessage()); 64 | } 65 | 66 | @Then("the response should have a success status code") 67 | public void the_response_should_have_a_success_status_code() { 68 | assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); 69 | } 70 | 71 | @Then("the response should have an error status code") 72 | public void the_response_should_have_an_error_status_code() { 73 | assertEquals(HttpStatus.NOT_FOUND, responseEntity.getStatusCode()); 74 | } 75 | }*/ 76 | -------------------------------------------------------------------------------- /pos-system/src/main/java/com/lifepill/possystem/controller/SupplierController.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.controller; 2 | 3 | import com.lifepill.possystem.dto.SupplierDTO; 4 | import com.lifepill.possystem.service.SupplierService; 5 | import lombok.AllArgsConstructor; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.web.bind.annotation.*; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Controller for managing suppliers. 14 | */ 15 | @RestController 16 | @RequestMapping("/lifepill/v1/supplier") 17 | @AllArgsConstructor 18 | public class SupplierController { 19 | 20 | private SupplierService supplierService; 21 | 22 | /** 23 | * Retrieves all suppliers. 24 | * 25 | * @return ResponseEntity containing a list of all suppliers. 26 | */ 27 | @GetMapping(path = "/get-all-suppliers") 28 | public ResponseEntity> getAllSuppliers() { 29 | List suppliers = supplierService.getAllSuppliers(); 30 | return new ResponseEntity<>(suppliers, HttpStatus.OK); 31 | } 32 | 33 | 34 | /** 35 | * Saves a new supplier. 36 | * 37 | * @param supplierDTO The supplier DTO to be saved. 38 | * @return ResponseEntity containing the saved supplier DTO. 39 | */ 40 | @PostMapping(path = "/save") 41 | public ResponseEntity saveSupplier(@RequestBody SupplierDTO supplierDTO) { 42 | SupplierDTO savedSupplier = supplierService.saveSupplier(supplierDTO); 43 | return new ResponseEntity<>(savedSupplier, HttpStatus.CREATED); 44 | } 45 | 46 | /** 47 | * Updates a supplier's details by their ID. 48 | * 49 | * @param id The ID of the supplier to update. 50 | * @param updatedSupplierDTO The updated SupplierDTO containing new details. 51 | * @return ResponseEntity containing the updated SupplierDTO with HTTP status OK if successful, or BAD_REQUEST if the update fails. 52 | */ 53 | 54 | @PutMapping(path ="/update-supplier/{id}") 55 | public ResponseEntity updateSupplierById(@PathVariable("id") long id, @RequestBody SupplierDTO updatedSupplierDTO) { 56 | SupplierDTO updatedSupplier = supplierService.updateSupplierById(id, updatedSupplierDTO); 57 | return new ResponseEntity<>(updatedSupplier, HttpStatus.OK); 58 | } 59 | 60 | /** 61 | * Retrieves a supplier by their ID. 62 | * 63 | * @param id The ID of the supplier to retrieve. 64 | * @return ResponseEntity containing the retrieved SupplierDTO with HTTP status OK if found, or NOT_FOUND if not found. 65 | */ 66 | @GetMapping(path ="get-supplier/{id}") 67 | public ResponseEntity getSupplierById(@PathVariable("id") long id) { 68 | SupplierDTO supplierDTO = supplierService.getSupplierById(id); 69 | return new ResponseEntity<>(supplierDTO, HttpStatus.OK); 70 | } 71 | 72 | /** 73 | * Deletes a supplier by their ID. 74 | * 75 | * @param id The ID of the supplier to delete. 76 | * @return ResponseEntity with HTTP status NO_CONTENT if the deletion is successful, or BAD_REQUEST if the deletion fails. 77 | */ 78 | 79 | @DeleteMapping(path = "/delete-supplier/{id}") 80 | public ResponseEntity deleteSupplierById(@PathVariable("id") long id) { 81 | supplierService.deleteSupplierById(id); 82 | return new ResponseEntity<>(HttpStatus.NO_CONTENT); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /pos-system/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent any 3 | 4 | tools { 5 | jdk 'Java17' 6 | maven 'maven_3_9_6' 7 | dockerTool 'docker' 8 | } 9 | 10 | stages { 11 | stage("Cleanup Workspace") { 12 | steps { 13 | cleanWs() 14 | } 15 | } 16 | 17 | stage("Checkout from SCM") { 18 | steps { 19 | git branch: 'main', credentialsId: 'github', url: 'https://github.com/Life-Pill/pharmacy-pos-backend' 20 | } 21 | } 22 | 23 | stage("Build Application") { 24 | steps { 25 | dir('pos-system') { 26 | sh "mvn clean package" 27 | } 28 | } 29 | } 30 | 31 | stage("Test Application") { 32 | steps { 33 | dir('pos-system') { 34 | sh "mvn test" 35 | } 36 | } 37 | } 38 | 39 | stage('Build docker image'){ 40 | steps{ 41 | dir('pos-system') { 42 | sh 'docker build -t pramithamj/pos-system:latest .' 43 | } 44 | } 45 | } 46 | 47 | stage('Stop and Remove Existing Container') { 48 | steps { 49 | sh 'docker stop java_container || true' 50 | sh 'docker rm java_container || true' 51 | } 52 | } 53 | 54 | stage('Run Docker container') { 55 | steps { 56 | sh 'docker run -d --name java_container pramithamj/pos-system:latest' 57 | } 58 | } 59 | 60 | stage('Check Docker containers') { 61 | steps { 62 | sh 'docker ps' 63 | } 64 | } 65 | 66 | stage("Unit Tests") { 67 | steps { 68 | dir('pos-system') { 69 | sh "mvn test" 70 | } 71 | } 72 | } 73 | stage("SonarQube Analysis"){ 74 | steps{ 75 | withSonarQubeEnv(credentialsId: 'jenkins-sonarqube-token', installationName: 'SonarQube') { 76 | dir('pos-system') { 77 | sh "mvn sonar:sonar" 78 | } 79 | } 80 | } 81 | } 82 | stage('Qodana') { 83 | environment { 84 | QODANA_TOKEN = credentials('qodana-token') 85 | } 86 | agent { 87 | docker { 88 | args ''' 89 | -v "${WORKSPACE}":/data/project 90 | --entrypoint="" 91 | ''' 92 | image 'jetbrains/qodana-jvm' 93 | } 94 | } 95 | when { 96 | branch 'main' 97 | branch 'dev' 98 | branch 'mobileDev' 99 | } 100 | steps { 101 | sh '''qodana''' 102 | } 103 | } 104 | } 105 | 106 | post { 107 | always { 108 | // Clean up Docker resources 109 | script { 110 | sh 'docker rmi --force pramithamj/pos-system:latest || true' 111 | } 112 | } 113 | success { 114 | echo 'Pipeline succeeded!' 115 | } 116 | failure { 117 | echo 'Pipeline failed!' 118 | } 119 | } 120 | } -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/possystem/controller/BranchManagerControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.lifepill.possystem.controller; 2 | 3 | import com.lifepill.possystem.dto.EmployerDTO; 4 | import com.lifepill.possystem.service.EmployerService; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.mockito.InjectMocks; 8 | import org.mockito.Mock; 9 | import org.mockito.Mockito; 10 | import org.mockito.junit.MockitoJUnitRunner; 11 | import org.springframework.http.HttpStatus; 12 | import org.springframework.http.ResponseEntity; 13 | 14 | import java.util.Arrays; 15 | import java.util.List; 16 | 17 | import static org.junit.jupiter.api.Assertions.assertEquals; 18 | 19 | /** 20 | * Unit tests for the BranchManagerController class. 21 | */ 22 | @RunWith(MockitoJUnitRunner.class) 23 | public class BranchManagerControllerTest { 24 | 25 | @InjectMocks 26 | private BranchManagerController branchManagerController; 27 | 28 | @Mock 29 | private EmployerService employerService; 30 | 31 | /** 32 | * Test for getting all cashiers by branch ID when there are cashiers. 33 | */ 34 | @Test 35 | public void testGetAllCashiersByBranchId() { 36 | // Mock data 37 | int branchId = 1; 38 | List mockEmployers = Arrays.asList( 39 | new EmployerDTO(), 40 | new EmployerDTO() 41 | ); 42 | 43 | // Mock employerService.getAllEmployerByBranchId to return mockEmployers 44 | Mockito.when(employerService.getAllEmployerByBranchId(branchId)).thenReturn(mockEmployers); 45 | 46 | // Call the controller method 47 | ResponseEntity> responseEntity = branchManagerController.getAllCashiersByBranchId(branchId); 48 | 49 | // Verify the response 50 | assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); 51 | assertEquals(mockEmployers, responseEntity.getBody()); 52 | } 53 | 54 | /** 55 | * Test for getting all cashiers by branch ID when there are no cashiers. 56 | */ 57 | @Test 58 | public void testGetAllCashiersByBranchIdEmpty() { 59 | // Mock data 60 | int branchId = 1; 61 | List mockEmployers = Arrays.asList(); 62 | 63 | // Mock employerService.getAllEmployerByBranchId to return mockEmployers 64 | Mockito.when(employerService.getAllEmployerByBranchId(branchId)).thenReturn(mockEmployers); 65 | 66 | // Call the controller method 67 | ResponseEntity> responseEntity = branchManagerController.getAllCashiersByBranchId(branchId); 68 | 69 | // Verify the response 70 | assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); 71 | assertEquals(mockEmployers, responseEntity.getBody()); 72 | } 73 | 74 | /** 75 | * Test for getting all cashiers by branch ID when the result is null. 76 | */ 77 | @Test 78 | public void testGetAllCashiersByBranchIdNull() { 79 | // Mock data 80 | int branchId = 1; 81 | 82 | // Mock employerService.getAllEmployerByBranchId to return null 83 | Mockito.when(employerService.getAllEmployerByBranchId(branchId)).thenReturn(null); 84 | 85 | // Call the controller method 86 | ResponseEntity> responseEntity = branchManagerController.getAllCashiersByBranchId(branchId); 87 | 88 | // Verify the response 89 | assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); 90 | assertEquals(null, responseEntity.getBody()); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /pos-system/src/test/java/com/lifepill/possystem/repo/EmployerRepositoryTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | package com.lifepill.possystem.repo; 3 | 4 | import com.lifepill.possystem.entity.Employer; 5 | import com.lifepill.possystem.entity.enums.Role; 6 | import com.lifepill.possystem.repo.employerRepository.EmployerRepository; 7 | import org.junit.jupiter.api.BeforeEach; 8 | import org.junit.jupiter.api.DisplayName; 9 | import org.junit.jupiter.api.Test; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.boot.test.context.SpringBootTest; 12 | 13 | import java.util.Date; 14 | import java.util.List; 15 | 16 | import static com.lifepill.possystem.entity.enums.Gender.MALE; 17 | import static org.assertj.core.api.Assertions.assertThat; 18 | import static org.junit.jupiter.api.Assertions.*; 19 | 20 | @SpringBootTest 21 | public class EmployerRepositoryTests { 22 | @Autowired 23 | private EmployerRepository employerRepository; 24 | 25 | @BeforeEach 26 | public void setUp() { 27 | employerRepository.deleteAll(); 28 | } 29 | 30 | @Test 31 | @DisplayName("Save Employer Operation") 32 | public void givenCashier_whenSave_thenReturnSavedCashier() { 33 | // Given Employer data 34 | Employer employer = com.lifepill.possystem.entity.Employer.builder() 35 | .employerNicName("JohnDoe") 36 | .employerFirstName("John") 37 | .employerLastName("Doe") 38 | .employerPassword("password") 39 | .employerEmail("john.doe@example.com") 40 | .employerPhone("1234567890") 41 | .employerAddress("123 Main Street") 42 | .employerSalary(50000.0) 43 | .employerNic("123456789012") 44 | .isActiveStatus(true) 45 | .pin(1234) 46 | .gender(MALE) 47 | .dateOfBirth(new Date()) 48 | .role(Role.CASHIER) 49 | .build(); 50 | 51 | // When save employer data 52 | Employer savedEmployer = employerRepository.save(employer); 53 | 54 | // Then return Employer data 55 | assertNotNull(savedEmployer.getEmployerId()); 56 | assertEquals("JohnDoe", savedEmployer.getEmployerNicName()); 57 | assertEquals("John", savedEmployer.getEmployerFirstName()); 58 | assertEquals("Doe", savedEmployer.getEmployerLastName()); 59 | assertEquals("password", savedEmployer.getEmployerPassword()); 60 | assertEquals("john.doe@example.com", savedEmployer.getEmployerEmail()); 61 | assertEquals("1234567890", savedEmployer.getEmployerPhone()); 62 | assertEquals("123 Main Street", savedEmployer.getEmployerAddress()); 63 | assertEquals(50000.0, savedEmployer.getEmployerSalary()); 64 | assertEquals("123456789012", savedEmployer.getEmployerNic()); 65 | assertTrue(savedEmployer.isActiveStatus()); 66 | assertEquals(1234, savedEmployer.getPin()); 67 | assertEquals(MALE, savedEmployer.getGender()); 68 | assertEquals(Role.CASHIER, savedEmployer.getRole()); 69 | 70 | // fetch the saved employer from the database and assert its values 71 | Employer retrievedEmployer = employerRepository.findById(savedEmployer.getEmployerId()).orElse(null); 72 | assertNotNull(retrievedEmployer); 73 | assertEquals(savedEmployer, retrievedEmployer); 74 | } 75 | 76 | @Test 77 | @DisplayName("Get All Cashiers Operation") 78 | public void givenNoCashiers_whenFindAll_thenReturnEmptyList() { 79 | // When finding all Cashiers 80 | List allEmployers = employerRepository.findAll(); 81 | 82 | // Then the list should be empty 83 | assertThat(allEmployers).isEmpty(); 84 | } 85 | 86 | 87 | } 88 | */ 89 | --------------------------------------------------------------------------------