6 Commits

Author SHA1 Message Date
Jose
3573f862eb moved: huertos to its own repo 2026-03-07 00:03:50 +01:00
Jose
39d75aecf9 add: pastes entity, controller and service 2026-03-05 18:37:49 +01:00
Jose
6949d8e083 fix: cache evict when updating 2026-03-04 22:55:07 +01:00
Jose
db27bcc1f7 fix: member editing unimplemented 2026-03-04 22:10:45 +01:00
Jose
e0807e4539 Merge remote-tracking branch 'origin/dev' into dev 2026-02-24 02:40:44 +01:00
Jose
fbdaa35087 Add: complete MPaste service rewritten in Spring 2026-02-24 02:40:31 +01:00
90 changed files with 28 additions and 5046 deletions

View File

@@ -1,10 +1,10 @@
#!/bin/bash
cd core/
cd core/ || exit
mvn clean package
cd ..
cd huertos/
cd mpaste/ || exit
mvn clean package
cd ..
scp core/target/core-1.0.0.jar jomaa@10.0.0.254:/home/jomaa/transfer
scp huertos/target/huertos-1.0.0.jar jomaa@10.0.0.254:/home/jomaa/transfer
scp core/target/core-*.jar jomaa@10.0.0.254:/home/jomaa/transfer
scp mpaste/target/mpaste-*.jar jomaa@10.0.0.254:/home/jomaa/transfer

1
cine/.gitignore vendored
View File

@@ -1 +0,0 @@
/target/

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="AdditionalModuleElements">
<content url="file://$MODULE_DIR$" dumb="true">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
</content>
</component>
</module>

View File

@@ -1,59 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.miarma</groupId>
<artifactId>backend</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>cine</artifactId>
<repositories>
<repository>
<id>gitea</id>
<url>https://git.miarma.net/api/packages/Gallardo7761/maven</url>
</repository>
</repositories>
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<scope>runtime</scope>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>

View File

@@ -44,14 +44,6 @@ public class CredentialController {
);
}
@GetMapping("/test/{userId}")
public ResponseEntity<String> test(@PathVariable("userId") UUID userId) {
CorePrincipal principal = (CorePrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return ResponseEntity.ok(
userId.equals(principal.getUserId()) ? "OK" : "NO"
);
}
@GetMapping("/user/{userId}")
public ResponseEntity<List<CredentialDto>> getByUserId(@PathVariable("userId") UUID userId) {
CorePrincipal principal = (CorePrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
@@ -90,6 +82,19 @@ public class CredentialController {
);
}
@PutMapping("/{credential_id}/full")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<CredentialDto> updateFull(
@PathVariable("credential_id") UUID credentialId,
@RequestBody CredentialDto dto
) {
return ResponseEntity.ok(
CredentialMapper.toDto(
credentialService.update(credentialId, CredentialMapper.toEntity(dto))
)
);
}
@GetMapping("/{service_id}/{user_id}/status")
public ResponseEntity<Byte> getStatus(@PathVariable("user_id") UUID userId, @PathVariable("service_id") Byte serviceId) {
return ResponseEntity.ok(credentialService.getStatus(userId, serviceId));

1
huertos/.gitignore vendored
View File

@@ -1 +0,0 @@
/target/

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="AdditionalModuleElements">
<content url="file://$MODULE_DIR$" dumb="true">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
</content>
</component>
</module>

View File

@@ -1,102 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.miarma</groupId>
<artifactId>backend</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>huertos</artifactId>
<properties>
<maven.compiler.source>25</maven.compiler.source>
<maven.compiler.target>25</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>gitea</id>
<url>https://git.miarma.net/api/packages/Gallardo7761/maven</url>
</repository>
</repositories>
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-http-client</artifactId>
<version>4.0.1</version>
<scope>compile</scope>
</dependency>
<!-- CACHE -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>net.miarma</groupId>
<artifactId>backlib</artifactId>
<version>1.1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,16 +0,0 @@
package net.miarma.backend.huertos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@EnableCaching
@SpringBootApplication(scanBasePackages = {
"net.miarma.backend.huertos",
"net.miarma.backlib"
})
public class HuertosApplication {
public static void main(String[] args) {
SpringApplication.run(HuertosApplication.class, args);
}
}

View File

@@ -1,73 +0,0 @@
package net.miarma.backend.huertos.client;
import net.miarma.backlib.dto.ApiErrorDto;
import net.miarma.backlib.dto.LoginRequest;
import net.miarma.backlib.dto.LoginResponse;
import net.miarma.backlib.exception.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;
@Component
public class CoreAuthClient {
private final RestTemplate restTemplate;
private final String coreUrl;
public CoreAuthClient(
@Qualifier("authRestTemplate") RestTemplate restTemplate,
@Value("${core.url}") String coreUrl
) {
this.restTemplate = restTemplate;
this.coreUrl = coreUrl;
}
public LoginResponse login(LoginRequest req) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<LoginRequest> requestEntity = new HttpEntity<>(req, headers);
ResponseEntity<LoginResponse> response = restTemplate.exchange(
coreUrl + "/auth/login",
HttpMethod.POST,
requestEntity,
LoginResponse.class
);
if (!response.getStatusCode().is2xxSuccessful()) {
handleError(response);
}
return response.getBody();
}
private void handleError(ResponseEntity<?> response) {
HttpStatusCode statusCode = response.getStatusCode();
if (statusCode.equals(HttpStatus.UNAUTHORIZED)) {
throw new UnauthorizedException("Credenciales no válidas");
} else if (statusCode.equals(HttpStatus.FORBIDDEN)) {
throw new ForbiddenException("Esa cuenta está desactivada");
} else if (statusCode.equals(HttpStatus.NOT_FOUND)) {
throw new NotFoundException("No encontrado");
} else if (statusCode.equals(HttpStatus.BAD_REQUEST)) {
throw new BadRequestException("Datos de solicitud faltantes");
} else if (statusCode.equals(HttpStatus.CONFLICT)) {
throw new ConflictException("Ya existe");
} else if (statusCode.equals(HttpStatus.UNPROCESSABLE_CONTENT)) {
throw new ValidationException("general", "Los datos no tienen formato válido");
} else {
if (statusCode.is4xxClientError()) {
throw new BadRequestException(response.getBody().toString());
} else {
throw new RuntimeException("Error desconocido");
}
}
}
}

View File

@@ -1,191 +0,0 @@
package net.miarma.backend.huertos.client;
import net.miarma.backend.huertos.dto.RequestMetadataDto;
import net.miarma.backend.huertos.model.RequestMetadata;
import net.miarma.backend.huertos.util.UsernameGenerator;
import net.miarma.backlib.dto.*;
import net.miarma.backlib.exception.*;
import net.miarma.backlib.security.PasswordGenerator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import tools.jackson.databind.ObjectMapper;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
@Component
public class HuertosWebClient {
private final RestTemplate restTemplate;
private final String coreUrl;
private final ObjectMapper objectMapper;
public HuertosWebClient(@Qualifier("secureRestTemplate") RestTemplate restTemplate,
@Value("${core.url}") String coreUrl,
ObjectMapper objectMapper) {
this.restTemplate = restTemplate;
this.coreUrl = coreUrl;
this.objectMapper = objectMapper;
}
public UserWithCredentialDto getUserWithCredential(UUID userId, Byte serviceId) {
ResponseEntity<UserWithCredentialDto> response = restTemplate.exchange(
coreUrl + "/users/{user_id}/service/{service_id}",
HttpMethod.GET,
null,
UserWithCredentialDto.class,
userId, serviceId
);
if (!response.getStatusCode().is2xxSuccessful()) {
handleError(response);
}
return response.getBody();
}
public List<UserWithCredentialDto> getAllUsersWithCredentials(Byte serviceId) {
ResponseEntity<UserWithCredentialDto[]> response = restTemplate.exchange(
coreUrl + "/users/service/{service_id}",
HttpMethod.GET,
null,
UserWithCredentialDto[].class,
serviceId
);
if (!response.getStatusCode().is2xxSuccessful()) {
handleError(response);
}
UserWithCredentialDto[] arr = response.getBody();
return arr == null ? List.of() : Arrays.asList(arr);
}
public UserWithCredentialDto createUser(RequestMetadataDto metadataDto) {
// 1. Crear el usuario
CreateUserDto userDto = new CreateUserDto(metadataDto.displayName(), null);
HttpEntity<CreateUserDto> userRequestEntity = new HttpEntity<>(userDto);
ResponseEntity<UserDto> userResponse = restTemplate.exchange(
coreUrl + "/users",
HttpMethod.POST,
userRequestEntity,
UserDto.class
);
if (!userResponse.getStatusCode().is2xxSuccessful()) {
handleError(userResponse);
}
UserDto createdUser = userResponse.getBody();
if (createdUser == null) {
throw new RuntimeException("No se pudo crear al usuario");
}
CreateCredentialDto credDto = new CreateCredentialDto(
createdUser.getUserId(),
(byte) 1,
UsernameGenerator.generate(metadataDto.displayName(), metadataDto.memberNumber()),
metadataDto.email(),
PasswordGenerator.generate(8),
(byte) 1
);
HttpEntity<CreateCredentialDto> credRequestEntity = new HttpEntity<>(credDto);
ResponseEntity<CredentialDto> credResponse = restTemplate.exchange(
coreUrl + "/credentials",
HttpMethod.POST,
credRequestEntity,
CredentialDto.class
);
if (!credResponse.getStatusCode().is2xxSuccessful()) {
handleError(credResponse);
}
CredentialDto createdCred = credResponse.getBody();
if (createdCred == null) {
throw new RuntimeException("No se pudo crear la cuenta del usuario");
}
return new UserWithCredentialDto(createdUser, createdCred);
}
public void deleteUser(UUID userId) {
ResponseEntity<Void> response = restTemplate.exchange(
coreUrl + "/users/{user_id}",
HttpMethod.DELETE,
null,
Void.class,
userId
);
if (!response.getStatusCode().is2xxSuccessful()) {
if (response.getStatusCode() != HttpStatus.NOT_FOUND) {
handleError(response);
}
}
}
public Byte getCredentialStatus(UUID userId, Byte serviceId) {
ResponseEntity<Byte> response = restTemplate.exchange(
coreUrl + "/credentials/{service_id}/{user_id}/status",
HttpMethod.GET,
null,
Byte.class,
serviceId, userId
);
if (!response.getStatusCode().is2xxSuccessful()) {
handleError(response);
}
return response.getBody();
}
public void updateCredentialStatus(UUID userId, Byte serviceId, Byte newStatus) {
ChangeStatusRequest req = new ChangeStatusRequest(newStatus);
HttpEntity<ChangeStatusRequest> requestEntity = new HttpEntity<>(req);
ResponseEntity<Void> response = restTemplate.exchange(
coreUrl + "/credentials/{service_id}/{user_id}/status",
HttpMethod.PUT,
requestEntity,
Void.class,
serviceId, userId
);
if (!response.getStatusCode().is2xxSuccessful()) {
handleError(response);
}
}
private void handleError(ResponseEntity<?> response) {
HttpStatusCode statusCode = response.getStatusCode();
if (statusCode.equals(HttpStatus.UNAUTHORIZED)) {
throw new UnauthorizedException("Credenciales no válidas");
} else if (statusCode.equals(HttpStatus.FORBIDDEN)) {
throw new ForbiddenException("Esa cuenta está desactivada");
} else if (statusCode.equals(HttpStatus.NOT_FOUND)) {
throw new NotFoundException("No encontrado");
} else if (statusCode.equals(HttpStatus.BAD_REQUEST)) {
throw new BadRequestException("Datos de solicitud faltantes");
} else if (statusCode.equals(HttpStatus.CONFLICT)) {
throw new ConflictException("Ya existe");
} else if (statusCode.equals(HttpStatus.UNPROCESSABLE_CONTENT)) {
throw new ValidationException("general", "Los datos no tienen formato válido");
} else {
if (statusCode.is4xxClientError()) {
throw new BadRequestException(response.getBody().toString());
} else {
throw new RuntimeException("Error desconocido");
}
}
}
}

View File

@@ -1,26 +0,0 @@
package net.miarma.backend.huertos.config;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
@Configuration
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager manager = new CaffeineCacheManager(
"members", "memberById", "waitlist",
"metadataByUserId", "metadataByMemberNumber", "metadataExists");
manager.setCaffeine(
Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.maximumSize(10_000)
);
return manager;
}
}

View File

@@ -1,48 +0,0 @@
package net.miarma.backend.huertos.config;
import io.jsonwebtoken.io.IOException;
import net.miarma.backend.huertos.service.CoreAuthService;
import net.miarma.backlib.security.CoreAuthTokenHolder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate authRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new NoOpResponseErrorHandler());
return restTemplate;
}
@Bean
public RestTemplate secureRestTemplate(CoreAuthService coreAuthService) {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add((request, body, execution) -> {
String token = coreAuthService.getToken();
request.getHeaders().setBearerAuth(token);
return execution.execute(request, body);
});
restTemplate.setErrorHandler(new NoOpResponseErrorHandler());
return restTemplate;
}
public static class NoOpResponseErrorHandler implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return false;
}
}
}

View File

@@ -1,70 +0,0 @@
package net.miarma.backend.huertos.config;
import net.miarma.backend.huertos.security.HuertosJwtFilter;
import net.miarma.backlib.http.RestAccessDeniedHandler;
import net.miarma.backlib.http.RestAuthEntryPoint;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfigurationSource;
import java.util.Optional;
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
private final HuertosJwtFilter jwtFilter;
private final RestAuthEntryPoint authEntryPoint;
private final RestAccessDeniedHandler accessDeniedHandler;
private final CorsConfigurationSource corsConfigurationSource;
public SecurityConfig(
HuertosJwtFilter jwtFilter,
RestAuthEntryPoint authEntryPoint,
RestAccessDeniedHandler accessDeniedHandler,
Optional<CorsConfigurationSource> corsConfigurationSource
) {
this.jwtFilter = jwtFilter;
this.authEntryPoint = authEntryPoint;
this.accessDeniedHandler = accessDeniedHandler;
this.corsConfigurationSource = corsConfigurationSource.orElse(null);
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
if (corsConfigurationSource != null) {
http.cors(Customizer.withDefaults());
}
http
.csrf(csrf -> csrf.disable())
.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.exceptionHandling(ex -> ex
.authenticationEntryPoint(authEntryPoint)
.accessDeniedHandler(accessDeniedHandler)
)
.authorizeHttpRequests(auth -> auth
// PUBLICAS
.requestMatchers("/auth/login").permitAll()
.requestMatchers("/users/waitlist/limited").permitAll()
.requestMatchers("/requests").permitAll()
.requestMatchers("/users/latest-number").permitAll()
// PRIVADAS
.anyRequest().authenticated()
);
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}

View File

@@ -1,69 +0,0 @@
package net.miarma.backend.huertos.controller;
import net.miarma.backend.huertos.dto.AnnouncementDto;
import net.miarma.backend.huertos.mapper.AnnouncementMapper;
import net.miarma.backend.huertos.model.Announcement;
import net.miarma.backend.huertos.service.AnnouncementService;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@RestController
@RequestMapping("/announcements")
public class AnnouncementController {
private final AnnouncementService announcementService;
public AnnouncementController(AnnouncementService announcementService) {
this.announcementService = announcementService;
}
@GetMapping
public ResponseEntity<List<AnnouncementDto.Response>> getAll() {
return ResponseEntity.ok(
announcementService.getAll()
.stream()
.map(AnnouncementMapper::toResponse)
.toList()
);
}
@GetMapping("/{announce_id}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<AnnouncementDto.Response> getById(@PathVariable("announce_id") UUID announcementId) {
Announcement announcement = announcementService.getById(announcementId);
return ResponseEntity.ok(AnnouncementMapper.toResponse(announcement));
}
@PutMapping("/{announce_id}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<AnnouncementDto.Response> update(
@PathVariable("announce_id") UUID announcementId,
@RequestBody AnnouncementDto.Request dto
) {
return ResponseEntity.ok(
AnnouncementMapper.toResponse(announcementService.update(announcementId, AnnouncementMapper.toEntity(dto)))
);
}
@PostMapping
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<AnnouncementDto.Response> create(@RequestBody AnnouncementDto.Request dto) {
return ResponseEntity.ok(
AnnouncementMapper.toResponse(
announcementService.create(
AnnouncementMapper.toEntity(dto)
)));
}
@DeleteMapping("/{announce_id}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<Map<String, String>> delete(@PathVariable("announce_id") UUID announcementId) {
announcementService.delete(announcementId);
return ResponseEntity.ok(Map.of("message", "Deleted announcement: " + announcementId));
}
}

View File

@@ -1,47 +0,0 @@
package net.miarma.backend.huertos.controller;
import net.miarma.backend.huertos.dto.BalanceDto;
import net.miarma.backend.huertos.dto.view.VBalanceWithTotalsDto;
import net.miarma.backend.huertos.mapper.BalanceMapper;
import net.miarma.backend.huertos.mapper.view.VBalanceWithTotalsMapper;
import net.miarma.backend.huertos.model.Balance;
import net.miarma.backend.huertos.service.BalanceService;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/balance")
public class BalanceController {
private final BalanceService balanceService;
public BalanceController(BalanceService balanceService) {
this.balanceService = balanceService;
}
@GetMapping
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<BalanceDto> getBalance() {
Balance balance = balanceService.get();
return ResponseEntity.ok(BalanceMapper.toDto(balance));
}
@GetMapping("/with-totals")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<VBalanceWithTotalsDto> getWithTotals() {
return ResponseEntity.ok(VBalanceWithTotalsMapper.toDto(balanceService.getWithTotals()));
}
@PostMapping
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<BalanceDto> setBalance(BalanceDto dto) {
return ResponseEntity.ok(
BalanceMapper.toDto(
balanceService.create(BalanceMapper.toEntity(dto))
)
);
}
}

View File

@@ -1,74 +0,0 @@
package net.miarma.backend.huertos.controller;
import net.miarma.backend.huertos.dto.ExpenseDto;
import net.miarma.backend.huertos.mapper.ExpenseMapper;
import net.miarma.backend.huertos.model.Expense;
import net.miarma.backend.huertos.service.ExpenseService;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@RestController
@RequestMapping("/expenses")
public class ExpenseController {
private ExpenseService expenseService;
public ExpenseController(ExpenseService expenseService) {
this.expenseService = expenseService;
}
@GetMapping
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<List<ExpenseDto.Response>> getAll() {
return ResponseEntity.ok(
expenseService.getAll()
.stream()
.map(ExpenseMapper::toResponse)
.toList()
);
}
@PostMapping
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<ExpenseDto.Response> create(@RequestBody ExpenseDto.Request dto) {
return ResponseEntity.ok(
ExpenseMapper.toResponse(
expenseService.create(
ExpenseMapper.toEntity(dto)
)));
}
@GetMapping("/{expense_id}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<ExpenseDto.Response> getById(@PathVariable("expense_id") UUID expenseId) {
Expense expense = expenseService.getById(expenseId);
return ResponseEntity.ok(ExpenseMapper.toResponse(expense));
}
@PutMapping("/{expense_id}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<ExpenseDto.Response> update(
@PathVariable("expense_id") UUID expenseId,
@RequestBody ExpenseDto.Request dto
) {
Expense updated = expenseService.update(
expenseId,
ExpenseMapper.toEntity(dto)
);
return ResponseEntity.ok(
ExpenseMapper.toResponse(updated)
);
}
@DeleteMapping("/{expense_id}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<Map<String,String>> delete(@PathVariable("expense_id") UUID expenseId) {
expenseService.delete(expenseId);
return ResponseEntity.ok(Map.of("message", "Deleted expense: " + expenseId));
}
}

View File

@@ -1,41 +0,0 @@
package net.miarma.backend.huertos.controller;
import net.miarma.backend.huertos.client.CoreAuthClient;
import net.miarma.backend.huertos.dto.HuertosLoginResponse;
import net.miarma.backend.huertos.mapper.UserMetadataMapper;
import net.miarma.backend.huertos.model.UserMetadata;
import net.miarma.backend.huertos.service.UserMetadataService;
import net.miarma.backlib.dto.LoginRequest;
import net.miarma.backlib.dto.LoginResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/auth")
public class HuertosAuthController {
private final UserMetadataService metadataService;
private final CoreAuthClient authClient;
public HuertosAuthController(UserMetadataService metadataService,
CoreAuthClient authClient) {
this.metadataService = metadataService;
this.authClient = authClient;
}
@PostMapping("/login")
public ResponseEntity<HuertosLoginResponse> login(@RequestBody LoginRequest req) {
LoginResponse coreResponse = authClient.login(req);
UserMetadata metadata = metadataService.getById(coreResponse.user().getUserId());
return ResponseEntity.ok(
new HuertosLoginResponse(
coreResponse.token(),
coreResponse.user(),
coreResponse.account(),
UserMetadataMapper.toDto(metadata)
)
);
}
}

View File

@@ -1,114 +0,0 @@
package net.miarma.backend.huertos.controller;
import net.miarma.backend.huertos.dto.IncomeDto;
import net.miarma.backend.huertos.dto.view.VIncomesWithInfoDto;
import net.miarma.backend.huertos.mapper.IncomeMapper;
import net.miarma.backend.huertos.mapper.view.VIncomesWithInfoMapper;
import net.miarma.backend.huertos.model.Income;
import net.miarma.backend.huertos.service.IncomeService;
import net.miarma.backend.huertos.service.view.VIncomesWithInfoService;
import net.miarma.backlib.security.JwtService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@RestController
@RequestMapping("/incomes")
public class IncomeController {
private IncomeService incomeService;
private VIncomesWithInfoService vIncomesWithInfoService;
private JwtService jwtService;
public IncomeController(IncomeService incomeService, VIncomesWithInfoService vIncomesWithInfoService, JwtService jwtService) {
this.incomeService = incomeService;
this.vIncomesWithInfoService = vIncomesWithInfoService;
this.jwtService = jwtService;
}
@GetMapping
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<List<IncomeDto.Response>> getAll() {
return ResponseEntity.ok(
incomeService.getAll()
.stream()
.map(IncomeMapper::toResponse)
.toList()
);
}
@GetMapping("/with-info")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<List<VIncomesWithInfoDto>> getAllWithInfo() {
return ResponseEntity.ok(
vIncomesWithInfoService.getAll()
.stream()
.map(VIncomesWithInfoMapper::toResponse)
.toList()
);
}
@GetMapping("/mine")
public ResponseEntity<List<IncomeDto.Response>> getMine(@RequestHeader("Authorization") String authHeader) {
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
String token = authHeader.substring(7);
UUID userId;
try {
userId = jwtService.getUserId(token);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
return ResponseEntity.ok(
incomeService.getByUserId(userId)
.stream()
.map(IncomeMapper::toResponse)
.toList()
);
}
@PostMapping
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<IncomeDto.Response> create(@RequestBody IncomeDto.Request dto) {
return ResponseEntity.ok(
IncomeMapper.toResponse(
incomeService.create(
IncomeMapper.toEntity(dto)
)));
}
@GetMapping("/{income_id}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<IncomeDto.Response> getById(@PathVariable("income_id") UUID incomeId) {
Income income = incomeService.getById(incomeId);
return ResponseEntity.ok(IncomeMapper.toResponse(income));
}
@PutMapping("/{income_id}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<IncomeDto.Response> update(
@PathVariable("income_id") UUID incomeId,
@RequestBody IncomeDto.Request dto
) {
IO.println(dto.getCreatedAt());
return ResponseEntity.ok(
IncomeMapper.toResponse(
incomeService.update(
incomeId, IncomeMapper.toEntity(dto))));
}
@DeleteMapping("/{income_id}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<Map<String,String>> delete(@PathVariable("income_id") UUID incomeId) {
incomeService.delete(incomeId);
return ResponseEntity.ok(Map.of("message", "Deleted income: " + incomeId));
}
}

View File

@@ -1,125 +0,0 @@
package net.miarma.backend.huertos.controller;
import net.miarma.backend.huertos.dto.*;
import net.miarma.backend.huertos.dto.view.VIncomesWithInfoDto;
import net.miarma.backend.huertos.mapper.IncomeMapper;
import net.miarma.backend.huertos.mapper.RequestMapper;
import net.miarma.backend.huertos.security.HuertosPrincipal;
import net.miarma.backend.huertos.service.IncomeService;
import net.miarma.backend.huertos.service.MemberService;
import net.miarma.backend.huertos.service.RequestService;
import net.miarma.backlib.security.JwtService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.UUID;
@RestController
@RequestMapping("/users")
public class MemberController {
private final MemberService memberService;
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
@GetMapping
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<List<MemberDto>> getAll() {
return ResponseEntity.ok(memberService.getAll());
}
@GetMapping("/me")
public ResponseEntity<MemberProfileDto> getMe(Authentication authentication) {
if (!(authentication.getPrincipal() instanceof HuertosPrincipal principal)) {
throw new IllegalStateException("Tipo de autenticación inválida");
}
return ResponseEntity.ok(
memberService.getMyProfile(principal.getUserId())
);
}
@GetMapping("/dropdown")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<List<DropdownDto>> getDropdown() {
return ResponseEntity.ok(memberService.getDropdown());
}
@GetMapping("/{user_id:[0-9a-fA-F\\-]{36}}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<MemberDto> getById(@PathVariable("user_id") UUID userId) {
return ResponseEntity.ok(memberService.getById(userId));
}
@GetMapping("/latest-number")
public ResponseEntity<Integer> getLatestNumber() {
return ResponseEntity.ok(memberService.getLatestMemberNumber());
}
@GetMapping("/waitlist")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<List<MemberDto>> getWaitlist() {
return ResponseEntity.ok(memberService.getWaitlist());
}
@GetMapping("/waitlist/limited")
public ResponseEntity<List<WaitlistCensoredDto>> getWaitlistLimited() {
return ResponseEntity.ok(memberService.getWaitlistLimited());
}
@GetMapping("/number/{member_number}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<MemberDto> getByMemberNumber(@PathVariable("member_number") Integer memberNumber) {
return ResponseEntity.ok(memberService.getByMemberNumber(memberNumber));
}
@GetMapping("/number/{member_number}/incomes")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<List<VIncomesWithInfoDto>> getMemberIncomes(@PathVariable("member_number") Integer memberNumber) {
return ResponseEntity.ok(memberService.getIncomes(memberNumber));
}
@GetMapping("/number/{member_number}/has-paid")
public ResponseEntity<Boolean> getMemberHasPaid(@PathVariable("member_number") Integer memberNumber) {
return ResponseEntity.ok(memberService.hasPaid(memberNumber));
}
@GetMapping("/number/{member_number}/has-collaborator")
public ResponseEntity<Boolean> getMemberHasCollaborator(@PathVariable("member_number") Integer memberNumber) {
return ResponseEntity.ok(memberService.hasCollaborator(memberNumber));
}
@GetMapping("/number/{member_number}/has-greenhouse")
public ResponseEntity<Boolean> getMemberHasGreenhouse(@PathVariable("member_number") Integer memberNumber) {
return ResponseEntity.ok(memberService.hasGreenhouse(memberNumber));
}
@GetMapping("/number/{member_number}/has-collaborator-request")
public ResponseEntity<Boolean> getMemberHasCollaboratorRequest(@PathVariable("member_number") Integer memberNumber) {
return ResponseEntity.ok(memberService.hasCollaboratorRequest(memberNumber));
}
@GetMapping("/number/{member_number}/has-greenhouse-request")
public ResponseEntity<Boolean> getMemberHasGreenhouseRequest(@PathVariable("member_number") Integer memberNumber) {
return ResponseEntity.ok(memberService.hasGreenhouseRequest(memberNumber));
}
@GetMapping("/plot/{plot_number}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<MemberDto> getByPlotNumber(@PathVariable("plot_number") Integer plotNumber) {
return ResponseEntity.ok(memberService.getByPlotNumber(plotNumber));
}
@GetMapping("/dni/{dni}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<MemberDto> getByDni(@PathVariable("dni") String dni) {
return ResponseEntity.ok(memberService.getByDni(dni));
}
}

View File

@@ -1,152 +0,0 @@
package net.miarma.backend.huertos.controller;
import net.miarma.backend.huertos.dto.*;
import net.miarma.backend.huertos.mapper.RequestMapper;
import net.miarma.backend.huertos.mapper.RequestMetadataMapper;
import net.miarma.backend.huertos.mapper.RequestWithMetadataMapper;
import net.miarma.backend.huertos.model.Request;
import net.miarma.backend.huertos.service.RequestAcceptanceService;
import net.miarma.backend.huertos.service.RequestService;
import net.miarma.backlib.security.JwtService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/requests")
public class RequestController {
private final RequestService requestService;
private final RequestAcceptanceService requestAcceptanceService;
private final JwtService jwtService;
public RequestController(RequestService requestService,
RequestAcceptanceService requestAcceptanceService,
JwtService jwtService) {
this.requestService = requestService;
this.requestAcceptanceService = requestAcceptanceService;
this.jwtService = jwtService;
}
@GetMapping
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<List<RequestDto.Response>> getAll() {
return ResponseEntity.ok(
requestService.getAll()
.stream()
.map(RequestMapper::toResponse)
.toList()
);
}
@PostMapping
public ResponseEntity<RequestDto.Response> create(@RequestBody RequestDto.Request dto) {
return ResponseEntity.ok(
RequestMapper.toResponse(
requestService.create(
RequestMapper.toEntity(dto)
)));
}
@GetMapping("/count")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<RequestCountDto> getRequestCount() {
return ResponseEntity.ok(
requestService.getAll()
.stream()
.map(RequestMapper::toResponse)
.collect(Collectors.collectingAndThen(
Collectors.counting(),
RequestCountDto::new
))
);
}
@GetMapping("/mine")
public ResponseEntity<List<RequestDto.Response>> getMine(@RequestHeader("Authorization") String authHeader) {
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
String token = authHeader.substring(7);
UUID userId;
try {
userId = jwtService.getUserId(token);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
return ResponseEntity.ok(
requestService.getByUserId(userId)
.stream()
.map(RequestMapper::toResponse)
.toList()
);
}
@GetMapping("/full")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<List<RequestWithMetadataDto>> getAllWithMetadata() {
return ResponseEntity.ok(
requestService.getAll()
.stream()
.map(RequestWithMetadataMapper::toDto)
.toList()
);
}
@GetMapping("/full/{request_id}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<RequestWithMetadataDto> getByIdWithMetadata(
@PathVariable("request_id") UUID requestId) {
Request request = requestService.getById(requestId);
return ResponseEntity.ok(RequestWithMetadataMapper.toDto(request));
}
@GetMapping("/{request_id}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<RequestDto.Response> getById(@PathVariable("request_id") UUID requestId) {
Request request = requestService.getById(requestId);
return ResponseEntity.ok(RequestMapper.toResponse(request));
}
@PutMapping("/{request_id}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<RequestDto.Response> update(
@PathVariable("request_id") UUID requestId,
@RequestBody RequestDto.Request dto
) {
return ResponseEntity.ok(
RequestMapper.toResponse(requestService.update(requestId, RequestMapper.toEntity(dto)))
);
}
@PutMapping("/{request_id}/accept")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<Map<String, String>> acceptRequest(@PathVariable("request_id") UUID requestId) {
Request r = requestAcceptanceService.acceptRequest(requestId);
requestAcceptanceService.handleSideEffects(r);
return ResponseEntity.ok(Map.of("message", "Accepted request: " + r.getRequestId()));
}
@PutMapping("/{request_id}/reject")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<Map<String, String>> rejectRequest(@PathVariable("request_id") UUID requestId) {
Request r = requestService.reject(requestId);
return ResponseEntity.ok(Map.of("message", "Denied request: " + r.getRequestId()));
}
@DeleteMapping("/{request_id}")
@PreAuthorize("hasAnyRole('HUERTOS_ROLE_ADMIN', 'HUERTOS_ROLE_DEV')")
public ResponseEntity<Map<String, String>> delete(@PathVariable("request_id") UUID requestId) {
requestService.delete(requestId);
return ResponseEntity.ok(Map.of("message", "Deleted request: " + requestId));
}
}

View File

@@ -1,89 +0,0 @@
package net.miarma.backend.huertos.dto;
import java.time.Instant;
import java.util.UUID;
public class AnnouncementDto {
public static class Request {
private String body;
private Byte priority;
private UUID publishedBy;
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public Byte getPriority() {
return priority;
}
public void setPriority(Byte priority) {
this.priority = priority;
}
public UUID getPublishedBy() {
return publishedBy;
}
public void setPublishedBy(UUID publishedBy) {
this.publishedBy = publishedBy;
}
}
public static class Response {
private UUID announceId;
private String body;
private Byte priority;
private UUID publishedBy;
private String publishedByName;
private Instant createdAt;
public UUID getAnnounceId() {
return announceId;
}
public void setAnnounceId(UUID announceId) {
this.announceId = announceId;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public Byte getPriority() {
return priority;
}
public void setPriority(Byte priority) {
this.priority = priority;
}
public UUID getPublishedBy() {
return publishedBy;
}
public void setPublishedBy(UUID publishedBy) {
this.publishedBy = publishedBy;
}
public String getPublishedByName() { return publishedByName; }
public void setPublishedByName(String publishedByName) { this.publishedByName = publishedByName; }
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
}
}

View File

@@ -1,43 +0,0 @@
package net.miarma.backend.huertos.dto;
import java.math.BigDecimal;
import java.time.Instant;
public class BalanceDto {
private Byte id;
private BigDecimal initialBank;
private BigDecimal initialCash;
private Instant createdAt;
public Byte getId() {
return id;
}
public void setId(Byte id) {
this.id = id;
}
public BigDecimal getInitialBank() {
return initialBank;
}
public void setInitialBank(BigDecimal initialBank) {
this.initialBank = initialBank;
}
public BigDecimal getInitialCash() {
return initialCash;
}
public void setInitialCash(BigDecimal initialCash) {
this.initialCash = initialCash;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
}

View File

@@ -1,6 +0,0 @@
package net.miarma.backend.huertos.dto;
import java.util.UUID;
public record DropdownDto(UUID userId, Integer memberNumber, String displayName) {
}

View File

@@ -1,130 +0,0 @@
package net.miarma.backend.huertos.dto;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.UUID;
public class ExpenseDto {
public static class Request {
private String concept;
private BigDecimal amount;
private String supplier;
private String invoice;
private Byte type;
private Instant createdAt;
public String getConcept() {
return concept;
}
public void setConcept(String concept) {
this.concept = concept;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public String getSupplier() {
return supplier;
}
public void setSupplier(String supplier) {
this.supplier = supplier;
}
public String getInvoice() {
return invoice;
}
public void setInvoice(String invoice) {
this.invoice = invoice;
}
public Byte getType() {
return type;
}
public void setType(Byte type) {
this.type = type;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
}
public static class Response {
private UUID expenseId;
private String concept;
private BigDecimal amount;
private String supplier;
private String invoice;
private Byte type;
private Instant createdAt;
public UUID getExpenseId() {
return expenseId;
}
public void setExpenseId(UUID expenseId) {
this.expenseId = expenseId;
}
public String getConcept() {
return concept;
}
public void setConcept(String concept) {
this.concept = concept;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public String getSupplier() {
return supplier;
}
public void setSupplier(String supplier) {
this.supplier = supplier;
}
public String getInvoice() {
return invoice;
}
public void setInvoice(String invoice) {
this.invoice = invoice;
}
public Byte getType() {
return type;
}
public void setType(Byte type) {
this.type = type;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
}
}

View File

@@ -1,12 +0,0 @@
package net.miarma.backend.huertos.dto;
import net.miarma.backlib.dto.CredentialDto;
import net.miarma.backlib.dto.UserDto;
public record HuertosLoginResponse(
String token,
UserDto user,
CredentialDto account,
UserMetadataDto metadata
) {
}

View File

@@ -1,139 +0,0 @@
package net.miarma.backend.huertos.dto;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.UUID;
public class IncomeDto {
public static class Request {
private UUID userId;
private Integer memberNumber;
private String concept;
private BigDecimal amount;
private Byte type;
private Byte frequency;
private Instant createdAt;
public Integer getMemberNumber() {
return memberNumber;
}
public void setMemberNumber(Integer memberNumber) {
this.memberNumber = memberNumber;
}
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public String getConcept() {
return concept;
}
public void setConcept(String concept) {
this.concept = concept;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public Byte getType() {
return type;
}
public void setType(Byte type) {
this.type = type;
}
public Byte getFrequency() {
return frequency;
}
public void setFrequency(Byte frequency) {
this.frequency = frequency;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
}
public static class Response {
private UUID incomeId;
private UUID userId;
private String concept;
private BigDecimal amount;
private Byte type;
private Byte frequency;
private Instant createdAt;
public UUID getIncomeId() {
return incomeId;
}
public void setIncomeId(UUID incomeId) {
this.incomeId = incomeId;
}
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public String getConcept() {
return concept;
}
public void setConcept(String concept) {
this.concept = concept;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public Byte getType() {
return type;
}
public void setType(Byte type) {
this.type = type;
}
public Byte getFrequency() {
return frequency;
}
public void setFrequency(Byte frequency) {
this.frequency = frequency;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
}
}

View File

@@ -1,8 +0,0 @@
package net.miarma.backend.huertos.dto;
import net.miarma.backlib.dto.CredentialDto;
import net.miarma.backlib.dto.UserDto;
public record MemberDto(UserDto user,
CredentialDto account,
UserMetadataDto metadata) {}

View File

@@ -1,20 +0,0 @@
package net.miarma.backend.huertos.dto;
import net.miarma.backend.huertos.dto.view.VIncomesWithInfoDto;
import net.miarma.backlib.dto.CredentialDto;
import net.miarma.backlib.dto.UserDto;
import java.util.List;
public record MemberProfileDto(
UserDto user,
CredentialDto account,
UserMetadataDto metadata,
List<RequestDto.Response> requests,
List<VIncomesWithInfoDto> payments,
boolean hasCollaborator,
boolean hasGreenhouse,
boolean hasCollaboratorRequest,
boolean hasGreenhouseRequest
) {
}

View File

@@ -1,5 +0,0 @@
package net.miarma.backend.huertos.dto;
public record RequestCountDto(Long count) {
}

View File

@@ -1,113 +0,0 @@
package net.miarma.backend.huertos.dto;
import jakarta.annotation.Nullable;
import java.time.Instant;
import java.util.UUID;
public class RequestDto {
public static class Request {
private Byte type;
private UUID userId;
private String name;
private RequestMetadataDto metadata;
public Byte getType() {
return type;
}
public void setType(Byte type) {
this.type = type;
}
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public RequestMetadataDto getMetadata() {
return metadata;
}
public void setMetadata(RequestMetadataDto metadata) {
this.metadata = metadata;
}
}
public static class Response {
private UUID requestId;
private Byte type;
private Byte status;
private UUID userId;
private String name;
private RequestMetadataDto metadata;
private Instant createdAt;
public UUID getRequestId() {
return requestId;
}
public void setRequestId(UUID requestId) {
this.requestId = requestId;
}
public Byte getType() {
return type;
}
public void setType(Byte type) {
this.type = type;
}
public Byte getStatus() {
return status;
}
public void setStatus(Byte status) {
this.status = status;
}
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public RequestMetadataDto getMetadata() {
return metadata;
}
public void setMetadata(RequestMetadataDto metadata) {
this.metadata = metadata;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
}
}

View File

@@ -1,20 +0,0 @@
package net.miarma.backend.huertos.dto;
import java.time.Instant;
public record RequestMetadataDto(
Long id,
String displayName,
String dni,
String phone,
String email,
String username,
String address,
String zipCode,
String city,
Integer memberNumber,
Integer plotNumber,
Byte type,
Instant createdAt
) {}

View File

@@ -1,15 +0,0 @@
package net.miarma.backend.huertos.dto;
import java.time.Instant;
import java.util.UUID;
public record RequestWithMetadataDto(
UUID requestId,
UUID userId,
String name,
Byte type,
Byte status,
Instant createdAt,
RequestMetadataDto metadata
) {}

View File

@@ -1,106 +0,0 @@
package net.miarma.backend.huertos.dto;
import java.time.Instant;
import java.util.UUID;
public class UserMetadataDto {
private UUID userId;
private Integer memberNumber;
private Integer plotNumber;
private String dni;
private String phone;
private Byte type;
private Byte role;
private String notes;
private Instant createdAt;
private Instant assignedAt;
private Instant deactivatedAt;
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public Integer getMemberNumber() {
return memberNumber;
}
public void setMemberNumber(Integer memberNumber) {
this.memberNumber = memberNumber;
}
public Integer getPlotNumber() {
return plotNumber;
}
public void setPlotNumber(Integer plotNumber) {
this.plotNumber = plotNumber;
}
public String getDni() {
return dni;
}
public void setDni(String dni) {
this.dni = dni;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Byte getType() {
return type;
}
public void setType(Byte type) {
this.type = type;
}
public Byte getRole() {
return role;
}
public void setRole(Byte role) {
this.role = role;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
public Instant getAssignedAt() {
return assignedAt;
}
public void setAssignedAt(Instant assignedAt) {
this.assignedAt = assignedAt;
}
public Instant getDeactivatedAt() {
return deactivatedAt;
}
public void setDeactivatedAt(Instant deactivatedAt) {
this.deactivatedAt = deactivatedAt;
}
}

View File

@@ -1,13 +0,0 @@
package net.miarma.backend.huertos.dto;
public class WaitlistCensoredDto {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -1,79 +0,0 @@
package net.miarma.backend.huertos.dto.view;
import java.math.BigDecimal;
import java.time.Instant;
public class VBalanceWithTotalsDto {
private Byte id;
private BigDecimal initialBank;
private BigDecimal initialCash;
private BigDecimal totalBankExpenses;
private BigDecimal totalCashExpenses;
private BigDecimal totalBankIncomes;
private BigDecimal totalCashIncomes;
private Instant createdAt;
public Byte getId() {
return id;
}
public void setId(Byte id) {
this.id = id;
}
public BigDecimal getInitialBank() {
return initialBank;
}
public void setInitialBank(BigDecimal initialBank) {
this.initialBank = initialBank;
}
public BigDecimal getInitialCash() {
return initialCash;
}
public void setInitialCash(BigDecimal initialCash) {
this.initialCash = initialCash;
}
public BigDecimal getTotalBankExpenses() {
return totalBankExpenses;
}
public void setTotalBankExpenses(BigDecimal totalBankExpenses) {
this.totalBankExpenses = totalBankExpenses;
}
public BigDecimal getTotalCashExpenses() {
return totalCashExpenses;
}
public void setTotalCashExpenses(BigDecimal totalCashExpenses) {
this.totalCashExpenses = totalCashExpenses;
}
public BigDecimal getTotalBankIncomes() {
return totalBankIncomes;
}
public void setTotalBankIncomes(BigDecimal totalBankIncomes) {
this.totalBankIncomes = totalBankIncomes;
}
public BigDecimal getTotalCashIncomes() {
return totalCashIncomes;
}
public void setTotalCashIncomes(BigDecimal totalCashIncomes) {
this.totalCashIncomes = totalCashIncomes;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
}

View File

@@ -1,89 +0,0 @@
package net.miarma.backend.huertos.dto.view;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.UUID;
public class VIncomesWithInfoDto {
private UUID incomeId;
private UUID userId;
private String displayName;
private Integer memberNumber;
private String concept;
private BigDecimal amount;
private Byte type;
private Byte frequency;
private Instant createdAt;
public UUID getIncomeId() {
return incomeId;
}
public void setIncomeId(UUID incomeId) {
this.incomeId = incomeId;
}
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public String getDisplayName() {
return displayName;
}
public Integer getMemberNumber() {
return memberNumber;
}
public void setMemberNumber(Integer memberNumber) {
this.memberNumber = memberNumber;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getConcept() {
return concept;
}
public void setConcept(String concept) {
this.concept = concept;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public Byte getType() {
return type;
}
public void setType(Byte type) {
this.type = type;
}
public Byte getFrequency() {
return frequency;
}
public void setFrequency(Byte frequency) {
this.frequency = frequency;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
}

View File

@@ -1,31 +0,0 @@
package net.miarma.backend.huertos.mapper;
import net.miarma.backend.huertos.dto.AnnouncementDto;
import net.miarma.backend.huertos.model.Announcement;
import java.time.Instant;
import java.util.UUID;
public class AnnouncementMapper {
public static AnnouncementDto.Response toResponse(Announcement entity) {
AnnouncementDto.Response dto = new AnnouncementDto.Response();
dto.setAnnounceId(entity.getAnnounceId());
dto.setBody(entity.getBody());
dto.setPriority(entity.getPriority());
dto.setPublishedBy(entity.getPublishedBy());
dto.setPublishedByName(entity.getPublishedByName());
dto.setCreatedAt(entity.getCreatedAt());
return dto;
}
public static Announcement toEntity(AnnouncementDto.Request dto) {
Announcement entity = new Announcement();
entity.setAnnounceId(UUID.randomUUID());
entity.setBody(dto.getBody());
entity.setPriority(dto.getPriority());
entity.setPublishedBy(dto.getPublishedBy());
entity.setCreatedAt(Instant.now());
return entity;
}
}

View File

@@ -1,29 +0,0 @@
package net.miarma.backend.huertos.mapper;
import net.miarma.backend.huertos.dto.BalanceDto;
import net.miarma.backend.huertos.model.Balance;
public class BalanceMapper {
public static BalanceDto toDto(Balance balance) {
if (balance == null) return null;
BalanceDto dto = new BalanceDto();
dto.setId(balance.getId());
dto.setInitialBank(balance.getInitialBank());
dto.setInitialCash(balance.getInitialCash());
dto.setCreatedAt(balance.getCreatedAt());
return dto;
}
public static Balance toEntity(BalanceDto dto) {
if (dto == null) return null;
Balance balance = new Balance();
balance.setId(dto.getId());
balance.setInitialBank(dto.getInitialBank());
balance.setInitialCash(dto.getInitialCash());
balance.setCreatedAt(dto.getCreatedAt());
return balance;
}
}

View File

@@ -1,10 +0,0 @@
package net.miarma.backend.huertos.mapper;
import net.miarma.backend.huertos.dto.DropdownDto;
import net.miarma.backend.huertos.dto.MemberDto;
public class DropdownDtoMapper {
public static DropdownDto toDto(MemberDto dto) {
return new DropdownDto(dto.user().getUserId(), dto.metadata().getMemberNumber(), dto.user().getDisplayName());
}
}

View File

@@ -1,34 +0,0 @@
package net.miarma.backend.huertos.mapper;
import net.miarma.backend.huertos.dto.ExpenseDto;
import net.miarma.backend.huertos.model.Expense;
public class ExpenseMapper {
public static ExpenseDto.Response toResponse(Expense entity) {
if (entity == null) return null;
ExpenseDto.Response dto = new ExpenseDto.Response();
dto.setExpenseId(entity.getExpenseId());
dto.setConcept(entity.getConcept());
dto.setAmount(entity.getAmount());
dto.setSupplier(entity.getSupplier());
dto.setInvoice(entity.getInvoice());
dto.setType(entity.getType());
dto.setCreatedAt(entity.getCreatedAt());
return dto;
}
public static Expense toEntity(ExpenseDto.Request dto) {
if (dto == null) return null;
Expense entity = new Expense();
entity.setConcept(dto.getConcept());
entity.setAmount(dto.getAmount());
entity.setSupplier(dto.getSupplier());
entity.setInvoice(dto.getInvoice());
entity.setType(dto.getType());
entity.setCreatedAt(dto.getCreatedAt());
return entity;
}
}

View File

@@ -1,34 +0,0 @@
package net.miarma.backend.huertos.mapper;
import net.miarma.backend.huertos.dto.IncomeDto;
import net.miarma.backend.huertos.model.Income;
public class IncomeMapper {
public static IncomeDto.Response toResponse(Income entity) {
if (entity == null) return null;
IncomeDto.Response dto = new IncomeDto.Response();
dto.setIncomeId(entity.getIncomeId());
dto.setUserId(entity.getUserId());
dto.setConcept(entity.getConcept());
dto.setAmount(entity.getAmount());
dto.setType(entity.getType());
dto.setFrequency(entity.getFrequency());
dto.setCreatedAt(entity.getCreatedAt());
return dto;
}
public static Income toEntity(IncomeDto.Request dto) {
if (dto == null) return null;
Income entity = new Income();
entity.setUserId(dto.getUserId());
entity.setConcept(dto.getConcept());
entity.setAmount(dto.getAmount());
entity.setType(dto.getType());
entity.setFrequency(dto.getFrequency());
entity.setCreatedAt(dto.getCreatedAt());
return entity;
}
}

View File

@@ -1,44 +0,0 @@
package net.miarma.backend.huertos.mapper;
import net.miarma.backend.huertos.dto.RequestDto;
import net.miarma.backend.huertos.model.Request;
public class RequestMapper {
public static RequestDto.Response toResponse(Request entity) {
if (entity == null) return null;
RequestDto.Response dto = new RequestDto.Response();
dto.setRequestId(entity.getRequestId());
dto.setType(entity.getType());
dto.setStatus(entity.getStatus());
dto.setUserId(entity.getUserId());
dto.setCreatedAt(entity.getCreatedAt());
if (entity.getMetadata() != null) {
dto.setMetadata(
RequestMetadataMapper.toDto(entity.getMetadata())
);
}
return dto;
}
public static Request toEntity(RequestDto.Request dto) {
if (dto == null) return null;
Request entity = new Request();
entity.setType(dto.getType());
entity.setUserId(dto.getUserId());
entity.setName(dto.getName());
entity.setStatus((byte) 0);
if (dto.getMetadata() != null) {
entity.setMetadata(
RequestMetadataMapper.fromDto(dto.getMetadata())
);
}
return entity;
}
}

View File

@@ -1,50 +0,0 @@
package net.miarma.backend.huertos.mapper;
import net.miarma.backend.huertos.dto.RequestMetadataDto;
import net.miarma.backend.huertos.model.RequestMetadata;
public class RequestMetadataMapper {
public static RequestMetadata fromDto(RequestMetadataDto dto) {
if (dto == null) return null;
RequestMetadata metadata = new RequestMetadata();
metadata.setDisplayName(dto.displayName());
metadata.setDni(dto.dni());
metadata.setPhone(dto.phone());
metadata.setEmail(dto.email());
metadata.setUsername(dto.username());
metadata.setAddress(dto.address());
metadata.setZipCode(dto.zipCode());
metadata.setCity(dto.city());
metadata.setMemberNumber(dto.memberNumber());
metadata.setPlotNumber(dto.plotNumber());
metadata.setType(dto.type());
return metadata;
}
public static RequestMetadataDto toDto(RequestMetadata entity) {
if (entity == null) return null;
return new RequestMetadataDto(
entity.getId(),
entity.getDisplayName(),
entity.getDni(),
entity.getPhone(),
entity.getEmail(),
entity.getUsername(),
entity.getAddress(),
entity.getZipCode(),
entity.getCity(),
entity.getMemberNumber(),
entity.getPlotNumber(),
entity.getType(),
entity.getCreatedAt()
);
}
}

View File

@@ -1,19 +0,0 @@
package net.miarma.backend.huertos.mapper;
import net.miarma.backend.huertos.dto.RequestWithMetadataDto;
import net.miarma.backend.huertos.model.Request;
public class RequestWithMetadataMapper {
public static RequestWithMetadataDto toDto(Request r) {
if (r == null) return null;
return new RequestWithMetadataDto(
r.getRequestId(),
r.getUserId(),
r.getName(),
r.getType(),
r.getStatus(),
r.getCreatedAt(),
RequestMetadataMapper.toDto(r.getMetadata())
);
}
}

View File

@@ -1,39 +0,0 @@
package net.miarma.backend.huertos.mapper;
import net.miarma.backend.huertos.dto.UserMetadataDto;
import net.miarma.backend.huertos.model.UserMetadata;
public class UserMetadataMapper {
public static UserMetadataDto toDto(UserMetadata entity) {
UserMetadataDto dto = new UserMetadataDto();
dto.setUserId(entity.getUserId());
dto.setMemberNumber(entity.getMemberNumber());
dto.setPlotNumber(entity.getPlotNumber());
dto.setDni(entity.getDni());
dto.setPhone(entity.getPhone());
dto.setType(entity.getType());
dto.setRole(entity.getRole());
dto.setNotes(entity.getNotes());
dto.setCreatedAt(entity.getCreatedAt());
dto.setAssignedAt(entity.getAssignedAt());
dto.setDeactivatedAt(entity.getDeactivatedAt());
return dto;
}
public static UserMetadata fromDto(UserMetadataDto dto) {
UserMetadata entity = new UserMetadata();
entity.setUserId(dto.getUserId());
entity.setMemberNumber(dto.getMemberNumber());
entity.setPlotNumber(dto.getPlotNumber());
entity.setDni(dto.getDni());
entity.setPhone(dto.getPhone());
entity.setType(dto.getType());
entity.setRole(dto.getRole());
entity.setNotes(dto.getNotes());
entity.setCreatedAt(dto.getCreatedAt());
entity.setAssignedAt(dto.getAssignedAt());
entity.setDeactivatedAt(dto.getDeactivatedAt());
return entity;
}
}

View File

@@ -1,20 +0,0 @@
package net.miarma.backend.huertos.mapper.view;
import net.miarma.backend.huertos.dto.view.VBalanceWithTotalsDto;
import net.miarma.backend.huertos.model.view.VBalanceWithTotals;
public class VBalanceWithTotalsMapper {
public static VBalanceWithTotalsDto toDto(VBalanceWithTotals entity) {
VBalanceWithTotalsDto dto = new VBalanceWithTotalsDto();
dto.setId(entity.getId());
dto.setInitialBank(entity.getInitialBank());
dto.setInitialCash(entity.getInitialCash());
dto.setTotalBankExpenses(entity.getTotalBankExpenses());
dto.setTotalCashExpenses(entity.getTotalCashExpenses());
dto.setTotalBankIncomes(entity.getTotalBankIncomes());
dto.setTotalCashIncomes(entity.getTotalCashIncomes());
dto.setCreatedAt(entity.getCreatedAt());
return dto;
}
}

View File

@@ -1,21 +0,0 @@
package net.miarma.backend.huertos.mapper.view;
import net.miarma.backend.huertos.dto.view.VIncomesWithInfoDto;
import net.miarma.backend.huertos.model.view.VIncomesWithInfo;
public class VIncomesWithInfoMapper {
public static VIncomesWithInfoDto toResponse(VIncomesWithInfo entity) {
VIncomesWithInfoDto dto = new VIncomesWithInfoDto();
dto.setIncomeId(entity.getIncomeId());
dto.setUserId(entity.getUserId());
dto.setDisplayName(entity.getDisplayName());
dto.setMemberNumber(entity.getMemberNumber());
dto.setConcept(entity.getConcept());
dto.setAmount(entity.getAmount());
dto.setType(entity.getType());
dto.setFrequency(entity.getFrequency());
dto.setCreatedAt(entity.getCreatedAt());
return dto;
}
}

View File

@@ -1,108 +0,0 @@
package net.miarma.backend.huertos.model;
import java.time.Instant;
import java.util.UUID;
import jakarta.persistence.*;
import net.miarma.backlib.util.UuidUtil;
@Entity
@Table(name = "huertos_announces")
public class Announcement {
@Id
@Column(name = "announce_id", columnDefinition = "BINARY(16)")
private byte[] announceIdBin;
@Transient
private UUID announceId;
@Column(name = "body", nullable = false, columnDefinition = "TEXT")
private String body;
@Column(name = "priority", nullable = false)
private Byte priority;
@Column(name = "published_by", columnDefinition = "BINARY(16)", nullable = false)
private byte[] publishedByBin;
@Transient
private UUID publishedBy;
@Column(name = "published_by_name", nullable = false)
private String publishedByName;
@Column(name = "created_at", nullable = false)
private Instant createdAt;
@PrePersist
@PreUpdate
private void prePersist() {
if (announceId != null) {
announceIdBin = UuidUtil.uuidToBin(announceId);
}
if (publishedBy != null) {
publishedByBin = UuidUtil.uuidToBin(publishedBy);
}
}
@PostLoad
private void postLoad() {
if (announceIdBin != null) {
announceId = UuidUtil.binToUUID(announceIdBin);
}
if (publishedByBin != null) {
publishedBy = UuidUtil.binToUUID(publishedByBin);
}
}
public UUID getAnnounceId() {
return announceId;
}
public void setAnnounceId(UUID announceId) {
this.announceId = announceId;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public Byte getPriority() {
return priority;
}
public void setPriority(Byte priority) {
this.priority = priority;
}
public UUID getPublishedBy() {
return publishedBy;
}
public void setPublishedBy(UUID publishedBy) {
this.publishedBy = publishedBy;
}
public String getPublishedByName() {
return publishedByName;
}
public void setPublishedByName(String publishedByName) {
this.publishedByName = publishedByName;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
}

View File

@@ -1,58 +0,0 @@
package net.miarma.backend.huertos.model;
import java.math.BigDecimal;
import java.time.Instant;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "huertos_balance")
public class Balance {
@Id
private Byte id = 1;
@Column(name = "initial_bank", nullable = false)
private BigDecimal initialBank;
@Column(name = "initial_cash", nullable = false)
private BigDecimal initialCash;
@Column(name = "created_at", nullable = false)
private Instant createdAt;
public Byte getId() {
return id;
}
public void setId(Byte id) {
this.id = id;
}
public BigDecimal getInitialBank() {
return initialBank;
}
public void setInitialBank(BigDecimal initialBank) {
this.initialBank = initialBank;
}
public BigDecimal getInitialCash() {
return initialCash;
}
public void setInitialCash(BigDecimal initialCash) {
this.initialCash = initialCash;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
}

View File

@@ -1,109 +0,0 @@
package net.miarma.backend.huertos.model;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.UUID;
import jakarta.persistence.*;
import net.miarma.backlib.util.UuidUtil;
@Entity
@Table(name = "huertos_expenses")
public class Expense {
@Id
@Column(name = "expense_id", columnDefinition = "BINARY(16)")
private byte[] expenseIdBin;
@Transient
private UUID expenseId;
@Column(name = "concept", nullable = false, length = 128)
private String concept;
@Column(name = "amount", nullable = false)
private BigDecimal amount;
@Column(name = "supplier", nullable = false, length = 128)
private String supplier;
@Column(name = "invoice", nullable = false, length = 32)
private String invoice;
@Column(name = "type")
private Byte type;
@Column(name = "created_at", nullable = false)
private Instant createdAt;
@PrePersist
@PreUpdate
private void prePersist() {
if (expenseId != null) {
expenseIdBin = UuidUtil.uuidToBin(expenseId);
}
}
@PostLoad
private void postLoad() {
if (expenseIdBin != null) {
expenseId = UuidUtil.binToUUID(expenseIdBin);
}
}
public UUID getExpenseId() {
return expenseId;
}
public void setExpenseId(UUID expenseId) {
this.expenseId = expenseId;
}
public String getConcept() {
return concept;
}
public void setConcept(String concept) {
this.concept = concept;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public String getSupplier() {
return supplier;
}
public void setSupplier(String supplier) {
this.supplier = supplier;
}
public String getInvoice() {
return invoice;
}
public void setInvoice(String invoice) {
this.invoice = invoice;
}
public Byte getType() {
return type;
}
public void setType(Byte type) {
this.type = type;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
}

View File

@@ -1,133 +0,0 @@
package net.miarma.backend.huertos.model;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.UUID;
import jakarta.persistence.*;
import net.miarma.backlib.util.UuidUtil;
@Entity
@Table(name = "huertos_incomes")
public class Income {
@Id
@Column(name = "income_id", columnDefinition = "BINARY(16)")
private byte[] incomeIdBin;
@Transient
private UUID incomeId;
@Column(name = "user_id", columnDefinition = "BINARY(16)", nullable = false)
private byte[] userIdBin;
@Transient
private UUID userId;
@Column(name = "concept", nullable = false, length = 128)
private String concept;
@Column(name = "amount", nullable = false)
private BigDecimal amount;
@Column(name = "type")
private Byte type;
@Column(name = "frequency")
private Byte frequency;
@Column(name = "created_at", nullable = false, updatable = true)
private Instant createdAt;
@PrePersist
@PreUpdate
private void prePersist() {
if (userId != null) {
userIdBin = UuidUtil.uuidToBin(userId);
}
if (incomeId != null) {
incomeIdBin = UuidUtil.uuidToBin(incomeId);
}
}
@PostLoad
private void postLoad() {
if (userIdBin != null) {
userId = UuidUtil.binToUUID(userIdBin);
}
if (incomeIdBin != null) {
incomeId = UuidUtil.binToUUID(incomeIdBin);
}
}
public boolean isPaid() {
Instant now = Instant.now();
if (frequency == 0) { // BIYEARLY
return Duration.between(createdAt, now).toDays() <= 6L * 30;
} else if (frequency == 1) { // YEARLY
return Duration.between(createdAt, now).toDays() <= 12L * 30;
} else {
return false;
}
}
public UUID getIncomeId() {
return incomeId;
}
public void setIncomeId(UUID incomeId) {
this.incomeId = incomeId;
}
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public String getConcept() {
return concept;
}
public void setConcept(String concept) {
this.concept = concept;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public Byte getType() {
return type;
}
public void setType(Byte type) {
this.type = type;
}
public Byte getFrequency() {
return frequency;
}
public void setFrequency(Byte frequency) {
this.frequency = frequency;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
}

View File

@@ -1,76 +0,0 @@
package net.miarma.backend.huertos.model;
import java.time.Instant;
import java.util.UUID;
import jakarta.persistence.*;
import net.miarma.backlib.util.UuidUtil;
@Entity
@Table(name = "huertos_requests")
public class Request {
@Id
@Column(name = "request_id", columnDefinition = "BINARY(16)")
private byte[] requestIdBin;
@Transient
private UUID requestId;
@Column(name = "user_id", columnDefinition = "BINARY(16)")
private byte[] userIdBin;
@Transient
private UUID userId;
private String name;
@Column(nullable = false)
private Byte type;
@Column(nullable = false)
private Byte status;
@Column(name = "created_at", nullable = false)
private Instant createdAt;
@OneToOne(mappedBy = "request", cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = true)
private RequestMetadata metadata;
@PrePersist
private void prePersist() {
if (requestId != null) requestIdBin = UuidUtil.uuidToBin(requestId);
if (userId != null) userIdBin = UuidUtil.uuidToBin(userId);
}
@PostLoad
private void postLoad() {
if (requestIdBin != null) requestId = UuidUtil.binToUUID(requestIdBin);
if (userIdBin != null) userId = UuidUtil.binToUUID(userIdBin);
}
public UUID getRequestId() { return requestId; }
public void setRequestId(UUID requestId) { this.requestId = requestId; }
public UUID getUserId() { return userId; }
public void setUserId(UUID userId) { this.userId = userId; }
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Byte getType() { return type; }
public void setType(Byte type) { this.type = type; }
public Byte getStatus() { return status; }
public void setStatus(Byte status) { this.status = status; }
public Instant getCreatedAt() { return createdAt; }
public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; }
public RequestMetadata getMetadata() { return metadata; }
public void setMetadata(RequestMetadata metadata) { this.metadata = metadata; }
}

View File

@@ -1,199 +0,0 @@
package net.miarma.backend.huertos.model;
import jakarta.persistence.*;
import net.miarma.backlib.util.UuidUtil;
import java.time.Instant;
import java.util.UUID;
@Entity
@Table(name = "huertos_request_metadata")
public class RequestMetadata {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "request_id", columnDefinition = "BINARY(16)", nullable = false, unique = true)
private byte[] requestIdBin;
@Transient
private UUID requestId;
@OneToOne
@JoinColumn(name = "request_id", referencedColumnName = "request_id", insertable = false, updatable = false)
private Request request;
@Column(name = "display_name", nullable = false, length = 150)
private String displayName;
@Column(nullable = false, length = 20)
private String dni;
@Column(length = 30)
private String phone;
@Column(nullable = false, length = 150)
private String email;
@Column(length = 255)
private String address;
@Column(name = "zip_code", length = 10)
private String zipCode;
@Column(length = 100)
private String city;
@Column(name = "member_number")
private Integer memberNumber;
@Column(name = "plot_number")
private Integer plotNumber;
@Column(nullable = false, length = 100)
private String username;
private Byte type;
@Column(name = "created_at", nullable = false, updatable = false)
private Instant createdAt;
@PrePersist
private void prePersist() {
if (requestId != null) requestIdBin = UuidUtil.uuidToBin(requestId);
}
@PostLoad
private void postLoad() {
if (requestIdBin != null) requestId = UuidUtil.binToUUID(requestIdBin);
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public byte[] getRequestIdBin() {
return requestIdBin;
}
public void setRequestIdBin(byte[] requestIdBin) {
this.requestIdBin = requestIdBin;
}
public UUID getRequestId() {
return requestId;
}
public void setRequestId(UUID requestId) {
this.requestId = requestId;
}
public Request getRequest() {
return request;
}
public void setRequest(Request request) {
this.request = request;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getDni() {
return dni;
}
public void setDni(String dni) {
this.dni = dni;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Integer getMemberNumber() {
return memberNumber;
}
public void setMemberNumber(Integer memberNumber) {
this.memberNumber = memberNumber;
}
public Integer getPlotNumber() {
return plotNumber;
}
public void setPlotNumber(Integer plotNumber) {
this.plotNumber = plotNumber;
}
public Byte getType() {
return type;
}
public void setType(Byte type) {
this.type = type;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}

View File

@@ -1,157 +0,0 @@
package net.miarma.backend.huertos.model;
import java.time.Instant;
import java.util.UUID;
import jakarta.persistence.*;
import net.miarma.backlib.util.UuidUtil;
@Entity
@Table(name = "huertos_user_metadata")
public class UserMetadata {
@Id
@Column(name = "user_id", columnDefinition = "BINARY(16)")
private byte[] userIdBin;
@Transient
private UUID userId;
@Column(name = "member_number", nullable = false, unique = true)
private Integer memberNumber;
@Column(name = "plot_number", nullable = false)
private Integer plotNumber;
@Column(name = "dni", nullable = false, unique = true, length = 9)
private String dni;
@Column(name = "phone", nullable = false, length = 20)
private String phone;
@Column(name = "type", nullable = false)
private Byte type;
@Column(name = "role", nullable = false)
private Byte role;
@Column(name = "notes")
private String notes;
@Column(name = "created_at", nullable = false)
private Instant createdAt;
@Column(name = "assigned_at")
private Instant assignedAt;
@Column(name = "deactivated_at")
private Instant deactivatedAt;
@PrePersist
@PreUpdate
private void prePersist() {
if (userId != null) {
userIdBin = UuidUtil.uuidToBin(userId);
}
}
@PostLoad
private void postLoad() {
if (userIdBin != null) {
userId = UuidUtil.binToUUID(userIdBin);
}
}
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public Integer getMemberNumber() {
return memberNumber;
}
public void setMemberNumber(Integer memberNumber) {
this.memberNumber = memberNumber;
}
public Integer getPlotNumber() {
return plotNumber;
}
public void setPlotNumber(Integer plotNumber) {
this.plotNumber = plotNumber;
}
public String getDni() {
return dni;
}
public void setDni(String dni) {
this.dni = dni;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Byte getType() {
return type;
}
public void setType(Byte type) {
this.type = type;
}
public Byte getRole() {
return role;
}
public void setRole(Byte role) {
this.role = role;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public Instant getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Instant createdAt) {
this.createdAt = createdAt;
}
public Instant getAssignedAt() {
return assignedAt;
}
public void setAssignedAt(Instant assignedAt) {
this.assignedAt = assignedAt;
}
public Instant getDeactivatedAt() {
return deactivatedAt;
}
public void setDeactivatedAt(Instant deactivatedAt) {
this.deactivatedAt = deactivatedAt;
}
public void setUserIdBin(byte[] userIdBin) {
this.userIdBin = userIdBin;
}
}

View File

@@ -1,72 +0,0 @@
package net.miarma.backend.huertos.model.view;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.annotations.Immutable;
import java.math.BigDecimal;
import java.time.Instant;
@Entity
@Immutable
@Table(name = "v_balance_with_totals")
public class VBalanceWithTotals {
@Id
private Byte id;
@Column(name = "initial_bank")
private BigDecimal initialBank;
@Column(name = "initial_cash")
private BigDecimal initialCash;
@Column(name = "total_bank_expenses")
private BigDecimal totalBankExpenses;
@Column(name = "total_cash_expenses")
private BigDecimal totalCashExpenses;
@Column(name = "total_bank_incomes")
private BigDecimal totalBankIncomes;
@Column(name = "total_cash_incomes")
private BigDecimal totalCashIncomes;
@Column(name = "created_at")
private Instant createdAt;
public Byte getId() {
return id;
}
public BigDecimal getInitialBank() {
return initialBank;
}
public BigDecimal getInitialCash() {
return initialCash;
}
public BigDecimal getTotalBankExpenses() {
return totalBankExpenses;
}
public BigDecimal getTotalCashExpenses() {
return totalCashExpenses;
}
public BigDecimal getTotalBankIncomes() {
return totalBankIncomes;
}
public BigDecimal getTotalCashIncomes() {
return totalCashIncomes;
}
public Instant getCreatedAt() {
return createdAt;
}
}

View File

@@ -1,87 +0,0 @@
package net.miarma.backend.huertos.model.view;
import jakarta.persistence.*;
import net.miarma.backlib.util.UuidUtil;
import org.hibernate.annotations.Immutable;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.UUID;
@Entity
@Immutable
@Table(name = "v_incomes_with_info")
public class VIncomesWithInfo {
@Id
@Column(name = "income_id", columnDefinition = "BINARY(16)")
private byte[] incomeIdBin;
@Transient
private UUID incomeId;
@Column(name = "user_id", columnDefinition = "BINARY(16)")
private byte[] userIdBin;
@Transient
private UUID userId;
@Column(name = "display_name")
private String displayName;
@Column(name = "member_number")
private Integer memberNumber;
private String concept;
private BigDecimal amount;
private Byte type;
private Byte frequency;
@Column(name = "created_at")
private Instant createdAt;
@PostLoad
private void postLoad() {
if (userIdBin != null) {
userId = UuidUtil.binToUUID(userIdBin);
}
if (incomeIdBin != null) {
incomeId = UuidUtil.binToUUID(incomeIdBin);
}
}
public UUID getIncomeId() {
return incomeId;
}
public UUID getUserId() {
return userId;
}
public String getDisplayName() {
return displayName;
}
public Integer getMemberNumber() { return memberNumber; }
public String getConcept() {
return concept;
}
public BigDecimal getAmount() {
return amount;
}
public Byte getType() {
return type;
}
public Byte getFrequency() {
return frequency;
}
public Instant getCreatedAt() {
return createdAt;
}
}

View File

@@ -1,7 +0,0 @@
package net.miarma.backend.huertos.repository;
import net.miarma.backend.huertos.model.Announcement;
import org.springframework.data.jpa.repository.JpaRepository;
public interface AnnouncementRepository extends JpaRepository<Announcement, byte[]> {
}

View File

@@ -1,8 +0,0 @@
package net.miarma.backend.huertos.repository;
import net.miarma.backend.huertos.model.Balance;
import org.springframework.data.jpa.repository.JpaRepository;
public interface BalanceRepository extends JpaRepository<Balance, Byte> {
}

View File

@@ -1,6 +0,0 @@
package net.miarma.backend.huertos.repository;
import net.miarma.backend.huertos.model.Expense;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ExpenseRepository extends JpaRepository<Expense, byte[]> {}

View File

@@ -1,7 +0,0 @@
package net.miarma.backend.huertos.repository;
import net.miarma.backend.huertos.model.Income;
import org.springframework.data.jpa.repository.JpaRepository;
public interface IncomeRepository extends JpaRepository<Income, byte[]> {
}

View File

@@ -1,7 +0,0 @@
package net.miarma.backend.huertos.repository;
import net.miarma.backend.huertos.model.RequestMetadata;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RequestMetadataRepository extends JpaRepository<RequestMetadata, Long> {
}

View File

@@ -1,18 +0,0 @@
package net.miarma.backend.huertos.repository;
import net.miarma.backend.huertos.model.Request;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.Optional;
public interface RequestRepository extends JpaRepository<Request, byte[]> {
@Query("""
SELECT r FROM Request r
LEFT JOIN FETCH r.metadata
WHERE r.requestIdBin = :id
""")
Optional<Request> findByIdWithMetadata(@Param("id") byte[] id);
}

View File

@@ -1,10 +0,0 @@
package net.miarma.backend.huertos.repository;
import net.miarma.backend.huertos.model.UserMetadata;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface UserMetadataRepository extends JpaRepository<UserMetadata, byte[]> {
Optional<UserMetadata> findByMemberNumber(Integer memberNumber);
}

View File

@@ -1,12 +0,0 @@
package net.miarma.backend.huertos.repository.view;
import net.miarma.backend.huertos.model.view.VBalanceWithTotals;
import org.springframework.data.repository.Repository;
import java.util.List;
import java.util.Optional;
public interface VBalanceWithTotalsRepository extends Repository<VBalanceWithTotals, Byte> {
List<VBalanceWithTotals> findAll();
Optional<VBalanceWithTotals> findById(Byte id);
}

View File

@@ -1,12 +0,0 @@
package net.miarma.backend.huertos.repository.view;
import net.miarma.backend.huertos.model.view.VIncomesWithInfo;
import org.springframework.data.repository.Repository;
import java.util.List;
import java.util.Optional;
public interface VIncomesWithInfoRepository extends Repository<VIncomesWithInfo, byte[]> {
List<VIncomesWithInfo> findAll();
Optional<VIncomesWithInfo> findById(byte[] incomeId);
}

View File

@@ -1,63 +0,0 @@
package net.miarma.backend.huertos.security;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import net.miarma.backend.huertos.model.UserMetadata;
import net.miarma.backend.huertos.service.UserMetadataService;
import net.miarma.backlib.security.JwtService;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
import java.util.UUID;
@Component
public class HuertosJwtFilter extends OncePerRequestFilter {
private final JwtService jwtService;
private final UserMetadataService metadataService;
public HuertosJwtFilter(JwtService jwtService, UserMetadataService metadataService) {
this.jwtService = jwtService;
this.metadataService = metadataService;
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring(7);
if (jwtService.validateToken(token)) {
UUID userId = jwtService.getUserId(token);
Byte serviceId = jwtService.getServiceId(token);
UserMetadata metadata = metadataService.getById(userId);
if (metadata != null) {
var principal = new HuertosPrincipal(
userId,
metadata.getRole(),
metadata.getType(),
serviceId
);
var auth = new UsernamePasswordAuthenticationToken(
principal, null, principal.getAuthorities()
);
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
}
filterChain.doFilter(request, response);
}
}

View File

@@ -1,65 +0,0 @@
package net.miarma.backend.huertos.security;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
public class HuertosPrincipal implements UserDetails {
private final UUID userId;
private final Byte role;
private final Byte type;
private final Byte serviceId;
public HuertosPrincipal(UUID userId, Byte role, Byte type, Byte serviceId) {
this.userId = userId;
this.role = role;
this.type = type;
this.serviceId = serviceId;
}
public UUID getUserId() { return userId; }
public Byte getHuertosRole() { return role; }
public Byte getHuertosType() { return type; }
public Byte getServiceId() { return serviceId; }
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> auth = new ArrayList<>();
String roleName = switch(role) {
case 0 -> "USER";
case 1 -> "ADMIN";
case 2 -> "DEV";
default -> "USER";
};
String typeName = switch(type) {
case 0 -> "WAIT_LIST";
case 1 -> "MEMBER";
case 2 -> "WITH_GREENHOUSE";
case 3 -> "COLLABORATOR";
case 4 -> "SUBSIDY";
case 5 -> "DEVELOPER";
default -> "WAIT_LIST";
};
auth.add(new SimpleGrantedAuthority("ROLE_HUERTOS_ROLE_" + roleName));
auth.add(new SimpleGrantedAuthority("ROLE_HUERTOS_TYPE_" + typeName));
return auth;
}
@Override public String getPassword() { return ""; }
@Override public String getUsername() { return userId.toString(); }
@Override public boolean isAccountNonExpired() { return true; }
@Override public boolean isAccountNonLocked() { return true; }
@Override public boolean isCredentialsNonExpired() { return true; }
@Override public boolean isEnabled() { return true; }
}

View File

@@ -1,36 +0,0 @@
package net.miarma.backend.huertos.security;
/**
* Clase de utilidad para censurar nombres.
* Censura los nombres dejando las primeras 3 letras visibles y el resto con asteriscos.
* Si el nombre es muy largo, lo acorta a 16 caracteres y añade "..." al final.
* @author José Manuel Amador Gallardo
*/
public class NameCensorer {
public static String censor(String name) {
if (name == null || name.isBlank()) return "";
String[] words = name.trim().split("\\s+");
for (int i = 0; i < words.length; i++) {
String word = words[i];
int len = word.length();
if (len > 3) {
words[i] = word.substring(0, 3) + "*".repeat(len - 3);
} else if (len > 0) {
words[i] = word.charAt(0) + "*".repeat(len - 1);
}
}
String censored = String.join(" ", words);
if (censored.length() > 16) {
censored = censored.substring(0, 16) + "...";
}
return censored;
}
}

View File

@@ -1,71 +0,0 @@
package net.miarma.backend.huertos.service;
import jakarta.transaction.Transactional;
import net.miarma.backend.huertos.dto.AnnouncementDto;
import net.miarma.backend.huertos.model.Announcement;
import net.miarma.backend.huertos.model.Income;
import net.miarma.backend.huertos.repository.AnnouncementRepository;
import net.miarma.backlib.exception.NotFoundException;
import net.miarma.backlib.util.UuidUtil;
import org.springframework.stereotype.Service;
import java.time.Instant;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
@Service
@Transactional
public class AnnouncementService {
private final AnnouncementRepository announcementRepository;
private final MemberService memberService;
public AnnouncementService(AnnouncementRepository announcementRepository, MemberService memberService) {
this.announcementRepository = announcementRepository;
this.memberService = memberService;
}
public List<Announcement> getAll() {
return announcementRepository.findAll().stream()
.sorted(Comparator.comparing(Announcement::getCreatedAt).reversed())
.toList();
}
public Announcement getById(UUID announceId) {
byte[] idBytes = UuidUtil.uuidToBin(announceId);
return announcementRepository.findById(idBytes)
.orElseThrow(() -> new NotFoundException("Anuncio no encontrado"));
}
public Announcement create(Announcement announcement) {
if (announcement.getAnnounceId() == null) {
announcement.setAnnounceId(UUID.randomUUID());
}
announcement.setPublishedByName(memberService.getById(announcement.getPublishedBy()).user().getDisplayName());
announcement.setCreatedAt(Instant.now());
return announcementRepository.save(announcement);
}
public Announcement update(UUID announceId, Announcement changes) {
Announcement announcement = getById(announceId);
if (changes.getBody() != null)
announcement.setBody(changes.getBody());
if (changes.getPriority() != null)
announcement.setPriority(changes.getPriority());
if (changes.getPublishedBy() != null)
announcement.setPublishedBy(changes.getPublishedBy());
return announcementRepository.save(announcement);
}
public void delete(UUID announceId) {
byte[] idBytes = UuidUtil.uuidToBin(announceId);
if (!announcementRepository.existsById(idBytes))
throw new NotFoundException("Anuncio no encontrado");
announcementRepository.deleteById(idBytes);
}
}

View File

@@ -1,62 +0,0 @@
package net.miarma.backend.huertos.service;
import java.time.Instant;
import net.miarma.backend.huertos.model.view.VBalanceWithTotals;
import net.miarma.backend.huertos.repository.view.VBalanceWithTotalsRepository;
import net.miarma.backlib.exception.ConflictException;
import net.miarma.backlib.exception.NotFoundException;
import org.springframework.stereotype.Service;
import jakarta.transaction.Transactional;
import net.miarma.backend.huertos.model.Balance;
import net.miarma.backend.huertos.repository.BalanceRepository;
@Service
@Transactional
public class BalanceService {
private final BalanceRepository balanceRepository;
private final VBalanceWithTotalsRepository vBalanceWithTotalsRepository;
public BalanceService(BalanceRepository balanceRepository, VBalanceWithTotalsRepository vBalanceWithTotalsRepository) {
this.balanceRepository = balanceRepository;
this.vBalanceWithTotalsRepository = vBalanceWithTotalsRepository;
}
public Balance get() {
return balanceRepository.findById((byte) 1)
.orElseThrow(() -> new NotFoundException("Balance no encontrado"));
}
public VBalanceWithTotals getWithTotals() {
return vBalanceWithTotalsRepository.findById((byte) 1)
.orElseThrow(() -> new NotFoundException("Balance no encontrado"));
}
public Balance create(Balance balance) {
if (balanceRepository.existsById((byte) 1)) {
throw new ConflictException("Ya hay un valor de balance en la base de datos");
}
balance.setId((byte) 1);
balance.setCreatedAt(Instant.now());
return balanceRepository.save(balance);
}
public Balance update(Balance dto) {
Balance balance = balanceRepository.findById((byte) 1)
.orElseThrow(() -> new NotFoundException("Balance no encontrado"));
if (dto.getInitialBank() != null) balance.setInitialBank(dto.getInitialBank());
if (dto.getInitialCash() != null) balance.setInitialCash(dto.getInitialCash());
return balanceRepository.save(balance);
}
public void delete() {
if (!balanceRepository.existsById((byte) 1)) {
throw new NotFoundException("Balance no encontrado");
}
balanceRepository.deleteById((byte) 1);
}
}

View File

@@ -1,60 +0,0 @@
package net.miarma.backend.huertos.service;
import net.miarma.backend.huertos.client.HuertosWebClient;
import net.miarma.backlib.dto.LoginRequest;
import net.miarma.backlib.dto.LoginResponse;
import net.miarma.backlib.security.CoreAuthTokenHolder;
import net.miarma.backlib.security.JwtService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import tools.jackson.databind.ObjectMapper;
import java.time.Instant;
@Service
public class CoreAuthService {
private final RestTemplate authRestTemplate;
private final CoreAuthTokenHolder tokenHolder;
private final JwtService jwtService;
@Value("${huertos.user}")
private String username;
@Value("${huertos.password}")
private String password;
@Value("${core.url}")
private String coreUrl;
public CoreAuthService(@Qualifier("authRestTemplate") RestTemplate authRestTemplate,
CoreAuthTokenHolder tokenHolder,
JwtService jwtService) {
this.authRestTemplate = authRestTemplate;
this.tokenHolder = tokenHolder;
this.jwtService = jwtService;
}
public synchronized String getToken() {
if (tokenHolder.getToken() == null || tokenHolder.isExpired()) {
refreshToken();
}
return tokenHolder.getToken();
}
private void refreshToken() {
var req = new LoginRequest(username, password, (byte) 1);
LoginResponse resp = authRestTemplate.postForObject(
coreUrl + "/auth/login",
req,
LoginResponse.class
);
String token = resp.token();
Instant exp = jwtService.getExpiration(token).toInstant();
tokenHolder.setToken(token, exp);
}
}

View File

@@ -1,96 +0,0 @@
package net.miarma.backend.huertos.service;
import jakarta.transaction.Transactional;
import net.miarma.backend.huertos.dto.ExpenseDto;
import net.miarma.backend.huertos.model.Expense;
import net.miarma.backend.huertos.model.Income;
import net.miarma.backend.huertos.repository.ExpenseRepository;
import net.miarma.backlib.exception.NotFoundException;
import net.miarma.backlib.exception.ValidationException;
import net.miarma.backlib.util.UuidUtil;
import org.springframework.stereotype.Service;
import java.time.Instant;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
@Service
@Transactional
public class ExpenseService {
private final ExpenseRepository expenseRepository;
public ExpenseService(ExpenseRepository expenseRepository) {
this.expenseRepository = expenseRepository;
}
public List<Expense> getAll() {
return expenseRepository.findAll().stream()
.sorted(Comparator.comparing(Expense::getCreatedAt).reversed())
.toList();
}
public Expense getById(UUID expenseId) {
byte[] idBytes = UuidUtil.uuidToBin(expenseId);
return expenseRepository.findById(idBytes)
.orElseThrow(() -> new NotFoundException("Gasto no encontrado"));
}
public Expense create(Expense expense) {
if (expense.getConcept() == null || expense.getConcept().isBlank()) {
throw new ValidationException("concept", "El concepto es obligatorio");
}
if (expense.getAmount() == null) {
throw new ValidationException("amount", "La cantidad es obligatoria");
}
if (expense.getSupplier() == null || expense.getSupplier().isBlank()) {
throw new ValidationException("supplier", "El proveedor es obligatorio");
}
if (expense.getInvoice() == null || expense.getInvoice().isBlank()) {
throw new ValidationException("invoice", "La factura es obligatoria");
}
if (expense.getCreatedAt() == null) {
expense.setCreatedAt(Instant.now());
}
expense.setExpenseId(UUID.randomUUID());
return expenseRepository.save(expense);
}
public Expense update(UUID expenseId, Expense changes) {
byte[] idBytes = UuidUtil.uuidToBin(expenseId);
Expense expense = expenseRepository.findById(idBytes)
.orElseThrow(() -> new NotFoundException("Gasto no encontrado"));
if (changes.getConcept() != null)
expense.setConcept(changes.getConcept());
if (changes.getAmount() != null)
expense.setAmount(changes.getAmount());
if (changes.getSupplier() != null)
expense.setSupplier(changes.getSupplier());
if (changes.getInvoice() != null)
expense.setInvoice(changes.getInvoice());
if (changes.getType() != null)
expense.setType(changes.getType());
if (changes.getCreatedAt() != null)
expense.setCreatedAt(changes.getCreatedAt());
return expenseRepository.save(expense);
}
public void delete(UUID expenseId) {
byte[] idBytes = UuidUtil.uuidToBin(expenseId);
if (!expenseRepository.existsById(idBytes)) {
throw new NotFoundException("Gasto no encontrado");
}
expenseRepository.deleteById(idBytes);
}
}

View File

@@ -1,128 +0,0 @@
package net.miarma.backend.huertos.service;
import java.time.Instant;
import java.time.temporal.TemporalAmount;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import net.miarma.backend.huertos.model.view.VIncomesWithInfo;
import net.miarma.backend.huertos.service.view.VIncomesWithInfoService;
import net.miarma.backlib.exception.BadRequestException;
import net.miarma.backlib.exception.NotFoundException;
import net.miarma.backlib.exception.ValidationException;
import org.springframework.stereotype.Service;
import jakarta.transaction.Transactional;
import net.miarma.backend.huertos.model.Income;
import net.miarma.backend.huertos.repository.IncomeRepository;
import net.miarma.backlib.util.UuidUtil;
@Service
@Transactional
public class IncomeService {
private final IncomeRepository incomeRepository;
private final VIncomesWithInfoService incomesWithInfoService;
private final UserMetadataService metadataService;
public IncomeService(IncomeRepository incomeRepository,
VIncomesWithInfoService incomesWithInfoService,
UserMetadataService metadataService) {
this.incomeRepository = incomeRepository;
this.incomesWithInfoService = incomesWithInfoService;
this.metadataService = metadataService;
}
public List<Income> getAll() {
return incomeRepository.findAll().stream()
.sorted(Comparator.comparing(Income::getCreatedAt).reversed())
.toList();
}
public Income getById(UUID incomeId) {
byte[] idBytes = UuidUtil.uuidToBin(incomeId);
return incomeRepository.findById(idBytes)
.orElseThrow(() -> new NotFoundException("Ingreso no encontrado"));
}
public List<Income> getByUserId(UUID userId) {
return incomeRepository.findAll().stream()
.filter(i -> i.getUserId().equals(userId))
.toList();
}
public Income create(Income income) {
if (income.getUserId() == null) {
throw new BadRequestException("El identificador de usuario es obligatorio");
}
if (income.getConcept() == null) {
throw new BadRequestException("El concepto es obligatorio");
}
if (income.getConcept().isBlank() || income.getConcept().isEmpty()) {
throw new ValidationException("concept", "El concepto no puede ir vacío");
}
if (income.getAmount() == null || income.getAmount().signum() <= 0) {
throw new ValidationException("amount", "La cantidad debe ser positiva");
}
if (income.getCreatedAt() == null) {
income.setCreatedAt(Instant.now());
}
income.setIncomeId(UUID.randomUUID());
return incomeRepository.save(income);
}
public Income update(UUID incomeId, Income changes) {
byte[] idBytes = UuidUtil.uuidToBin(incomeId);
Income income = incomeRepository.findById(idBytes)
.orElseThrow(() -> new NotFoundException("Ingreso no encontrado"));
if (changes.getConcept() != null) income.setConcept(changes.getConcept());
if (changes.getAmount() != null) {
if (changes.getAmount().signum() <= 0) {
throw new ValidationException("amount", "La cantidad debe ser positiva");
}
income.setAmount(changes.getAmount());
}
if (changes.getType() != null) income.setType(changes.getType());
if (changes.getFrequency() != null) income.setFrequency(changes.getFrequency());
if (changes.getCreatedAt() != null && !changes.getCreatedAt().equals(income.getCreatedAt())) {
income.setCreatedAt(changes.getCreatedAt());
}
return incomeRepository.save(income);
}
public void delete(UUID incomeId) {
byte[] idBytes = UuidUtil.uuidToBin(incomeId);
if (!incomeRepository.existsById(idBytes)) {
throw new NotFoundException("Ingreso no encontrado");
}
incomeRepository.deleteById(idBytes);
}
public Boolean existsByMemberNumber(Integer memberNumber) {
try {
UUID userId = metadataService.getByMemberNumber(memberNumber).getUserId();
return !getByUserId(userId).isEmpty();
} catch (Exception e) {
return false;
}
}
public Boolean hasPaid(Integer memberNumber) {
UUID userId = metadataService.getByMemberNumber(memberNumber).getUserId();
List<Income> incomes = getByUserId(userId);
return !incomes.isEmpty() && incomes.stream().allMatch(Income::isPaid);
}
public List<VIncomesWithInfo> getByMemberNumber(Integer memberNumber) {
UUID userId = metadataService.getByMemberNumber(memberNumber).getUserId();
return incomesWithInfoService.getByUserId(userId);
}
}

View File

@@ -1,202 +0,0 @@
package net.miarma.backend.huertos.service;
import net.miarma.backend.huertos.client.HuertosWebClient;
import net.miarma.backend.huertos.dto.*;
import net.miarma.backend.huertos.dto.view.VIncomesWithInfoDto;
import net.miarma.backend.huertos.mapper.DropdownDtoMapper;
import net.miarma.backend.huertos.mapper.RequestMapper;
import net.miarma.backend.huertos.mapper.UserMetadataMapper;
import net.miarma.backend.huertos.mapper.IncomeMapper;
import net.miarma.backend.huertos.mapper.view.VIncomesWithInfoMapper;
import net.miarma.backend.huertos.security.NameCensorer;
import net.miarma.backlib.dto.UserWithCredentialDto;
import net.miarma.backlib.exception.NotFoundException;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
@Service
public class MemberService {
private final HuertosWebClient huertosWebClient;
private final IncomeService incomeService;
private final RequestService requestService;
private final UserMetadataService metadataService;
public MemberService(HuertosWebClient huertosWebClient,
IncomeService incomeService,
RequestService requestService,
UserMetadataService metadataService) {
this.huertosWebClient = huertosWebClient;
this.incomeService = incomeService;
this.requestService = requestService;
this.metadataService = metadataService;
}
@Cacheable(value = "memberById")
public MemberDto getById(UUID userId) {
var uwc = huertosWebClient.getUserWithCredential(userId, (byte)1);
if (uwc == null) {
throw new NotFoundException("Socio no encontrado");
}
var meta = metadataService.getById(userId);
if (meta == null) {
throw new NotFoundException("User metadata not found");
}
return new MemberDto(
uwc.user(),
uwc.account(),
UserMetadataMapper.toDto(meta)
);
}
@Cacheable("members")
public List<MemberDto> getAll() {
List<UserWithCredentialDto> all = huertosWebClient.getAllUsersWithCredentials((byte)1);
return all.stream()
.filter(uwc -> metadataService.existsById(uwc.user().getUserId()))
.map(uwc -> {
var meta = metadataService.getById(uwc.user().getUserId());
return new MemberDto(
uwc.user(),
uwc.account(),
UserMetadataMapper.toDto(meta)
);
})
.sorted(Comparator.comparing(dto -> dto.metadata().getMemberNumber()))
.toList();
}
public MemberProfileDto getMyProfile(UUID userId) {
MemberDto member = getById(userId);
Integer memberNumber = member.metadata().getMemberNumber();
List<RequestDto.Response> requests = requestService.getByUserId(userId).stream()
.map(RequestMapper::toResponse)
.toList();
List<VIncomesWithInfoDto> payments = incomeService.getByMemberNumber(memberNumber).stream()
.map(VIncomesWithInfoMapper::toResponse)
.toList();
return new MemberProfileDto(
member.user(),
member.account(),
member.metadata(),
requests,
payments,
hasCollaborator(memberNumber),
hasGreenhouse(memberNumber),
hasCollaboratorRequest(memberNumber),
hasGreenhouseRequest(memberNumber)
);
}
public Integer getLatestMemberNumber() {
return metadataService.getLatestMemberNumber();
}
@Cacheable("waitlist")
public List<MemberDto> getWaitlist() {
List<UserWithCredentialDto> all = huertosWebClient.getAllUsersWithCredentials((byte)1);
return all.stream()
.filter(uwc -> metadataService.existsById(uwc.user().getUserId()))
.filter(uwc -> uwc.account().getStatus() != 0)
.map(uwc -> {
var meta = metadataService.getById(uwc.user().getUserId());
return new MemberDto(uwc.user(), uwc.account(),
UserMetadataMapper.toDto(meta));
})
.filter(dto -> dto.metadata().getType().equals((byte) 0))
.sorted(Comparator.comparing(dto -> dto.metadata().getCreatedAt()))
.toList();
}
public List<WaitlistCensoredDto> getWaitlistLimited() {
return getWaitlist().stream()
.map(dto -> {
WaitlistCensoredDto censored = new WaitlistCensoredDto();
censored.setName(NameCensorer.censor(dto.user().getDisplayName()));
return censored;
})
.toList();
}
public MemberDto getByMemberNumber(Integer memberNumber) {
return getAll().stream()
.filter(dto -> dto.metadata().getMemberNumber().equals(memberNumber))
.findFirst()
.orElseThrow(() -> new NotFoundException("No hay socio con ese número"));
}
public MemberDto getByPlotNumber(Integer plotNumber) {
return getAll().stream()
.filter(dto -> dto.metadata().getPlotNumber().equals(plotNumber))
.findFirst()
.orElseThrow(() -> new NotFoundException("No hay socio con ese huerto"));
}
public MemberDto getByDni(String dni) {
return getAll().stream()
.filter(dto -> dni.equals(dto.metadata().getDni()))
.findFirst()
.orElseThrow(() -> new NotFoundException("No hay socio con ese DNI"));
}
public List<VIncomesWithInfoDto> getIncomes(Integer memberNumber) {
return incomeService.getByMemberNumber(memberNumber).stream()
.map(VIncomesWithInfoMapper::toResponse)
.toList();
}
public Boolean hasPaid(Integer memberNumber) {
return incomeService.hasPaid(memberNumber);
}
public Boolean hasCollaborator(Integer memberNumber) {
List<MemberDto> all = getAll();
var member = all.stream()
.filter(dto -> dto.metadata().getMemberNumber().equals(memberNumber))
.findFirst()
.orElse(null);
if (member == null) return false;
Integer plotNumber = member.metadata().getPlotNumber();
if (plotNumber == null) return false;
List<MemberDto> plotMembers = all.stream()
.filter(dto -> plotNumber.equals(dto.metadata().getPlotNumber()))
.toList();
return plotMembers.stream()
.anyMatch(dto -> dto.metadata().getType().equals((byte)3));
}
public Boolean hasGreenhouse(Integer memberNumber) {
return metadataService.getByMemberNumber(memberNumber).getType().equals((byte)2);
}
public Boolean hasCollaboratorRequest(Integer memberNumber) {
UUID userId = metadataService.getByMemberNumber(memberNumber).getUserId();
return requestService.hasCollaboratorRequest(userId);
}
public Boolean hasGreenhouseRequest(Integer memberNumber) {
UUID userId = metadataService.getByMemberNumber(memberNumber).getUserId();
return requestService.hasGreenhouseRequest(userId);
}
public List<DropdownDto> getDropdown() {
return getAll().stream()
.map(DropdownDtoMapper::toDto)
.toList();
}
}

View File

@@ -1,140 +0,0 @@
package net.miarma.backend.huertos.service;
import jakarta.transaction.Transactional;
import net.miarma.backend.huertos.client.HuertosWebClient;
import net.miarma.backend.huertos.mapper.RequestMetadataMapper;
import net.miarma.backend.huertos.model.Request;
import net.miarma.backend.huertos.model.RequestMetadata;
import net.miarma.backend.huertos.model.UserMetadata;
import net.miarma.backlib.dto.UserWithCredentialDto;
import net.miarma.backlib.exception.BadRequestException;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service
public class RequestAcceptanceService {
private final RequestService requestService;
private final UserMetadataService metadataService;
private final HuertosWebClient huertosWebClient;
private final MemberService memberService;
public RequestAcceptanceService(
RequestService requestService,
UserMetadataService metadataService,
HuertosWebClient huertosWebClient,
MemberService memberService
) {
this.requestService = requestService;
this.metadataService = metadataService;
this.huertosWebClient = huertosWebClient;
this.memberService = memberService;
}
public Request acceptRequest(UUID requestId) {
Request request = requestService.accept(requestId);
if (request.getMetadata() == null) {
throw new BadRequestException("No hay metadata asociada");
}
return request;
}
public void handleSideEffects(Request request) {
RequestMetadata metadata = request.getMetadata();
switch (request.getType()) {
case 0: // REGISTER
handleRegister(metadata);
break;
case 1: // UNREGISTER
handleUnregister(metadata);
break;
case 2: // ADD_COLLABORATOR
handleAddCollaborator(metadata);
break;
case 3: // REMOVE_COLLABORATOR
handleRemoveCollaborator(metadata);
break;
case 4: // ADD_GREENHOUSE
handleAddGreenhouse(metadata);
break;
case 5: // REMOVE_GREENHOUSE
handleRemoveGreenhouse(metadata);
break;
default:
throw new BadRequestException("Tipo de solicitud no soportado");
}
}
private void handleRegister(RequestMetadata metadata) {
UserWithCredentialDto createdUser =
huertosWebClient.createUser(RequestMetadataMapper.toDto(metadata));
UserMetadata userMetadata = buildBaseUserMetadata(metadata, createdUser.user().getUserId());
userMetadata.setType((byte) 0); // socio
userMetadata.setRole((byte) 0);
metadataService.create(userMetadata);
}
private void handleUnregister(RequestMetadata metadata) {
UserMetadata toRemove = metadataService.getByMemberNumber(metadata.getMemberNumber());
huertosWebClient.updateCredentialStatus(toRemove.getUserId(), (byte)1, (byte)0);
}
private void handleAddCollaborator(RequestMetadata metadata) {
UserWithCredentialDto newCollab =
huertosWebClient.createUser(RequestMetadataMapper.toDto(metadata));
UserMetadata collabMeta = buildBaseUserMetadata(
metadata,
newCollab.user().getUserId()
);
collabMeta.setType((byte) 3); // colaborador
collabMeta.setRole((byte) 0);
metadataService.create(collabMeta);
}
private void handleRemoveCollaborator(RequestMetadata metadata) {
UserMetadata collab = metadataService.getByMemberNumber(metadata.getMemberNumber());
huertosWebClient.updateCredentialStatus(collab.getUserId(), (byte)1, (byte)0);
}
private void handleAddGreenhouse(RequestMetadata metadata) {
UserMetadata user =
metadataService.getByMemberNumber(metadata.getMemberNumber());
user.setType((byte) 2); // invernadero
metadataService.update(user.getUserId(), user);
}
private void handleRemoveGreenhouse(RequestMetadata metadata) {
UserMetadata user =
metadataService.getByMemberNumber(metadata.getMemberNumber());
user.setType((byte) 1); // socio normal
metadataService.update(user.getUserId(), user);
}
private UserMetadata buildBaseUserMetadata(RequestMetadata metadata, UUID userId) {
UserMetadata um = new UserMetadata();
um.setUserId(userId);
um.setMemberNumber(metadata.getMemberNumber());
um.setPlotNumber(metadata.getPlotNumber());
um.setDni(metadata.getDni());
um.setPhone(metadata.getPhone());
return um;
}
}

View File

@@ -1,140 +0,0 @@
package net.miarma.backend.huertos.service;
import java.time.Instant;
import java.util.List;
import java.util.UUID;
import net.miarma.backend.huertos.dto.RequestDto;
import net.miarma.backend.huertos.dto.RequestMetadataDto;
import net.miarma.backend.huertos.mapper.RequestMapper;
import net.miarma.backend.huertos.mapper.RequestMetadataMapper;
import net.miarma.backend.huertos.validation.RequestValidator;
import net.miarma.backlib.exception.ConflictException;
import org.springframework.stereotype.Service;
import jakarta.transaction.Transactional;
import net.miarma.backend.huertos.model.Request;
import net.miarma.backend.huertos.model.RequestMetadata;
import net.miarma.backend.huertos.repository.RequestRepository;
import net.miarma.backend.huertos.repository.RequestMetadataRepository;
import net.miarma.backlib.exception.BadRequestException;
import net.miarma.backlib.exception.NotFoundException;
import net.miarma.backlib.util.UuidUtil;
@Service
@Transactional
public class RequestService {
private final RequestRepository requestRepository;
private final RequestMetadataRepository metadataRepository;
public RequestService(RequestRepository requestRepository,
RequestMetadataRepository metadataRepository) {
this.requestRepository = requestRepository;
this.metadataRepository = metadataRepository;
}
public List<Request> getAll() {
return requestRepository.findAll();
}
public Request getById(UUID requestId) {
return requestRepository.findById(UuidUtil.uuidToBin(requestId))
.orElseThrow(() -> new NotFoundException("Solicitud no encontrada"));
}
public List<Request> getByUserId(UUID userId) {
return requestRepository.findAll().stream()
.filter(r -> r.getUserId() != null && r.getUserId().equals(userId))
.toList();
}
@Transactional
public Request create(Request request) {
if (request == null) {
throw new BadRequestException("La solicitud es obligatoria");
}
if (request.getType() == null) {
throw new BadRequestException("El tipo de solicitud es obligatorio");
}
if (request.getType() == 1 && hasUnregisterRequest(request.getUserId())) {
throw new ConflictException("Ya tienes una solicitud, espera que se acepte o se elimine al ser rechazada");
}
if ((request.getType() == 2 || request.getType() == 3) &&
hasCollaboratorRequest(request.getUserId())) { // tiene soli de collab
throw new ConflictException("Ya tienes una solicitud, espera que se acepte o se elimine al ser rechazada");
}
if ((request.getType() == 4 || request.getType() == 5) &&
hasGreenhouseRequest(request.getUserId())) { // tiene soli de invernadero
throw new ConflictException("Ya tienes una solicitud, espera que se acepte o se elimine al ser rechazada");
}
request.setRequestId(UUID.randomUUID());
request.setCreatedAt(Instant.now());
request.getMetadata().setRequestId(request.getRequestId());
if (request.getMetadata() != null) {
RequestValidator.validate(request.getMetadata(), request.getType());
}
return requestRepository.save(request);
}
public Request update(UUID requestId, Request changes) {
Request request = getById(requestId);
if (changes.getType() != null) request.setType(changes.getType());
if (changes.getStatus() != null) request.setStatus(changes.getStatus());
if (changes.getUserId() != null) request.setUserId(changes.getUserId());
return requestRepository.save(request);
}
public Request accept(UUID requestId) {
byte[] bin = UuidUtil.uuidToBin(requestId);
Request request = requestRepository.findByIdWithMetadata(bin)
.orElseThrow(() -> new NotFoundException("Request no encontrada"));
if (request.getStatus() != 0) {
throw new BadRequestException("La solicitud ya ha sido procesada");
}
request.setStatus((byte)1);
return requestRepository.save(request);
}
public Request reject(UUID requestId) {
Request request = getById(requestId);
if (request.getStatus() != 0) {
throw new BadRequestException("La solicitud ya ha sido procesada");
}
request.setStatus((byte)2);
return requestRepository.save(request);
}
public void delete(UUID requestId) {
UUID id = requestId;
if (!requestRepository.existsById(UuidUtil.uuidToBin(id))) {
throw new NotFoundException("Solicitud no encontrada");
}
requestRepository.deleteById(UuidUtil.uuidToBin(id));
}
public boolean hasGreenhouseRequest(UUID userId) {
return getByUserId(userId).stream()
.anyMatch(r -> r.getType() == 4 || r.getType() == 5);
}
public boolean hasCollaboratorRequest(UUID userId) {
return getByUserId(userId).stream()
.anyMatch(r -> r.getType() == 2 || r.getType() == 3);
}
public boolean hasUnregisterRequest(UUID userId) {
return getByUserId(userId).stream()
.anyMatch(r -> r.getType() == 1);
}
}

View File

@@ -1,120 +0,0 @@
package net.miarma.backend.huertos.service;
import java.time.Instant;
import java.util.List;
import java.util.UUID;
import net.miarma.backlib.exception.BadRequestException;
import net.miarma.backlib.exception.ConflictException;
import net.miarma.backlib.exception.NotFoundException;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import jakarta.transaction.Transactional;
import net.miarma.backend.huertos.model.UserMetadata;
import net.miarma.backend.huertos.repository.UserMetadataRepository;
import net.miarma.backlib.util.UuidUtil;
@Service
@Transactional
public class UserMetadataService {
private final UserMetadataRepository repository;
public UserMetadataService(UserMetadataRepository repository) {
this.repository = repository;
}
public List<UserMetadata> getAll() {
return repository.findAll();
}
@Cacheable("metadataByUserId")
public UserMetadata getById(UUID userId) {
byte[] idBytes = UuidUtil.uuidToBin(userId);
return repository.findById(idBytes)
.orElseThrow(() -> new NotFoundException("Metadatos de usuario no encontrados"));
}
@Cacheable("metadataByMemberNumber")
public UserMetadata getByMemberNumber(Integer memberNumber) {
return repository.findByMemberNumber(memberNumber)
.orElseThrow(() -> new NotFoundException("Metadatos de usuario no encontrados"));
}
@Cacheable("metadataExists")
public boolean existsById(UUID userId) {
byte[] idBytes = UuidUtil.uuidToBin(userId);
return repository.existsById(idBytes);
}
public UserMetadata create(UserMetadata meta) {
if (meta.getUserId() == null) {
throw new BadRequestException("El identificador de usuario es obligatorio");
}
if (repository.existsById(UuidUtil.uuidToBin(meta.getUserId()))) {
throw new ConflictException("Este usuario ya tiene metadatos asociados");
}
if (meta.getMemberNumber() == null) throw new BadRequestException("El número de socio es obligatorio");
if (meta.getPlotNumber() == null) throw new BadRequestException("El número de huerto es obligatorio");
if (meta.getDni() == null || meta.getDni().isBlank()) throw new BadRequestException("El DNI es obligatorio");
if (meta.getPhone() == null || meta.getPhone().isBlank()) throw new BadRequestException("El teléfono es obligatorio");
if (meta.getType() == null) meta.setType((byte) 0);
if (meta.getRole() == null) meta.setRole((byte) 0);
meta.setCreatedAt(Instant.now());
meta.setAssignedAt(null);
meta.setDeactivatedAt(null);
return repository.save(meta);
}
@CacheEvict(
value = {
"metadataByUserId",
"metadataByMemberNumber",
"metadataExists"
},
key = "#p0"
)
public UserMetadata update(UUID userId, UserMetadata changes) {
byte[] idBytes = UuidUtil.uuidToBin(userId);
UserMetadata metadata = repository.findById(idBytes)
.orElseThrow(() -> new NotFoundException("Metadatos de usuario no encontrados"));
if (changes.getMemberNumber() != null) metadata.setMemberNumber(changes.getMemberNumber());
if (changes.getPlotNumber() != null) metadata.setPlotNumber(changes.getPlotNumber());
if (changes.getDni() != null) metadata.setDni(changes.getDni());
if (changes.getPhone() != null) metadata.setPhone(changes.getPhone());
if (changes.getType() != null) metadata.setType(changes.getType());
if (changes.getRole() != null) metadata.setRole(changes.getRole());
if (changes.getNotes() != null) metadata.setNotes(changes.getNotes());
if (changes.getAssignedAt() != null) metadata.setAssignedAt(changes.getAssignedAt());
if (changes.getDeactivatedAt() != null) metadata.setDeactivatedAt(changes.getDeactivatedAt());
return repository.save(metadata);
}
public void delete(UUID userId) {
byte[] idBytes = UuidUtil.uuidToBin(userId);
if (!repository.existsById(idBytes)) {
throw new NotFoundException("Metadatos de usuario no encontrados");
}
repository.deleteById(idBytes);
}
public Integer getLatestMemberNumber() {
return repository.findAll()
.stream()
.map(UserMetadata::getMemberNumber)
.max(Integer::compareTo)
.get();
}
public Boolean existsByMemberNumber(Integer memberNumber) {
return getByMemberNumber(memberNumber).getUserId() != null;
}
}

View File

@@ -1,24 +0,0 @@
package net.miarma.backend.huertos.service.view;
import java.util.List;
import org.springframework.stereotype.Service;
import jakarta.transaction.Transactional;
import net.miarma.backend.huertos.model.view.VBalanceWithTotals;
import net.miarma.backend.huertos.repository.view.VBalanceWithTotalsRepository;
@Service
@Transactional
public class VBalanceWithTotalsService {
private final VBalanceWithTotalsRepository repository;
public VBalanceWithTotalsService(VBalanceWithTotalsRepository repository) {
this.repository = repository;
}
public List<VBalanceWithTotals> getAll() {
return repository.findAll();
}
}

View File

@@ -1,44 +0,0 @@
package net.miarma.backend.huertos.service.view;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import net.miarma.backend.huertos.model.Income;
import net.miarma.backlib.exception.NotFoundException;
import org.springframework.stereotype.Service;
import jakarta.transaction.Transactional;
import net.miarma.backend.huertos.model.view.VIncomesWithInfo;
import net.miarma.backend.huertos.repository.view.VIncomesWithInfoRepository;
import net.miarma.backlib.util.UuidUtil;
@Service
@Transactional
public class VIncomesWithInfoService {
private final VIncomesWithInfoRepository repository;
public VIncomesWithInfoService(VIncomesWithInfoRepository repository) {
this.repository = repository;
}
public List<VIncomesWithInfo> getAll() {
return repository.findAll().stream()
.sorted(Comparator.comparing(VIncomesWithInfo::getCreatedAt).reversed())
.toList();
}
public VIncomesWithInfo getById(UUID incomeId) {
byte[] idBytes = UuidUtil.uuidToBin(incomeId);
return repository.findById(idBytes)
.orElseThrow(() -> new NotFoundException("Ingreso no encontrado"));
}
public List<VIncomesWithInfo> getByUserId(UUID userId) {
byte[] idBytes = UuidUtil.uuidToBin(userId);
return repository.findAll().stream()
.filter(i -> i.getUserId().equals(userId))
.toList();
}
}

View File

@@ -1,9 +0,0 @@
package net.miarma.backend.huertos.util;
import java.util.Locale;
public class UsernameGenerator {
public static String generate(String name, Integer number) {
return name.split(" ")[0].toLowerCase() + number;
}
}

View File

@@ -1,66 +0,0 @@
package net.miarma.backend.huertos.validation;
/**
* Validador de DNI/NIE español.
* <p>
* Este validador comprueba si un DNI o NIE es válido según las reglas establecidas por la legislación española.
* Un DNI debe tener 8 dígitos seguidos de una letra, y un NIE debe comenzar con X, Y o Z seguido de 7 dígitos y una letra.
*
* @author José Manuel Amador Gallardo
*/
public class DniValidator {
/**
* Valida un DNI o NIE español.
*
* @param id El DNI o NIE a validar.
* @return true si el DNI/NIE es válido, false en caso contrario.
*/
public static boolean isValid(String id) {
if (id == null || id.length() != 9) {
return false;
}
id = id.toUpperCase(); // Pa evitar problemas con minúsculas
String numberPart;
char letterPart = id.charAt(8);
if (id.startsWith("X") || id.startsWith("Y") || id.startsWith("Z")) {
// NIE
char prefix = id.charAt(0);
String numericPrefix = switch (prefix) {
case 'X' -> "0";
case 'Y' -> "1";
case 'Z' -> "2";
default -> null;
};
if (numericPrefix == null) return false;
numberPart = numericPrefix + id.substring(1, 8);
} else {
// DNI
numberPart = id.substring(0, 8);
}
if (!numberPart.matches("\\d{8}")) {
return false;
}
int number = Integer.parseInt(numberPart);
char expectedLetter = calculateLetter(number);
return letterPart == expectedLetter;
}
/**
* Calcula la letra correspondiente a un número de DNI.
*
* @param number El número del DNI (8 dígitos).
* @return La letra correspondiente.
*/
private static char calculateLetter(int number) {
String letters = "TRWAGMYFPDXBNJZSQVHLCKE";
return letters.charAt(number % 23);
}
}

View File

@@ -1,90 +0,0 @@
package net.miarma.backend.huertos.validation;
import net.miarma.backend.huertos.model.RequestMetadata;
import net.miarma.backlib.exception.BadRequestException;
import net.miarma.backlib.exception.ValidationException;
import java.util.regex.Pattern;
public class RequestValidator {
private static final Pattern DNI_PATTERN = Pattern.compile("\\d{8}[A-Za-z]");
private static final Pattern EMAIL_PATTERN = Pattern.compile("^[\\w.%+-]+@[\\w.-]+\\.[a-zA-Z]{2,6}$");
private static final Pattern PHONE_PATTERN = Pattern.compile("^\\+?\\d{9,15}$");
public static void validate(RequestMetadata metadata, Byte requestType) {
if (metadata.getRequestId() == null) {
throw new BadRequestException("Estos metadatos deben pertenecer a una solicitud (falta ID)");
}
if (isBlank(metadata.getDisplayName())) {
throw new BadRequestException("El nombre a mostrar es obligatorio");
} else if (metadata.getDisplayName().length() < 3) {
throw new ValidationException("displayName", "El nombre a mostrar debe tener al menos 3 caracteres");
}
if (isBlank(metadata.getDni())) {
throw new BadRequestException("El DNI es obligatorio");
} else if (!DNI_PATTERN.matcher(metadata.getDni()).matches()) {
throw new ValidationException("dni", "Formato de DNI inválido (ej: 12345678A)");
} else if (!DniValidator.isValid(metadata.getDni())) {
throw new ValidationException("dni", "Este DNI no es un DNI real");
}
if (isBlank(metadata.getEmail())) {
throw new BadRequestException("El email es obligatorio");
} else if (!EMAIL_PATTERN.matcher(metadata.getEmail()).matches()) {
throw new ValidationException("email", "Email inválido");
}
if (isBlank(metadata.getUsername())) {
throw new BadRequestException("El usuario es obligatorio");
} else if (metadata.getUsername().length() < 3) {
throw new ValidationException("username", "El usuario debe tener al menos 3 caracteres");
}
if (metadata.getType() == null) {
throw new BadRequestException("El tipo de usuario es obligatorio");
}
if (requestType == 2) {
if (metadata.getPlotNumber() == null) {
throw new BadRequestException("El colaborador debe tener huerto");
}
}
if (requestType == 0 || requestType == 1) {
if (metadata.getMemberNumber() == null) {
throw new BadRequestException("El número de socio es obligatorio");
}
}
if (requestType == 0) {
if (metadata.getAddress() == null || metadata.getZipCode() == null || metadata.getCity() == null) {
throw new BadRequestException("La dirección, código postal y ciudad son obligatorios");
}
}
if (requestType == 0) {
if (isBlank(metadata.getAddress())) {
throw new ValidationException("address", "La dirección es obligatoria");
}
if (isBlank(metadata.getZipCode())) {
throw new ValidationException("zipCode", "El código postal es obligatorio");
} else if(metadata.getZipCode().length() < 5) {
throw new ValidationException("zipCode", "El código postal debe tener 5 dígitos");
}
if (isBlank(metadata.getCity())) {
throw new ValidationException("city", "La ciudad es obligatoria");
}
}
if (metadata.getPhone() != null && !PHONE_PATTERN.matcher(metadata.getPhone()).matches()) {
throw new ValidationException("phone", "Teléfono inválido (debe tener 9 dígitos)");
}
}
private static boolean isBlank(String s) {
return s == null || s.trim().isEmpty();
}
}

View File

@@ -1,28 +0,0 @@
server:
port: 8081
servlet:
context-path: /v2/huertos
spring:
datasource:
url: jdbc:mariadb://localhost:3306/miarma_v2
username: admin
password: ${DB_PASS}
driver-class-name: org.mariadb.jdbc.Driver
logging:
level:
org.hibernate.SQL: DEBUG
org.hibernate.orm.jdbc.bind: TRACE
core:
url: http://localhost:8080/v2/core
huertos:
user: SYSTEM
password: ${HUERTOS_PASS}
mail:
smtp:
server: smtp.dondominio.com
port: 587

View File

@@ -1,27 +0,0 @@
server:
port: 8081
servlet:
context-path: /v2/huertos
spring:
datasource:
url: jdbc:mariadb://mariadb:3306/miarma_v2
username: ${DB_USER}
password: ${DB_PASS}
driver-class-name: org.mariadb.jdbc.Driver
logging:
level:
org.hibernate.SQL: WARN
core:
url: http://core:8080/v2/core
huertos:
user: SYSTEM
password: ${HUERTOS_PASS}
mail:
smtp:
server: smtp.dondominio.com
port: 587

View File

@@ -1,25 +0,0 @@
spring:
application:
name: huertos-service
jpa:
open-in-view: false
hibernate:
ddl-auto: validate
properties:
hibernate:
jdbc:
time_zone: UTC
jackson:
default-property-inclusion: non_null
time-zone: Europe/Madrid
jwt:
expiration-ms: 3600000
management:
endpoints:
web:
exposure:
include: health,info

View File

@@ -36,14 +36,17 @@ public class PasteController {
}
@GetMapping("/{paste_key}")
public ResponseEntity<PasteDto.Response> getByKey(@PathVariable("paste_key") String pasteKey, @RequestBody PastePassword dto) {
public ResponseEntity<PasteDto.Response> getByKey(
@PathVariable("paste_key") String pasteKey,
@RequestParam(value = "password", required = false) String password
) {
return ResponseEntity.ok(
PasteMapper.toResponse(pasteService.getByKey(pasteKey, dto.password()))
PasteMapper.toResponse(pasteService.getByKey(pasteKey, password))
);
}
@PostMapping
public ResponseEntity<PasteDto.Response> create(PasteDto.Request request) {
public ResponseEntity<PasteDto.Response> create(@RequestBody PasteDto.Request request) {
return ResponseEntity.ok(
PasteMapper.toResponse(
pasteService.create(

View File

@@ -22,7 +22,7 @@ public class Paste {
@Transient
private UUID ownerId;
@Column(name = "paste_key", updatable = false, insertable = false, unique = true, nullable = false)
@Column(name = "paste_key", updatable = false, unique = true, nullable = false)
private String pasteKey;
@Column(nullable = false)

View File

@@ -3,6 +3,7 @@ package net.miarma.backend.mpaste.service;
import jakarta.transaction.Transactional;
import net.miarma.backend.mpaste.model.Paste;
import net.miarma.backend.mpaste.repository.PasteRepository;
import net.miarma.backend.mpaste.util.PasteKeyGenerator;
import net.miarma.backend.mpaste.validation.PasteValidator;
import net.miarma.backlib.exception.ForbiddenException;
import net.miarma.backlib.exception.NotFoundException;
@@ -62,6 +63,8 @@ public class PasteService {
public Paste create(Paste paste) {
PasteValidator.validate(paste);
paste.setPasteId(UUID.randomUUID());
paste.setPasteKey(PasteKeyGenerator.generate(6));
return pasteRepository.save(paste);
}

View File

@@ -11,9 +11,7 @@
<modules>
<module>core</module>
<module>huertos</module>
<module>minecraft</module>
<module>cine</module>
<module>mpaste</module>
<module>backlib</module>
</modules>