From 49dc19cd0415f2666ea6082831bed082c7b69bae Mon Sep 17 00:00:00 2001 From: vladp Date: Fri, 30 Jan 2026 12:52:16 +0700 Subject: [PATCH] dev add tariff and temp flag for files --- .../soune/nocopy/dto/tarriff/TariffDTO.java | 19 ++++ .../nocopy/dto/tarriff/TariffInfoDTO.java | 19 ++++ .../soune/nocopy/entity/company/Company.java | 5 + .../soune/nocopy/entity/file/FileStatus.java | 3 +- .../ru/soune/nocopy/entity/tarif/Tariff.java | 42 +++++++ .../soune/nocopy/entity/tarif/TariffInfo.java | 34 ++++++ .../nocopy/entity/tarif/TariffStatus.java | 5 + .../soune/nocopy/entity/tarif/TariffType.java | 6 + .../soune/nocopy/entity/user/Permission.java | 30 +++++ .../ru/soune/nocopy/entity/user/User.java | 60 ++++++++-- .../exception/TariffNotFoundException.java | 7 ++ .../repository/TariffInfoRepository.java | 9 ++ .../nocopy/repository/TariffRepository.java | 16 +++ .../nocopy/service/file/FileStatsService.java | 8 +- .../service/file/FileUploadService.java | 3 +- .../file/impl/FileUploadServiceImpl.java | 8 +- .../nocopy/service/register/AuthService.java | 46 ++++++-- .../service/tariff/TariffConstants.java | 15 +++ .../service/tariff/TariffInfoService.java | 105 ++++++++++++++++++ .../tariff/TariffInitializationService.java | 98 ++++++++++++++++ .../nocopy/service/tariff/TariffService.java | 98 ++++++++++++++++ 21 files changed, 612 insertions(+), 24 deletions(-) create mode 100644 src/main/java/ru/soune/nocopy/dto/tarriff/TariffDTO.java create mode 100644 src/main/java/ru/soune/nocopy/dto/tarriff/TariffInfoDTO.java create mode 100644 src/main/java/ru/soune/nocopy/entity/tarif/Tariff.java create mode 100644 src/main/java/ru/soune/nocopy/entity/tarif/TariffInfo.java create mode 100644 src/main/java/ru/soune/nocopy/entity/tarif/TariffStatus.java create mode 100644 src/main/java/ru/soune/nocopy/entity/tarif/TariffType.java create mode 100644 src/main/java/ru/soune/nocopy/entity/user/Permission.java create mode 100644 src/main/java/ru/soune/nocopy/exception/TariffNotFoundException.java create mode 100644 src/main/java/ru/soune/nocopy/repository/TariffInfoRepository.java create mode 100644 src/main/java/ru/soune/nocopy/repository/TariffRepository.java create mode 100644 src/main/java/ru/soune/nocopy/service/tariff/TariffConstants.java create mode 100644 src/main/java/ru/soune/nocopy/service/tariff/TariffInfoService.java create mode 100644 src/main/java/ru/soune/nocopy/service/tariff/TariffInitializationService.java create mode 100644 src/main/java/ru/soune/nocopy/service/tariff/TariffService.java diff --git a/src/main/java/ru/soune/nocopy/dto/tarriff/TariffDTO.java b/src/main/java/ru/soune/nocopy/dto/tarriff/TariffDTO.java new file mode 100644 index 0000000..0748a9f --- /dev/null +++ b/src/main/java/ru/soune/nocopy/dto/tarriff/TariffDTO.java @@ -0,0 +1,19 @@ +package ru.soune.nocopy.dto.tarriff; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class TariffDTO { + private Long id; + private String type; + private String name; + private double price; + private int tokens; + private int maxFilesCount; + private Long diskSize; + private Long maxUsers; +} diff --git a/src/main/java/ru/soune/nocopy/dto/tarriff/TariffInfoDTO.java b/src/main/java/ru/soune/nocopy/dto/tarriff/TariffInfoDTO.java new file mode 100644 index 0000000..64a4461 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/dto/tarriff/TariffInfoDTO.java @@ -0,0 +1,19 @@ +package ru.soune.nocopy.dto.tarriff; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class TariffInfoDTO { + private String id; + private String status; + private LocalDateTime startTariff; + private LocalDateTime endTariff; + private Long tariffId; + private String tariffName; +} \ No newline at end of file diff --git a/src/main/java/ru/soune/nocopy/entity/company/Company.java b/src/main/java/ru/soune/nocopy/entity/company/Company.java index a7cc176..09faf32 100644 --- a/src/main/java/ru/soune/nocopy/entity/company/Company.java +++ b/src/main/java/ru/soune/nocopy/entity/company/Company.java @@ -5,6 +5,7 @@ import jakarta.persistence.*; import jakarta.validation.constraints.Size; import lombok.*; import org.springframework.data.annotation.CreatedDate; +import ru.soune.nocopy.entity.tarif.TariffInfo; import ru.soune.nocopy.entity.user.User; import java.time.LocalDateTime; @@ -46,4 +47,8 @@ public class Company { @JsonIgnore @ToString.Exclude private List users = new ArrayList<>(); + + @OneToOne(cascade = CascadeType.ALL) + @JoinColumn(name = "tariff_info_id") + private TariffInfo tariffInfo; } diff --git a/src/main/java/ru/soune/nocopy/entity/file/FileStatus.java b/src/main/java/ru/soune/nocopy/entity/file/FileStatus.java index b0b2351..cdd4fc1 100644 --- a/src/main/java/ru/soune/nocopy/entity/file/FileStatus.java +++ b/src/main/java/ru/soune/nocopy/entity/file/FileStatus.java @@ -6,5 +6,6 @@ public enum FileStatus { PROCESSING, VIOLATION, CHECKED, - ERROR + ERROR, + TEMP } diff --git a/src/main/java/ru/soune/nocopy/entity/tarif/Tariff.java b/src/main/java/ru/soune/nocopy/entity/tarif/Tariff.java new file mode 100644 index 0000000..45b3654 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/entity/tarif/Tariff.java @@ -0,0 +1,42 @@ +package ru.soune.nocopy.entity.tarif; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Entity +@Table(name = "tariff") +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +public class Tariff { + + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "type") + private String type; + + @Column(name = "tariff_name") + private String name; + + @Column(name = "price") + private double price; + + @Column(name = "tokens") + private int tokens; + + @Column(name = "max_files_count") + private int maxFilesCount; + + @Column(name = "disk_size") + private Long diskSize; + + @Column(name = "max_users") + private Long maxUsers; +} diff --git a/src/main/java/ru/soune/nocopy/entity/tarif/TariffInfo.java b/src/main/java/ru/soune/nocopy/entity/tarif/TariffInfo.java new file mode 100644 index 0000000..9900595 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/entity/tarif/TariffInfo.java @@ -0,0 +1,34 @@ +package ru.soune.nocopy.entity.tarif; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.time.LocalDateTime; + +@Entity +@Table(name = "tariff_info") +@AllArgsConstructor +@NoArgsConstructor +@Getter @Setter +public class TariffInfo { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private String id; + + @Column(name = "status", nullable = false) + private TariffStatus status; + + @Column(name = "start_tariff") + private LocalDateTime startTariff; + + @Column(name = "end_tariff") + private LocalDateTime endTariff; + + @ManyToOne + @JoinColumn(name = "tariff_id") + private Tariff tariff; +} \ No newline at end of file diff --git a/src/main/java/ru/soune/nocopy/entity/tarif/TariffStatus.java b/src/main/java/ru/soune/nocopy/entity/tarif/TariffStatus.java new file mode 100644 index 0000000..95794d1 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/entity/tarif/TariffStatus.java @@ -0,0 +1,5 @@ +package ru.soune.nocopy.entity.tarif; + +public enum TariffStatus { + ACTIVE, EXPIRED, INACTIVE +} diff --git a/src/main/java/ru/soune/nocopy/entity/tarif/TariffType.java b/src/main/java/ru/soune/nocopy/entity/tarif/TariffType.java new file mode 100644 index 0000000..5158cb4 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/entity/tarif/TariffType.java @@ -0,0 +1,6 @@ +package ru.soune.nocopy.entity.tarif; + + +public enum TariffType { + START, BASIC, PRO, ENTERPRISE, DEMO; +} \ No newline at end of file diff --git a/src/main/java/ru/soune/nocopy/entity/user/Permission.java b/src/main/java/ru/soune/nocopy/entity/user/Permission.java new file mode 100644 index 0000000..b6ed9b8 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/entity/user/Permission.java @@ -0,0 +1,30 @@ +package ru.soune.nocopy.entity.user; + +public class Permission { + public static final long LOGIN_BIT = 1L << 0; + public static final long COMPANY_SETTINGS_BIT = 1L << 1; + public static final long DEFAULT_USER_PERMISSIONS = LOGIN_BIT; + public static final long COMPANY_ADMIN_PERMISSIONS = + LOGIN_BIT | COMPANY_SETTINGS_BIT; + public static final long SUPER_ADMIN_PERMISSIONS = -1L; + + public static boolean hasPermission(long userPermissions, long permissionBit) { + return (userPermissions & permissionBit) != 0; + } + + public static long addPermission(long userPermissions, long permissionBit) { + return userPermissions | permissionBit; + } + + public static long removePermission(long userPermissions, long permissionBit) { + return userPermissions & ~permissionBit; + } + + public static boolean canLogin(long userPermissions) { + return hasPermission(userPermissions, LOGIN_BIT); + } + + public static boolean canManageCompanySettings(long userPermissions) { + return hasPermission(userPermissions, COMPANY_SETTINGS_BIT); + } +} diff --git a/src/main/java/ru/soune/nocopy/entity/user/User.java b/src/main/java/ru/soune/nocopy/entity/user/User.java index b839e2d..b3bd024 100644 --- a/src/main/java/ru/soune/nocopy/entity/user/User.java +++ b/src/main/java/ru/soune/nocopy/entity/user/User.java @@ -8,6 +8,8 @@ import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import ru.soune.nocopy.entity.company.Company; import ru.soune.nocopy.entity.file.Violation; +import ru.soune.nocopy.entity.tarif.TariffInfo; +import ru.soune.nocopy.entity.tarif.TariffStatus; import java.time.LocalDate; import java.time.LocalDateTime; @@ -68,9 +70,6 @@ public class User { @Column(name = "is_active") private boolean isActive = false; - @Column(name = "permissions") - private Long userPermissions; - @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) @JsonIgnore @ToString.Exclude @@ -90,6 +89,56 @@ public class User { @JsonIgnore private ProtectedFileCheck protectedFileCheck; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "company_id") + @ToString.Exclude + private Company company; + + @Column(name = "permissions") + private Long userPermissions = Permission.DEFAULT_USER_PERMISSIONS; + + @OneToOne(cascade = CascadeType.ALL) + @JoinColumn(name = "personal_tariff_info_id") + @ToString.Exclude + private TariffInfo personalTariffInfo; + + public TariffInfo getActiveTariffInfo() { + if (company != null && company.getTariffInfo() != null) { + return company.getTariffInfo(); + } + return personalTariffInfo; + } + + public boolean hasTariffAccess() { + TariffInfo activeTariff = getActiveTariffInfo(); + if (activeTariff == null) { + return false; + } + + return activeTariff.getStatus() == TariffStatus.ACTIVE && + LocalDateTime.now().isBefore(activeTariff.getEndTariff()); + } + + public boolean canLogin() { + return Permission.canLogin(this.userPermissions); + } + + public boolean canManageCompanySettings() { + return Permission.canManageCompanySettings(this.userPermissions); + } + + public void grantPermission(long permissionBit) { + this.userPermissions = Permission.addPermission(this.userPermissions, permissionBit); + } + + public void removePermission(long permissionBit) { + this.userPermissions = Permission.removePermission(this.userPermissions, permissionBit); + } + + public boolean hasPermission(long permissionBit) { + return Permission.hasPermission(this.userPermissions, permissionBit); + } + public String getCompanyName() { if (company != null) { return company.getCompanyName(); @@ -97,9 +146,4 @@ public class User { return null; } } - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "company_id") - @ToString.Exclude - private Company company; } diff --git a/src/main/java/ru/soune/nocopy/exception/TariffNotFoundException.java b/src/main/java/ru/soune/nocopy/exception/TariffNotFoundException.java new file mode 100644 index 0000000..cc41574 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/exception/TariffNotFoundException.java @@ -0,0 +1,7 @@ +package ru.soune.nocopy.exception; + +public class TariffNotFoundException extends RuntimeException { + public TariffNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/ru/soune/nocopy/repository/TariffInfoRepository.java b/src/main/java/ru/soune/nocopy/repository/TariffInfoRepository.java new file mode 100644 index 0000000..a74bd87 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/repository/TariffInfoRepository.java @@ -0,0 +1,9 @@ +package ru.soune.nocopy.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import ru.soune.nocopy.entity.tarif.TariffInfo; + +@Repository +public interface TariffInfoRepository extends JpaRepository { +} diff --git a/src/main/java/ru/soune/nocopy/repository/TariffRepository.java b/src/main/java/ru/soune/nocopy/repository/TariffRepository.java new file mode 100644 index 0000000..f31295c --- /dev/null +++ b/src/main/java/ru/soune/nocopy/repository/TariffRepository.java @@ -0,0 +1,16 @@ +package ru.soune.nocopy.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import ru.soune.nocopy.entity.tarif.Tariff; +import ru.soune.nocopy.entity.tarif.TariffType; + +import java.util.List; +import java.util.Optional; + +@Repository +public interface TariffRepository extends JpaRepository { + Optional findByType(TariffType type); + List findAllByOrderByPriceAsc(); + Tariff findByName(String name); +} diff --git a/src/main/java/ru/soune/nocopy/service/file/FileStatsService.java b/src/main/java/ru/soune/nocopy/service/file/FileStatsService.java index 8e98f13..a1b973d 100644 --- a/src/main/java/ru/soune/nocopy/service/file/FileStatsService.java +++ b/src/main/java/ru/soune/nocopy/service/file/FileStatsService.java @@ -60,14 +60,14 @@ public class FileStatsService { private Long calculateTotalSize(List files) { return files.stream() - .filter(file -> file.getStatus() != FileStatus.DELETED) + .filter(file -> file.getStatus() != FileStatus.DELETED && file.getStatus() != FileStatus.TEMP) .mapToLong(FileEntity::getFileSize) .sum(); } private Integer calculateTotalCount(List files) { return (int) files.stream() - .filter(file -> file.getStatus() != FileStatus.DELETED) + .filter(file -> file.getStatus() != FileStatus.DELETED && file.getStatus() != FileStatus.TEMP) .count(); } @@ -79,7 +79,7 @@ public class FileStatsService { private Long calculateMediaSize(List files, FileType fileType) { return files.stream() - .filter(file -> file.getStatus() != FileStatus.DELETED) + .filter(file -> file.getStatus() != FileStatus.DELETED && file.getStatus() != FileStatus.TEMP) .filter(file -> isFileType(file, fileType)) .mapToLong(FileEntity::getFileSize) .sum(); @@ -87,7 +87,7 @@ public class FileStatsService { private Integer calculateMediaCount(List files, FileType fileType) { return (int) files.stream() - .filter(file -> file.getStatus() != FileStatus.DELETED) + .filter(file -> file.getStatus() != FileStatus.DELETED && file.getStatus() != FileStatus.TEMP) .filter(file -> isFileType(file, fileType)) .count(); } diff --git a/src/main/java/ru/soune/nocopy/service/file/FileUploadService.java b/src/main/java/ru/soune/nocopy/service/file/FileUploadService.java index de8d09d..1ae1a28 100644 --- a/src/main/java/ru/soune/nocopy/service/file/FileUploadService.java +++ b/src/main/java/ru/soune/nocopy/service/file/FileUploadService.java @@ -2,6 +2,7 @@ package ru.soune.nocopy.service.file; import org.springframework.web.multipart.MultipartFile; import ru.soune.nocopy.dto.file.UploadProgressResponse; +import ru.soune.nocopy.entity.file.FileStatus; import ru.soune.nocopy.entity.file.FileUploadSession; import java.io.IOException; @@ -18,5 +19,5 @@ public interface FileUploadService { UploadProgressResponse getUploadProgress(String uploadId); - void completeFileProcessingAsync(FileUploadSession session); + void completeFileProcessingAsync(FileUploadSession session, FileStatus status); } diff --git a/src/main/java/ru/soune/nocopy/service/file/impl/FileUploadServiceImpl.java b/src/main/java/ru/soune/nocopy/service/file/impl/FileUploadServiceImpl.java index c7b1391..8f02cee 100644 --- a/src/main/java/ru/soune/nocopy/service/file/impl/FileUploadServiceImpl.java +++ b/src/main/java/ru/soune/nocopy/service/file/impl/FileUploadServiceImpl.java @@ -215,7 +215,7 @@ public class FileUploadServiceImpl implements FileUploadService { @Async("fileUploadTaskExecutor") @Transactional @Override - public void completeFileProcessingAsync(FileUploadSession session) { + public void completeFileProcessingAsync(FileUploadSession session, FileStatus status) { try { Path filePath = Paths.get(session.getFilePath()); String checksum = calculateChecksum(filePath); @@ -231,7 +231,7 @@ public class FileUploadServiceImpl implements FileUploadService { .checksum(checksum) .uploadSessionId(session.getUploadId()) .protectionStatus(ProtectionStatus.PROCESSING) - .status(FileStatus.ACTIVE) + .status(status) .build(); FileEntity saved = fileEntityRepository.save(fileEntity); @@ -317,7 +317,9 @@ public class FileUploadServiceImpl implements FileUploadService { session.setStatus(UploadStatus.COMPLETED); session.setFilePath(finalFilePath); - completeFileProcessingAsync(session); + FileStatus status = findSimilar == 0 ? FileStatus.ACTIVE: FileStatus.TEMP; + + completeFileProcessingAsync(session, status); } else { sessionRepository.save(session); diff --git a/src/main/java/ru/soune/nocopy/service/register/AuthService.java b/src/main/java/ru/soune/nocopy/service/register/AuthService.java index ee8cf9e..ab64e8c 100644 --- a/src/main/java/ru/soune/nocopy/service/register/AuthService.java +++ b/src/main/java/ru/soune/nocopy/service/register/AuthService.java @@ -10,14 +10,20 @@ import ru.soune.nocopy.dto.register.LoginAnswer; import ru.soune.nocopy.dto.register.LoginRequest; import ru.soune.nocopy.dto.register.RegRequest; import ru.soune.nocopy.entity.company.Company; +import ru.soune.nocopy.entity.tarif.TariffInfo; +import ru.soune.nocopy.entity.tarif.TariffType; import ru.soune.nocopy.entity.user.AuthToken; +import ru.soune.nocopy.entity.user.Permission; import ru.soune.nocopy.entity.user.User; import ru.soune.nocopy.exception.NotFoundAuthToken; import ru.soune.nocopy.exception.NotValidFieldException; import ru.soune.nocopy.repository.AuthTokenRepository; import ru.soune.nocopy.repository.CompanyRepository; +import ru.soune.nocopy.repository.TariffInfoRepository; import ru.soune.nocopy.repository.UserRepository; import ru.soune.nocopy.service.file.CheckCounterService; +import ru.soune.nocopy.service.tariff.TariffInfoService; +import ru.soune.nocopy.service.tariff.TariffService; import java.security.SecureRandom; import java.time.LocalDateTime; @@ -37,6 +43,10 @@ public class AuthService { private final CheckCounterService checkCounterService; + private final TariffInfoRepository tariffInfoRepository; + + private final TariffInfoService tariffInfoService; + private final SecureRandom secureRandom = new SecureRandom(); @Transactional @@ -48,20 +58,20 @@ public class AuthService { user.setActive(true); user.setEmailVerified(true); - if (registerRequest.getCompanyName() != null && - AccountType.valueOf(registerRequest.getAccountType().toUpperCase()).equals(AccountType.B2B)) { - Company company = new Company(); - company.setCompanyName(registerRequest.getCompanyName()); + AccountType accountType = AccountType.valueOf(registerRequest.getAccountType().toUpperCase()); - companyRepository.save(company); - - user.setCompany(company); + if (accountType == AccountType.B2B && registerRequest.getCompanyName() != null) { + createCompanyAccount(registerRequest, user); + } else { + createIndividualAccount(user); } if (registerRequest.getPhone() != null) { user.setPhone(registerRequest.getPhone()); } + user.grantPermission(Permission.LOGIN_BIT); + User savedUser = userRepository.save(user); AuthToken authToken = genereateAuthToken(savedUser); @@ -138,4 +148,26 @@ public class AuthService { secureRandom.nextBytes(bytes); return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes); } + + private void createCompanyAccount(RegRequest request, User user) { + Company company = new Company(); + company.setCompanyName(request.getCompanyName()); + + TariffInfo companyTariff = tariffInfoService.createTariffInfo(TariffType.DEMO); + company.setTariffInfo(companyTariff); + + companyRepository.save(company); + tariffInfoService.addTariffInfo(companyTariff); + + user.setCompany(company); + user.grantPermission(Permission.COMPANY_SETTINGS_BIT); + } + + private void createIndividualAccount(User user) { + TariffInfo personalTariff = tariffInfoService.createTariffInfo(TariffType.DEMO); + + tariffInfoService.addTariffInfo(personalTariff); + + user.setPersonalTariffInfo(personalTariff); + } } diff --git a/src/main/java/ru/soune/nocopy/service/tariff/TariffConstants.java b/src/main/java/ru/soune/nocopy/service/tariff/TariffConstants.java new file mode 100644 index 0000000..c2c27dd --- /dev/null +++ b/src/main/java/ru/soune/nocopy/service/tariff/TariffConstants.java @@ -0,0 +1,15 @@ +package ru.soune.nocopy.service.tariff; + +public class TariffConstants { + public static final double DEMO_PRICE = 0; + public static final double BASIC_PRICE = 100; + public static final double START_PRICE = 200; + public static final double PRO_PRICE = 300; + public static final double ENTERPRISE_PRICE = 400; + + public static final Integer DEMO_TOKENS = 10; + public static final Integer BASIC_TOKENS = 100; + public static final Integer START_TOKENS = 200; + public static final Integer PRO_TOKENS = 300; + public static final Integer ENTERPRISE_TOKENS = 400; +} diff --git a/src/main/java/ru/soune/nocopy/service/tariff/TariffInfoService.java b/src/main/java/ru/soune/nocopy/service/tariff/TariffInfoService.java new file mode 100644 index 0000000..90df795 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/service/tariff/TariffInfoService.java @@ -0,0 +1,105 @@ +package ru.soune.nocopy.service.tariff; + +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.soune.nocopy.dto.tarriff.TariffInfoDTO; +import ru.soune.nocopy.entity.tarif.Tariff; +import ru.soune.nocopy.entity.tarif.TariffInfo; +import ru.soune.nocopy.entity.tarif.TariffStatus; +import ru.soune.nocopy.entity.tarif.TariffType; +import ru.soune.nocopy.exception.TariffNotFoundException; +import ru.soune.nocopy.repository.TariffInfoRepository; +import ru.soune.nocopy.repository.TariffRepository; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@AllArgsConstructor +public class TariffInfoService { + + private TariffInfoRepository tariffInfoRepository; + + private TariffRepository tariffRepository; + + public TariffInfo createTariffInfo(LocalDateTime startTariff, LocalDateTime endTariff, TariffStatus tariffStatus) { + TariffInfo tariffInfo = new TariffInfo(); + tariffInfo.setStartTariff(startTariff); + tariffInfo.setStatus(tariffStatus); + tariffInfo.setEndTariff(endTariff); + + return tariffInfoRepository.save(tariffInfo); + } + + public TariffInfo createTariffInfo(TariffType tariffType) { + Tariff tariff = tariffRepository.findByType(tariffType).orElseThrow(); + + TariffInfo tariffInfo = createTariffInfo(LocalDateTime.now(), LocalDateTime.now().plusDays(30), + TariffStatus.ACTIVE); + tariffInfo.setTariff(tariff); + + return tariffInfoRepository.save(tariffInfo); + } + + public void addTariffInfo(TariffInfo tariffInfo) { + tariffInfoRepository.save(tariffInfo); + } + + public List getAllTariffInfos() { + return tariffInfoRepository.findAll() + .stream() + .map(this::convertToInfoDTO) + .collect(Collectors.toList()); + } + + public TariffInfoDTO getTariffInfoById(String id) { + return tariffInfoRepository.findById(id) + .map(this::convertToInfoDTO) + .orElseThrow(() -> new TariffNotFoundException("Tariff info not found")); + } + + @Transactional + public TariffInfoDTO createTariffInfo(TariffInfoDTO tariffInfoDTO) { + TariffInfo tariffInfo = new TariffInfo(); + updateTariffInfoFromDTO(tariffInfo, tariffInfoDTO); + return convertToInfoDTO(tariffInfoRepository.save(tariffInfo)); + } + + @Transactional + public TariffInfoDTO updateTariffInfo(String id, TariffInfoDTO tariffInfoDTO) { + TariffInfo tariffInfo = tariffInfoRepository.findById(id) + .orElseThrow(() -> new TariffNotFoundException("Tariff not found")); + updateTariffInfoFromDTO(tariffInfo, tariffInfoDTO); + return convertToInfoDTO(tariffInfoRepository.save(tariffInfo)); + } + + @Transactional + public void deleteTariffInfo(String id) { + tariffInfoRepository.deleteById(id); + } + + private TariffInfoDTO convertToInfoDTO(TariffInfo tariffInfo) { + return new TariffInfoDTO( + tariffInfo.getId(), + tariffInfo.getStatus().name(), + tariffInfo.getStartTariff(), + tariffInfo.getEndTariff(), + tariffInfo.getTariff() != null ? tariffInfo.getTariff().getId() : null, + tariffInfo.getTariff() != null ? tariffInfo.getTariff().getName() : null + ); + } + + private void updateTariffInfoFromDTO(TariffInfo tariffInfo, TariffInfoDTO dto) { + tariffInfo.setStatus(TariffStatus.valueOf(dto.getStatus())); + tariffInfo.setStartTariff(dto.getStartTariff()); + tariffInfo.setEndTariff(dto.getEndTariff()); + + if (dto.getTariffId() != null) { + Tariff tariff = tariffRepository.findById(dto.getTariffId()) + .orElseThrow(() -> new TariffNotFoundException("Tariff not found")); + tariffInfo.setTariff(tariff); + } + } +} diff --git a/src/main/java/ru/soune/nocopy/service/tariff/TariffInitializationService.java b/src/main/java/ru/soune/nocopy/service/tariff/TariffInitializationService.java new file mode 100644 index 0000000..47fd615 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/service/tariff/TariffInitializationService.java @@ -0,0 +1,98 @@ +package ru.soune.nocopy.service.tariff; + +import lombok.RequiredArgsConstructor; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.soune.nocopy.entity.tarif.Tariff; +import ru.soune.nocopy.entity.tarif.TariffType; +import ru.soune.nocopy.repository.TariffRepository; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +@RequiredArgsConstructor +public class TariffInitializationService { + + private final TariffRepository tariffRepository; + + @EventListener(ApplicationReadyEvent.class) + @Transactional + public void initializeDefaultTariffs() { + List existingTariffs = tariffRepository.findAll(); + + if (existingTariffs.isEmpty()) { + createDefaultTariffs(); + } else { + Map existingTypes = new HashMap<>(); + existingTariffs.forEach(tariff -> existingTypes.put(TariffType.valueOf(tariff.getType()), true)); + + Arrays.stream(TariffType.values()) + .filter(type -> !existingTypes.containsKey(type)) + .forEach(this::createDefaultTariff); + } + } + + private void createDefaultTariffs() { + Arrays.stream(TariffType.values()) + .forEach(this::createDefaultTariff); + } + + private void createDefaultTariff(TariffType type) { + Tariff tariff = new Tariff(); + tariff.setType(type.name()); + + switch (type) { + case DEMO: + tariff.setName("Демо"); + tariff.setPrice(TariffConstants.DEMO_PRICE); + tariff.setTokens(TariffConstants.DEMO_TOKENS); + tariff.setMaxFilesCount(10); + tariff.setDiskSize(1024L * 1024 * 100); + tariff.setMaxUsers(1L); + break; + + case START: + tariff.setName("Стартовый"); + tariff.setPrice(TariffConstants.START_PRICE); + tariff.setTokens(TariffConstants.START_TOKENS); + tariff.setMaxFilesCount(50); + tariff.setDiskSize(1024L * 1024 * 500); + tariff.setMaxUsers(3L); + break; + + case BASIC: + tariff.setName("Базовый"); + tariff.setPrice(TariffConstants.BASIC_PRICE); + tariff.setTokens(TariffConstants.BASIC_TOKENS); + tariff.setMaxFilesCount(200); + tariff.setDiskSize(1024L * 1024 * 1024 * 2L); + tariff.setMaxUsers(10L); + break; + + case PRO: + tariff.setName("Профессиональный"); + tariff.setPrice(TariffConstants.PRO_PRICE); + tariff.setTokens(TariffConstants.PRO_TOKENS); + tariff.setMaxFilesCount(1000); + tariff.setDiskSize(1024L * 1024 * 1024 * 10L); + tariff.setMaxUsers(25L); + break; + + case ENTERPRISE: + tariff.setName("Корпоративный"); + tariff.setPrice(TariffConstants.ENTERPRISE_PRICE); + tariff.setTokens(TariffConstants.ENTERPRISE_TOKENS); + tariff.setMaxFilesCount(5000); + tariff.setDiskSize(1024L * 1024 * 1024 * 50L); + tariff.setMaxUsers(100L); + break; + } + + tariffRepository.save(tariff); + } +} diff --git a/src/main/java/ru/soune/nocopy/service/tariff/TariffService.java b/src/main/java/ru/soune/nocopy/service/tariff/TariffService.java new file mode 100644 index 0000000..0b5879f --- /dev/null +++ b/src/main/java/ru/soune/nocopy/service/tariff/TariffService.java @@ -0,0 +1,98 @@ +package ru.soune.nocopy.service.tariff; + +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.soune.nocopy.dto.tarriff.TariffDTO; +import ru.soune.nocopy.entity.tarif.Tariff; +import ru.soune.nocopy.entity.tarif.TariffType; +import ru.soune.nocopy.exception.TariffNotFoundException; +import ru.soune.nocopy.repository.TariffRepository; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +@AllArgsConstructor +public class TariffService { + + private final TariffRepository tariffRepository; + + public Tariff addTariff(String tariffName, double price, String type, int tokens, long diskSize, long maxUsers, + int maxFilesCount) { + Tariff tariff = new Tariff(); + tariff.setName(tariffName); + tariff.setPrice(price); + tariff.setType(type); + tariff.setTokens(tokens); + tariff.setDiskSize(diskSize); + tariff.setMaxUsers(maxUsers); + tariff.setMaxFilesCount(maxFilesCount); + + return tariffRepository.save(tariff); + } + + public List getAllTariffs() { + return tariffRepository.findAllByOrderByPriceAsc() + .stream() + .map(this::convertToDTO) + .collect(Collectors.toList()); + } + + public TariffDTO getTariffById(Long id) { + return tariffRepository.findById(id) + .map(this::convertToDTO) + .orElseThrow(() -> new TariffNotFoundException("Tariff not found")); + } + + public TariffDTO getTariffByType(TariffType type) { + return tariffRepository.findByType(type) + .map(this::convertToDTO) + .orElseThrow(() -> new TariffNotFoundException("Tariff not found")); + } + + @Transactional + public TariffDTO createTariff(TariffDTO tariffDTO) { + Tariff tariff = new Tariff(); + updateTariffFromDTO(tariff, tariffDTO); + + return convertToDTO(tariffRepository.save(tariff)); + } + + @Transactional + public TariffDTO updateTariff(Long id, TariffDTO tariffDTO) { + Tariff tariff = tariffRepository.findById(id) + .orElseThrow(() -> new TariffNotFoundException("Tariff not found")); + updateTariffFromDTO(tariff, tariffDTO); + + return convertToDTO(tariffRepository.save(tariff)); + } + + @Transactional + public void deleteTariff(Long id) { + tariffRepository.deleteById(id); + } + + private TariffDTO convertToDTO(Tariff tariff) { + return new TariffDTO( + tariff.getId(), + tariff.getType(), + tariff.getName(), + tariff.getPrice(), + tariff.getTokens(), + tariff.getMaxFilesCount(), + tariff.getDiskSize(), + tariff.getMaxUsers() + ); + } + + private void updateTariffFromDTO(Tariff tariff, TariffDTO dto) { + tariff.setType(dto.getType()); + tariff.setName(dto.getName()); + tariff.setPrice(dto.getPrice()); + tariff.setTokens(dto.getTokens()); + tariff.setMaxFilesCount(dto.getMaxFilesCount()); + tariff.setDiskSize(dto.getDiskSize()); + tariff.setMaxUsers(dto.getMaxUsers()); + } +}