diff --git a/backend/exence/src/main/java/com/exence/finance/common/aspect/UserFilterAspect.java b/backend/exence/src/main/java/com/exence/finance/common/aspect/UserFilterAspect.java deleted file mode 100644 index e2c151c7..00000000 --- a/backend/exence/src/main/java/com/exence/finance/common/aspect/UserFilterAspect.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.exence.finance.common.aspect; - -import com.exence.finance.modules.auth.service.UserService; -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.hibernate.Session; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Component; - -@Aspect -@Component -@RequiredArgsConstructor -@Slf4j -public class UserFilterAspect { - @PersistenceContext - private EntityManager entityManager; - - private final UserService userService; - - @SneakyThrows - @Around("execution(* com.exence.finance.modules.*.repository.*Repository.*(..))") - public Object enableUserFilter(ProceedingJoinPoint joinPoint) { - Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - - if (auth != null - && auth.isAuthenticated() - && !"anonymousUser".equals(auth.getPrincipal().toString())) { - Long userId = userService.getCurrentUserId(); - - Session hibernateSession = entityManager.unwrap(Session.class); - hibernateSession.enableFilter("userFilter").setParameter("userId", userId); - } - - return joinPoint.proceed(); - } -} diff --git a/backend/exence/src/main/java/com/exence/finance/common/aspect/WorkspaceFilterAspect.java b/backend/exence/src/main/java/com/exence/finance/common/aspect/WorkspaceFilterAspect.java new file mode 100644 index 00000000..26f80a1f --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/common/aspect/WorkspaceFilterAspect.java @@ -0,0 +1,33 @@ +package com.exence.finance.common.aspect; + +import com.exence.finance.modules.workspace.context.WorkspaceContextHolder; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.hibernate.Session; +import org.springframework.stereotype.Component; + +@Aspect +@Component +@Slf4j +public class WorkspaceFilterAspect { + + @PersistenceContext + private EntityManager entityManager; + + @SneakyThrows + @Around("execution(* com.exence.finance.modules.*.repository.*Repository.*(..))") + public Object enableWorkspaceFilter(ProceedingJoinPoint joinPoint) { + if (WorkspaceContextHolder.isSet()) { + Session hibernateSession = entityManager.unwrap(Session.class); + hibernateSession + .enableFilter("workspaceFilter") + .setParameter("workspaceId", WorkspaceContextHolder.getWorkspaceId()); + } + return joinPoint.proceed(); + } +} diff --git a/backend/exence/src/main/java/com/exence/finance/common/entity/BaseWorkspaceEntity.java b/backend/exence/src/main/java/com/exence/finance/common/entity/BaseWorkspaceEntity.java new file mode 100644 index 00000000..362a6ecf --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/common/entity/BaseWorkspaceEntity.java @@ -0,0 +1,25 @@ +package com.exence.finance.common.entity; + +import com.exence.finance.modules.workspace.entity.Workspace; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.MappedSuperclass; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.SuperBuilder; + +@Getter +@Setter +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@MappedSuperclass +public abstract class BaseWorkspaceEntity extends BaseAuditableEntity { + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "workspace_id", nullable = false) + private Workspace workspace; +} diff --git a/backend/exence/src/main/java/com/exence/finance/common/exception/ErrorCode.java b/backend/exence/src/main/java/com/exence/finance/common/exception/ErrorCode.java index bbd9520a..6278232e 100644 --- a/backend/exence/src/main/java/com/exence/finance/common/exception/ErrorCode.java +++ b/backend/exence/src/main/java/com/exence/finance/common/exception/ErrorCode.java @@ -18,6 +18,11 @@ public enum ErrorCode { ACCESS_DENIED(HttpStatus.FORBIDDEN, "access-denied"), INVALID_TOKEN(HttpStatus.FORBIDDEN, "invalid-token"), EMAIL_VERIFICATION_REQUIRED(HttpStatus.FORBIDDEN, "email-verification-required"), + WORKSPACE_NOT_FOUND(HttpStatus.FORBIDDEN, "workspace-not-found"), + WORKSPACE_CANNOT_DELETE_LAST(HttpStatus.FORBIDDEN, "workspace-cannot-delete-last"), + WORKSPACE_OWNER_CANNOT_LEAVE(HttpStatus.FORBIDDEN, "workspace-owner-cannot-leave"), + WORKSPACE_OWNER_CANNOT_BE_REMOVED(HttpStatus.FORBIDDEN, "workspace-owner-cannot-be-removed"), + WORKSPACE_OWNER_REQUIRED(HttpStatus.FORBIDDEN, "workspace-owner-required"), // 404 - Not Found USER_NOT_FOUND(HttpStatus.NOT_FOUND, "user-not-found"), @@ -32,11 +37,13 @@ public enum ErrorCode { // 409 - Conflict EMAIL_ALREADY_IN_USE(HttpStatus.CONFLICT, "email-already-in-use"), + WORKSPACE_MEMBER_ALREADY_EXISTS(HttpStatus.CONFLICT, "workspace-member-already-exists"), CATEGORY_ALREADY_EXISTS(HttpStatus.CONFLICT, "category-already-exists"), CATEGORY_IN_USE(HttpStatus.CONFLICT, "category-in-use"), DATA_INTEGRITY_VIOLATION(HttpStatus.CONFLICT, "data-integrity-violation"), // 400 - Bad Request + WORKSPACE_HEADER_MISSING(HttpStatus.BAD_REQUEST, "workspace-header-missing"), INVALID_PASSWORD(HttpStatus.BAD_REQUEST, "invalid-password"), WIDGET_TYPE_MISMATCH(HttpStatus.BAD_REQUEST, "widget-type-mismatch"), INVALID_WIDGET_SETTING(HttpStatus.BAD_REQUEST, "invalid-widget-setting"), diff --git a/backend/exence/src/main/java/com/exence/finance/common/util/ValidationConstants.java b/backend/exence/src/main/java/com/exence/finance/common/util/ValidationConstants.java index b1d84832..a6dc3c46 100644 --- a/backend/exence/src/main/java/com/exence/finance/common/util/ValidationConstants.java +++ b/backend/exence/src/main/java/com/exence/finance/common/util/ValidationConstants.java @@ -34,7 +34,9 @@ public final class ValidationConstants { // User settings validations public static final int LANGUAGE_CODE_LENGTH = 2; - public static final int CURRENCY_CODE_LENGTH = 3; + + // Workspace validations + public static final int WORKSPACE_NAME_MAX_LENGTH = 100; // Category validations public static final int CATEGORY_NAME_MIN_LENGTH = 1; diff --git a/backend/exence/src/main/java/com/exence/finance/config/CacheConfig.java b/backend/exence/src/main/java/com/exence/finance/config/CacheConfig.java index 55200fc7..3cf61e3f 100644 --- a/backend/exence/src/main/java/com/exence/finance/config/CacheConfig.java +++ b/backend/exence/src/main/java/com/exence/finance/config/CacheConfig.java @@ -20,7 +20,7 @@ public class CacheConfig { public CacheManager cacheManager() { ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager(); - cacheManager.setCacheNames(List.of("currentUser", "currentUserId", "systemSettings")); + cacheManager.setCacheNames(List.of("currentUser", "currentUserId", "systemSettings", "workspaceMembership")); return cacheManager; } diff --git a/backend/exence/src/main/java/com/exence/finance/config/WebConfig.java b/backend/exence/src/main/java/com/exence/finance/config/WebConfig.java index daf8a698..c93b0ba9 100644 --- a/backend/exence/src/main/java/com/exence/finance/config/WebConfig.java +++ b/backend/exence/src/main/java/com/exence/finance/config/WebConfig.java @@ -4,6 +4,7 @@ import com.exence.finance.common.converter.StringToTimeframeConverter; import com.exence.finance.common.converter.StringToTransactionTypeConverter; import com.exence.finance.security.EmailVerificationInterceptor; +import com.exence.finance.security.WorkspaceInterceptor; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; @@ -17,6 +18,7 @@ public class WebConfig implements WebMvcConfigurer { private final StringToCategoryTypeConverter stringToCategoryTypeConverter; private final StringToTimeframeConverter stringToTimeframeConverter; private final EmailVerificationInterceptor emailVerificationInterceptor; + private final WorkspaceInterceptor workspaceInterceptor; @Override public void addFormatters(FormatterRegistry registry) { @@ -30,5 +32,9 @@ public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(emailVerificationInterceptor) .addPathPatterns("/api/**") .excludePathPatterns("/api/auth/**"); + + registry.addInterceptor(workspaceInterceptor) + .addPathPatterns("/api/**") + .excludePathPatterns("/api/auth/**", "/api/admin/**", "/api/exchange-rates/**"); } } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/AchievementChecker.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/AchievementChecker.java index 22bdaabe..f7d11aae 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/AchievementChecker.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/AchievementChecker.java @@ -6,5 +6,5 @@ public interface AchievementChecker { AchievementType getSupportedType(); - long computeCurrentValue(Long userId); + long computeCurrentValue(Long workspaceId); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/AppStreakChecker.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/AppStreakChecker.java index 594180f4..532f5000 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/AppStreakChecker.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/AppStreakChecker.java @@ -4,6 +4,7 @@ import com.exence.finance.modules.achievement.checker.AchievementChecker; import com.exence.finance.modules.achievement.enums.AchievementType; import com.exence.finance.modules.transaction.repository.TransactionRepository; +import java.sql.Date; import java.time.LocalDate; import java.util.List; import lombok.RequiredArgsConstructor; @@ -22,9 +23,11 @@ public AchievementType getSupportedType() { @Override @ReadTransactional - public long computeCurrentValue(Long userId) { + public long computeCurrentValue(Long workspaceId) { // TODO: make it weekly streak - List dates = transactionRepository.findDistinctCreatedAtByUserId(userId); + List dates = transactionRepository.findDistinctCreatedAtByWorkspaceId(workspaceId).stream() + .map(Date::toLocalDate) + .toList(); if (dates.isEmpty()) { return 0; } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/DebtCountChecker.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/DebtCountChecker.java index fdff1026..f63685b2 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/DebtCountChecker.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/DebtCountChecker.java @@ -20,7 +20,7 @@ public AchievementType getSupportedType() { @Override @ReadTransactional - public long computeCurrentValue(Long userId) { - return debtRepository.countAllByUserId(userId); + public long computeCurrentValue(Long workspaceId) { + return debtRepository.countAllByWorkspaceId(workspaceId); } } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/DebtSettledChecker.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/DebtSettledChecker.java index eadb7272..75d1b75b 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/DebtSettledChecker.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/DebtSettledChecker.java @@ -21,7 +21,7 @@ public AchievementType getSupportedType() { @Override @ReadTransactional - public long computeCurrentValue(Long userId) { - return debtRepository.countByUserIdAndStatus(userId, DebtStatus.SETTLED); + public long computeCurrentValue(Long workspaceId) { + return debtRepository.countByWorkspaceIdAndStatus(workspaceId, DebtStatus.SETTLED); } } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/GoalCompletedChecker.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/GoalCompletedChecker.java index 28b666d9..f568cca8 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/GoalCompletedChecker.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/GoalCompletedChecker.java @@ -21,7 +21,7 @@ public AchievementType getSupportedType() { @Override @ReadTransactional - public long computeCurrentValue(Long userId) { - return goalRepository.countByUserIdAndStatus(userId, GoalStatus.COMPLETED); + public long computeCurrentValue(Long workspaceId) { + return goalRepository.countByWorkspaceIdAndStatus(workspaceId, GoalStatus.COMPLETED); } } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/GoalCountChecker.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/GoalCountChecker.java index 12e6d7b1..0448b194 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/GoalCountChecker.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/GoalCountChecker.java @@ -20,7 +20,7 @@ public AchievementType getSupportedType() { @Override @ReadTransactional - public long computeCurrentValue(Long userId) { - return goalRepository.countAllByUserId(userId); + public long computeCurrentValue(Long workspaceId) { + return goalRepository.countAllByWorkspaceId(workspaceId); } } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/TransactionCountChecker.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/TransactionCountChecker.java index 67b55c9a..d827278d 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/TransactionCountChecker.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/checker/impl/TransactionCountChecker.java @@ -20,7 +20,7 @@ public AchievementType getSupportedType() { @Override @ReadTransactional - public long computeCurrentValue(Long userId) { - return transactionRepository.countByUserId(userId); + public long computeCurrentValue(Long workspaceId) { + return transactionRepository.countByWorkspaceId(workspaceId); } } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/controller/AchievementController.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/controller/AchievementController.java index fae3cdd9..35e55943 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/controller/AchievementController.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/controller/AchievementController.java @@ -1,7 +1,7 @@ package com.exence.finance.modules.achievement.controller; import com.exence.finance.modules.achievement.dto.AchievementGetDTO; -import com.exence.finance.modules.achievement.dto.UserAchievementGetDTO; +import com.exence.finance.modules.achievement.dto.WorkspaceAchievementGetDTO; import java.util.List; import org.springframework.http.ResponseEntity; @@ -9,5 +9,5 @@ public interface AchievementController { ResponseEntity> getAllAchievements(); - ResponseEntity> getUnlockedAchievements(); + ResponseEntity> getUnlockedAchievements(); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/controller/impl/AchievementControllerImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/controller/impl/AchievementControllerImpl.java index b7f3344b..8743d37a 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/controller/impl/AchievementControllerImpl.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/controller/impl/AchievementControllerImpl.java @@ -3,7 +3,7 @@ import com.exence.finance.common.util.ResponseFactory; import com.exence.finance.modules.achievement.controller.AchievementController; import com.exence.finance.modules.achievement.dto.AchievementGetDTO; -import com.exence.finance.modules.achievement.dto.UserAchievementGetDTO; +import com.exence.finance.modules.achievement.dto.WorkspaceAchievementGetDTO; import com.exence.finance.modules.achievement.service.AchievementService; import java.util.List; import lombok.RequiredArgsConstructor; @@ -27,7 +27,7 @@ public ResponseEntity> getAllAchievements() { } @GetMapping("/unlocked") - public ResponseEntity> getUnlockedAchievements() { + public ResponseEntity> getUnlockedAchievements() { return ResponseFactory.ok(achievementService.getUnlockedAchievements()); } } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/dto/UserAchievementGetDTO.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/dto/WorkspaceAchievementGetDTO.java similarity index 91% rename from backend/exence/src/main/java/com/exence/finance/modules/achievement/dto/UserAchievementGetDTO.java rename to backend/exence/src/main/java/com/exence/finance/modules/achievement/dto/WorkspaceAchievementGetDTO.java index 9dffb2c4..d5be05ca 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/dto/UserAchievementGetDTO.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/dto/WorkspaceAchievementGetDTO.java @@ -4,7 +4,7 @@ import com.exence.finance.modules.achievement.enums.AchievementType; import java.time.Instant; -public record UserAchievementGetDTO( +public record WorkspaceAchievementGetDTO( Long id, Long achievementId, String name, diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/entity/AchievementProgress.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/entity/AchievementProgress.java index ff52c002..24b0482d 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/entity/AchievementProgress.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/entity/AchievementProgress.java @@ -3,7 +3,7 @@ import static com.exence.finance.common.util.ValidationConstants.ACHIEVEMENT_TYPE_MAX_LENGTH; import com.exence.finance.modules.achievement.enums.AchievementType; -import com.exence.finance.modules.auth.entity.User; +import com.exence.finance.modules.workspace.entity.Workspace; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; @@ -28,8 +28,8 @@ name = "achievement_progress", uniqueConstraints = @UniqueConstraint( - columnNames = {"user_id", "achievement_type"}, - name = "uq_achievement_progress_user_type")) + columnNames = {"workspace_id", "achievement_type"}, + name = "uq_achievement_progress_workspace_type")) @Getter @Setter @Builder @@ -47,8 +47,8 @@ public class AchievementProgress { private Long id; @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "user_id", nullable = false) - private User user; + @JoinColumn(name = "workspace_id", nullable = false) + private Workspace workspace; @Enumerated(EnumType.STRING) @Column(name = "achievement_type", nullable = false, length = ACHIEVEMENT_TYPE_MAX_LENGTH) diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/entity/UserAchievement.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/entity/WorkspaceAchievement.java similarity index 69% rename from backend/exence/src/main/java/com/exence/finance/modules/achievement/entity/UserAchievement.java rename to backend/exence/src/main/java/com/exence/finance/modules/achievement/entity/WorkspaceAchievement.java index 421e2e2a..70e9713b 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/entity/UserAchievement.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/entity/WorkspaceAchievement.java @@ -1,6 +1,6 @@ package com.exence.finance.modules.achievement.entity; -import com.exence.finance.modules.auth.entity.User; +import com.exence.finance.modules.workspace.entity.Workspace; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; @@ -22,27 +22,30 @@ @Entity @Table( - name = "user_achievement", + name = "workspace_achievement", uniqueConstraints = @UniqueConstraint( - columnNames = {"user_id", "achievement_id"}, - name = "uq_user_achievement")) + columnNames = {"workspace_id", "achievement_id"}, + name = "uq_workspace_achievement")) @Getter @Setter @Builder @NoArgsConstructor @AllArgsConstructor -public class UserAchievement { +public class WorkspaceAchievement { @Id - @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_achievement_id_seq") - @SequenceGenerator(name = "user_achievement_id_seq", sequenceName = "user_achievement_id_seq", allocationSize = 1) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "workspace_achievement_id_seq") + @SequenceGenerator( + name = "workspace_achievement_id_seq", + sequenceName = "workspace_achievement_id_seq", + allocationSize = 1) @Column(name = "id") private Long id; @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "user_id", nullable = false) - private User user; + @JoinColumn(name = "workspace_id", nullable = false) + private Workspace workspace; @ManyToOne(fetch = FetchType.LAZY, optional = false) @JoinColumn(name = "achievement_id", nullable = false) diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/listener/AchievementListener.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/listener/AchievementListener.java index db81125d..26c79349 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/listener/AchievementListener.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/listener/AchievementListener.java @@ -30,36 +30,36 @@ public class AchievementListener { @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) public void onTransactionCreated(TransactionCreatedEvent event) { - log.debug("Processing achievements for TRANSACTION_COUNT and APP_STREAK, userId={}", event.userId()); - achievementService.processAchievement(event.userId(), TRANSACTION_COUNT); - achievementService.processAchievement(event.userId(), APP_STREAK); + log.debug("Processing achievements for TRANSACTION_COUNT and APP_STREAK, workspaceId={}", event.workspaceId()); + achievementService.processAchievement(event.workspaceId(), TRANSACTION_COUNT); + achievementService.processAchievement(event.workspaceId(), APP_STREAK); } @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) public void onGoalCreated(GoalCreatedEvent event) { - log.debug("Processing achievements for GOAL_COUNT, userId={}", event.userId()); - achievementService.processAchievement(event.userId(), GOAL_COUNT); + log.debug("Processing achievements for GOAL_COUNT, workspaceId={}", event.workspaceId()); + achievementService.processAchievement(event.workspaceId(), GOAL_COUNT); } @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) public void onGoalCompleted(GoalCompletedEvent event) { - log.debug("Processing achievements for GOAL_COMPLETED, userId={}", event.userId()); - achievementService.processAchievement(event.userId(), GOAL_COMPLETED); + log.debug("Processing achievements for GOAL_COMPLETED, workspaceId={}", event.workspaceId()); + achievementService.processAchievement(event.workspaceId(), GOAL_COMPLETED); } @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) public void onDebtCreated(DebtCreatedEvent event) { - log.debug("Processing achievements for DEBT_COUNT, userId={}", event.userId()); - achievementService.processAchievement(event.userId(), DEBT_COUNT); + log.debug("Processing achievements for DEBT_COUNT, workspaceId={}", event.workspaceId()); + achievementService.processAchievement(event.workspaceId(), DEBT_COUNT); } @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) public void onDebtSettled(DebtSettledEvent event) { - log.debug("Processing achievements for DEBT_SETTLED, userId={}", event.userId()); - achievementService.processAchievement(event.userId(), DEBT_SETTLED); + log.debug("Processing achievements for DEBT_SETTLED, workspaceId={}", event.workspaceId()); + achievementService.processAchievement(event.workspaceId(), DEBT_SETTLED); } } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/repository/AchievementProgressRepository.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/repository/AchievementProgressRepository.java index a7b3c883..08e83661 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/repository/AchievementProgressRepository.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/repository/AchievementProgressRepository.java @@ -12,12 +12,12 @@ @Repository public interface AchievementProgressRepository extends JpaRepository { - @Query("SELECT ap FROM AchievementProgress ap WHERE ap.user.id = :userId AND ap.achievementType = :type") - Optional findByUserIdAndType(Long userId, AchievementType type); + @Query("SELECT ap FROM AchievementProgress ap WHERE ap.workspace.id = :workspaceId AND ap.achievementType = :type") + Optional findByWorkspaceIdAndType(Long workspaceId, AchievementType type); @Query("SELECT " + "new com.exence.finance.modules.achievement.dto.projection.ProgressProjection(" + "ap.achievementType, ap.currentValue" + ") " - + "FROM AchievementProgress ap WHERE ap.user.id = :userId") - List findAllByUserId(Long userId); + + "FROM AchievementProgress ap WHERE ap.workspace.id = :workspaceId") + List findAllByWorkspaceId(Long workspaceId); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/repository/UserAchievementRepository.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/repository/UserAchievementRepository.java deleted file mode 100644 index 56ce45a7..00000000 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/repository/UserAchievementRepository.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.exence.finance.modules.achievement.repository; - -import com.exence.finance.modules.achievement.entity.UserAchievement; -import com.exence.finance.modules.achievement.enums.AchievementTier; -import com.exence.finance.modules.achievement.enums.AchievementType; -import java.util.List; -import java.util.Set; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.stereotype.Repository; - -@Repository -public interface UserAchievementRepository extends JpaRepository { - - @Query("SELECT ua FROM UserAchievement ua JOIN FETCH ua.achievement WHERE ua.user.id = :userId") - List findByUserId(Long userId); - - @Query("SELECT ua.achievement.id FROM UserAchievement ua WHERE ua.user.id = :userId") - Set findUnlockedAchievementIdsByUserId(Long userId); - - @Query("SELECT COUNT(ua) > 0 FROM UserAchievement ua " - + "WHERE ua.user.id = :userId " - + "AND ua.achievement.type = :type " - + "AND ua.achievement.tier = :tier") - boolean existsByUserIdAndTypeAndTier(Long userId, AchievementType type, AchievementTier tier); -} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/repository/WorkspaceAchievementRepository.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/repository/WorkspaceAchievementRepository.java new file mode 100644 index 00000000..697ff1c8 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/repository/WorkspaceAchievementRepository.java @@ -0,0 +1,26 @@ +package com.exence.finance.modules.achievement.repository; + +import com.exence.finance.modules.achievement.entity.WorkspaceAchievement; +import com.exence.finance.modules.achievement.enums.AchievementTier; +import com.exence.finance.modules.achievement.enums.AchievementType; +import java.util.List; +import java.util.Set; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +@Repository +public interface WorkspaceAchievementRepository extends JpaRepository { + + @Query("SELECT wa FROM WorkspaceAchievement wa JOIN FETCH wa.achievement WHERE wa.workspace.id = :workspaceId") + List findByWorkspaceId(Long workspaceId); + + @Query("SELECT wa.achievement.id FROM WorkspaceAchievement wa WHERE wa.workspace.id = :workspaceId") + Set findUnlockedAchievementIdsByWorkspaceId(Long workspaceId); + + @Query("SELECT COUNT(wa) > 0 FROM WorkspaceAchievement wa " + + "WHERE wa.workspace.id = :workspaceId " + + "AND wa.achievement.type = :type " + + "AND wa.achievement.tier = :tier") + boolean existsByWorkspaceIdAndTypeAndTier(Long workspaceId, AchievementType type, AchievementTier tier); +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/service/AchievementService.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/service/AchievementService.java index cff99365..b638d902 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/service/AchievementService.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/service/AchievementService.java @@ -1,7 +1,7 @@ package com.exence.finance.modules.achievement.service; import com.exence.finance.modules.achievement.dto.AchievementGetDTO; -import com.exence.finance.modules.achievement.dto.UserAchievementGetDTO; +import com.exence.finance.modules.achievement.dto.WorkspaceAchievementGetDTO; import com.exence.finance.modules.achievement.enums.AchievementType; import java.util.List; @@ -9,7 +9,7 @@ public interface AchievementService { List getAllAchievements(); - List getUnlockedAchievements(); + List getUnlockedAchievements(); - void processAchievement(Long userId, AchievementType type); + void processAchievement(Long workspaceId, AchievementType type); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/achievement/service/impl/AchievementServiceImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/achievement/service/impl/AchievementServiceImpl.java index fc1734a1..7752f048 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/achievement/service/impl/AchievementServiceImpl.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/achievement/service/impl/AchievementServiceImpl.java @@ -5,20 +5,20 @@ import com.exence.finance.common.i18n.I18nService; import com.exence.finance.modules.achievement.checker.AchievementChecker; import com.exence.finance.modules.achievement.dto.AchievementGetDTO; -import com.exence.finance.modules.achievement.dto.UserAchievementGetDTO; +import com.exence.finance.modules.achievement.dto.WorkspaceAchievementGetDTO; import com.exence.finance.modules.achievement.dto.projection.ProgressProjection; import com.exence.finance.modules.achievement.entity.Achievement; import com.exence.finance.modules.achievement.entity.AchievementProgress; -import com.exence.finance.modules.achievement.entity.UserAchievement; +import com.exence.finance.modules.achievement.entity.WorkspaceAchievement; import com.exence.finance.modules.achievement.enums.AchievementTier; import com.exence.finance.modules.achievement.enums.AchievementType; import com.exence.finance.modules.achievement.repository.AchievementProgressRepository; import com.exence.finance.modules.achievement.repository.AchievementRepository; -import com.exence.finance.modules.achievement.repository.UserAchievementRepository; +import com.exence.finance.modules.achievement.repository.WorkspaceAchievementRepository; import com.exence.finance.modules.achievement.service.AchievementService; -import com.exence.finance.modules.auth.entity.User; -import com.exence.finance.modules.auth.repository.UserRepository; -import com.exence.finance.modules.auth.service.UserService; +import com.exence.finance.modules.workspace.context.WorkspaceContextHolder; +import com.exence.finance.modules.workspace.entity.Workspace; +import com.exence.finance.modules.workspace.repository.WorkspaceRepository; import java.util.List; import java.util.Map; import java.util.Set; @@ -32,29 +32,30 @@ @RequiredArgsConstructor public class AchievementServiceImpl implements AchievementService { - private final UserService userService; + private final WorkspaceRepository workspaceRepository; private final AchievementRepository achievementRepository; - private final UserAchievementRepository userAchievementRepository; + private final WorkspaceAchievementRepository workspaceAchievementRepository; private final AchievementProgressRepository achievementProgressRepository; - private final UserRepository userRepository; private final List checkers; private final I18nService i18n; @ReadTransactional public List getAllAchievements() { - Long userId = userService.getCurrentUserId(); + Long workspaceId = WorkspaceContextHolder.getWorkspaceId(); List achievements = achievementRepository.findAll(); - Map unlockedMap = userAchievementRepository.findByUserId(userId).stream() - .collect(Collectors.toMap(ua -> ua.getAchievement().getId(), ua -> ua)); + Map unlockedMap = + workspaceAchievementRepository.findByWorkspaceId(workspaceId).stream() + .collect(Collectors.toMap(wa -> wa.getAchievement().getId(), wa -> wa)); - Map progressMap = achievementProgressRepository.findAllByUserId(userId).stream() - .collect(Collectors.toMap(ProgressProjection::type, ProgressProjection::currentValue)); + Map progressMap = + achievementProgressRepository.findAllByWorkspaceId(workspaceId).stream() + .collect(Collectors.toMap(ProgressProjection::type, ProgressProjection::currentValue)); return achievements.stream() .map(a -> { boolean unlocked = unlockedMap.containsKey(a.getId()); - UserAchievement ua = unlockedMap.get(a.getId()); + WorkspaceAchievement wa = unlockedMap.get(a.getId()); long progress = progressMap.getOrDefault(a.getType(), 0L); return new AchievementGetDTO( a.getId(), @@ -65,68 +66,69 @@ public List getAllAchievements() { a.getRequirementValue(), Math.min(progress, a.getRequirementValue()), unlocked, - ua != null ? ua.getUnlockedAt() : null); + wa != null ? wa.getUnlockedAt() : null); }) .toList(); } @ReadTransactional - public List getUnlockedAchievements() { - Long userId = userService.getCurrentUserId(); - return userAchievementRepository.findByUserId(userId).stream() - .map(ua -> new UserAchievementGetDTO( - ua.getId(), - ua.getAchievement().getId(), - i18n.get(ua.getAchievement().getName()), - i18n.get(ua.getAchievement().getDescription()), - ua.getAchievement().getTier(), - ua.getAchievement().getType(), - ua.getAchievement().getRequirementValue(), - ua.getUnlockedAt())) + public List getUnlockedAchievements() { + Long workspaceId = WorkspaceContextHolder.getWorkspaceId(); + return workspaceAchievementRepository.findByWorkspaceId(workspaceId).stream() + .map(wa -> new WorkspaceAchievementGetDTO( + wa.getId(), + wa.getAchievement().getId(), + i18n.get(wa.getAchievement().getName()), + i18n.get(wa.getAchievement().getDescription()), + wa.getAchievement().getTier(), + wa.getAchievement().getType(), + wa.getAchievement().getRequirementValue(), + wa.getUnlockedAt())) .toList(); } @WriteTransactional - public void processAchievement(Long userId, AchievementType type) { - if (userAchievementRepository.existsByUserIdAndTypeAndTier(userId, type, AchievementTier.GOLD)) { - log.debug("Skipping achievement processing, user (userId={}) already has GOLD for type={}", userId, type); + public void processAchievement(Long workspaceId, AchievementType type) { + if (workspaceAchievementRepository.existsByWorkspaceIdAndTypeAndTier(workspaceId, type, AchievementTier.GOLD)) { + log.debug( + "Skipping achievement processing, workspace (workspaceId={}) already has GOLD for type={}", + workspaceId, + type); return; } - // get relevant checker AchievementChecker checker = checkers.stream() .filter(c -> c.getSupportedType() == type) .findFirst() .orElseThrow(() -> new IllegalArgumentException("No checker found for type: " + type)); - long currentValue = checker.computeCurrentValue(userId); + long currentValue = checker.computeCurrentValue(workspaceId); - User userRef = userRepository.getReferenceById(userId); + Workspace workspaceRef = workspaceRepository.getReferenceById(workspaceId); - // upsert AchievementProgress progress = achievementProgressRepository - .findByUserIdAndType(userId, type) + .findByWorkspaceIdAndType(workspaceId, type) .orElseGet(() -> AchievementProgress.builder() - .user(userRef) + .workspace(workspaceRef) .achievementType(type) .currentValue(0L) .build()); progress.setCurrentValue(currentValue); achievementProgressRepository.save(progress); - Set alreadyUnlocked = userAchievementRepository.findUnlockedAchievementIdsByUserId(userId); + Set alreadyUnlocked = workspaceAchievementRepository.findUnlockedAchievementIdsByWorkspaceId(workspaceId); List qualified = achievementRepository.findQualifiedByType(type, currentValue); for (Achievement achievement : qualified) { if (!alreadyUnlocked.contains(achievement.getId())) { - UserAchievement ua = UserAchievement.builder() - .user(userRef) + WorkspaceAchievement wa = WorkspaceAchievement.builder() + .workspace(workspaceRef) .achievement(achievement) .build(); - userAchievementRepository.save(ua); + workspaceAchievementRepository.save(wa); log.info( - "Achievement unlocked: userId={}, achievement={} ({})", - userId, + "Achievement unlocked: workspaceId={}, achievement={} ({})", + workspaceId, achievement.getName(), achievement.getTier()); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/request/RegisterRequest.java b/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/request/RegisterRequest.java index 41cc4587..9634bd34 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/request/RegisterRequest.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/request/RegisterRequest.java @@ -6,8 +6,10 @@ import com.exence.finance.common.annotations.ValidStrictEmail; import com.exence.finance.common.annotations.ValidUsername; import com.exence.finance.common.dto.SupportedCurrency; +import com.exence.finance.common.util.ValidationConstants; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; @PasswordMatches(password = "password", confirmPassword = "confirmPassword") public record RegisterRequest( @@ -15,11 +17,13 @@ public record RegisterRequest( @ValidStrictEmail @UniqueEmail String email, @ValidPassword String password, @NotBlank(message = "{validation.confirm-password.not-blank}") String confirmPassword, - @NotNull SupportedCurrency baseCurrency) { + @NotNull SupportedCurrency baseCurrency, + @NotBlank @Size(max = ValidationConstants.WORKSPACE_NAME_MAX_LENGTH) String workspaceName) { @Override public String toString() { return "RegisterRequest[username=" + username + ", email=" + email - + ", password=[PROTECTED], confirmPassword=[PROTECTED], baseCurrency=" + baseCurrency + "]"; + + ", password=[PROTECTED], confirmPassword=[PROTECTED], baseCurrency=" + baseCurrency + + ", workspaceName=" + workspaceName + "]"; } } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/request/UpdateUserSettingsRequest.java b/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/request/UpdateUserSettingsRequest.java index 0edec111..f2a960f8 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/request/UpdateUserSettingsRequest.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/request/UpdateUserSettingsRequest.java @@ -1,12 +1,6 @@ package com.exence.finance.modules.auth.dto.request; import com.exence.finance.common.annotations.ValidLanguage; -import com.exence.finance.common.dto.SupportedCurrency; import com.exence.finance.modules.auth.dto.Theme; -public record UpdateUserSettingsRequest( - @ValidLanguage String language, - Theme primaryTheme, - Theme secondaryTheme, - SupportedCurrency baseCurrency, - Boolean showBaseCurrency) {} +public record UpdateUserSettingsRequest(@ValidLanguage String language, Theme primaryTheme, Theme secondaryTheme) {} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/response/AuthenticationResponse.java b/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/response/AuthenticationResponse.java index 444bf51f..0cde53f9 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/response/AuthenticationResponse.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/response/AuthenticationResponse.java @@ -4,4 +4,4 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.validation.Valid; -public record AuthenticationResponse(@Valid UserGetDTO user, @JsonIgnore TokenPair tokens) {} +public record AuthenticationResponse(@Valid UserGetDTO user, @JsonIgnore TokenPair tokens, Long workspaceId) {} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/response/UserSettingsResponse.java b/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/response/UserSettingsResponse.java index 36547c73..cf073b92 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/response/UserSettingsResponse.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/auth/dto/response/UserSettingsResponse.java @@ -1,11 +1,5 @@ package com.exence.finance.modules.auth.dto.response; -import com.exence.finance.common.dto.SupportedCurrency; import com.exence.finance.modules.auth.dto.Theme; -public record UserSettingsResponse( - String language, - Theme primaryTheme, - Theme secondaryTheme, - SupportedCurrency baseCurrency, - boolean showBaseCurrency) {} +public record UserSettingsResponse(String language, Theme primaryTheme, Theme secondaryTheme) {} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/auth/entity/User.java b/backend/exence/src/main/java/com/exence/finance/modules/auth/entity/User.java index 73cdec4c..f512a27a 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/auth/entity/User.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/auth/entity/User.java @@ -4,9 +4,7 @@ import static com.exence.finance.common.util.ValidationConstants.ROLE_MAX_LENGTH; import static com.exence.finance.common.util.ValidationConstants.USERNAME_MAX_LENGTH; -import com.exence.finance.modules.category.entity.Category; import com.exence.finance.modules.email.entity.EmailLog; -import com.exence.finance.modules.transaction.entity.Transaction; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -43,10 +41,10 @@ @AllArgsConstructor @EqualsAndHashCode( callSuper = false, - exclude = {"transactions", "categories", "tokens", "emailLogs", "passwordHistories", "settings"}) + exclude = {"tokens", "emailLogs", "passwordHistories", "settings"}) @ToString( callSuper = true, - exclude = {"transactions", "categories", "tokens", "password", "emailLogs", "passwordHistories", "settings"}) + exclude = {"tokens", "password", "emailLogs", "passwordHistories", "settings"}) @Table(name = "_user") public class User implements UserDetails { @@ -84,12 +82,6 @@ public class User implements UserDetails { @Builder.Default private Role role = Role.USER; - @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true) - private List transactions; - - @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true) - private List categories; - @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true) private Set tokens; diff --git a/backend/exence/src/main/java/com/exence/finance/modules/auth/entity/UserSettings.java b/backend/exence/src/main/java/com/exence/finance/modules/auth/entity/UserSettings.java index 211b658d..dbea3298 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/auth/entity/UserSettings.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/auth/entity/UserSettings.java @@ -2,7 +2,6 @@ import static com.exence.finance.common.util.ValidationConstants.LANGUAGE_CODE_LENGTH; -import com.exence.finance.common.dto.SupportedCurrency; import com.exence.finance.modules.auth.dto.Theme; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -61,13 +60,4 @@ public class UserSettings { @JdbcTypeCode(SqlTypes.NAMED_ENUM) @Column(name = "secondary_theme", nullable = false) private Theme secondaryTheme; - - @NotNull - @JdbcTypeCode(SqlTypes.NAMED_ENUM) - @Column(name = "base_currency", nullable = false) - private SupportedCurrency baseCurrency; - - @NotNull - @Column(name = "show_base_currency", nullable = false) - private Boolean showBaseCurrency; } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/auth/mapper/UserMapper.java b/backend/exence/src/main/java/com/exence/finance/modules/auth/mapper/UserMapper.java index ef41d2ca..b1d6c860 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/auth/mapper/UserMapper.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/auth/mapper/UserMapper.java @@ -32,8 +32,6 @@ public abstract class UserMapper { @Mapping(target = "createdAt", ignore = true) // AfterMapping @Mapping(target = "role", ignore = true) // AfterMapping @Mapping(target = "id", ignore = true) - @Mapping(target = "transactions", ignore = true) - @Mapping(target = "categories", ignore = true) @Mapping(target = "tokens", ignore = true) @Mapping(target = "emailLogs", ignore = true) @Mapping(target = "passwordHistories", ignore = true) @@ -54,8 +52,6 @@ protected void finalizeRegistration(RegisterRequest request, @MappingTarget User @Mapping(target = "password", ignore = true) @Mapping(target = "emailVerified", ignore = true) @Mapping(target = "lastLoginAt", ignore = true) - @Mapping(target = "transactions", ignore = true) - @Mapping(target = "categories", ignore = true) @Mapping(target = "tokens", ignore = true) @Mapping(target = "emailLogs", ignore = true) @Mapping(target = "passwordHistories", ignore = true) diff --git a/backend/exence/src/main/java/com/exence/finance/modules/auth/repository/UserRepository.java b/backend/exence/src/main/java/com/exence/finance/modules/auth/repository/UserRepository.java index ca8f8761..0fb59697 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/auth/repository/UserRepository.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/auth/repository/UserRepository.java @@ -15,8 +15,8 @@ public interface UserRepository extends JpaRepository { @Query( """ SELECT u FROM User u WHERE u.emailVerified = true AND ( - NOT EXISTS (SELECT t FROM Transaction t WHERE t.user = u) - OR (SELECT MAX(t.createdAt) FROM Transaction t WHERE t.user = u) < :threshold + NOT EXISTS (SELECT t FROM Transaction t WHERE t.createdBy = u.email) + OR (SELECT MAX(t.createdAt) FROM Transaction t WHERE t.createdBy = u.email) < :threshold ) """) List findInactiveUsers(Instant threshold); diff --git a/backend/exence/src/main/java/com/exence/finance/modules/auth/repository/UserSettingsRepository.java b/backend/exence/src/main/java/com/exence/finance/modules/auth/repository/UserSettingsRepository.java index d3977843..f731e59e 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/auth/repository/UserSettingsRepository.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/auth/repository/UserSettingsRepository.java @@ -1,15 +1,9 @@ package com.exence.finance.modules.auth.repository; -import com.exence.finance.common.dto.SupportedCurrency; import com.exence.finance.modules.auth.entity.UserSettings; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; public interface UserSettingsRepository extends JpaRepository { Optional findByUserId(Long userId); - - @Query("SELECT us.baseCurrency FROM UserSettings us WHERE us.user.id = :userId") - Optional findBaseCurrencyByUserId(@Param("userId") Long userId); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/auth/service/UserService.java b/backend/exence/src/main/java/com/exence/finance/modules/auth/service/UserService.java index 68fec369..f7297db9 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/auth/service/UserService.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/auth/service/UserService.java @@ -23,4 +23,6 @@ public interface UserService { void requestVerifyEmail(); void deleteUser(); + + User getUserByEmail(String email); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/auth/service/impl/AuthServiceImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/auth/service/impl/AuthServiceImpl.java index bd843018..d154e3de 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/auth/service/impl/AuthServiceImpl.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/auth/service/impl/AuthServiceImpl.java @@ -1,7 +1,6 @@ package com.exence.finance.modules.auth.service.impl; import com.exence.finance.common.annotations.transaction.WriteTransactional; -import com.exence.finance.common.dto.SupportedCurrency; import com.exence.finance.common.exception.ErrorCode; import com.exence.finance.common.exception.ExenceException; import com.exence.finance.modules.auth.dto.EmailType; @@ -35,6 +34,8 @@ import com.exence.finance.modules.statistics.entity.Widget; import com.exence.finance.modules.statistics.repository.WidgetRepository; import com.exence.finance.modules.systemsettings.service.SystemSettingsService; +import com.exence.finance.modules.workspace.entity.Workspace; +import com.exence.finance.modules.workspace.service.WorkspaceMembershipService; import jakarta.servlet.http.HttpServletRequest; import java.time.Instant; import java.util.Collections; @@ -69,6 +70,7 @@ public class AuthServiceImpl implements AuthService { private final SystemSettingsService systemSettingsService; private final CookieService cookieService; private final UserSettingsRepository userSettingsRepository; + private final WorkspaceMembershipService workspaceMembershipService; @Override @WriteTransactional @@ -87,11 +89,13 @@ private AuthenticationResponse internalRegister(RegisterRequest request, Role ro user.setRole(role); user = userRepository.save(user); - createUserSettings(user, request.baseCurrency()); - createDefaultDashboardWidget(user); + createUserSettings(user); + Workspace workspace = workspaceMembershipService.createDefaultWorkspace( + user, request.workspaceName(), request.baseCurrency()); + createDefaultDashboardWidget(workspace); sendEmailVerification(user); - return createAuthenticationResponse(user); + return createAuthenticationResponse(user, workspace.getId()); } @Override @@ -112,7 +116,7 @@ public AuthenticationResponse login(LoginRequest request) { user.setLastLoginAt(Instant.now()); user = userRepository.save(user); - return createAuthenticationResponse(user); + return createAuthenticationResponse(user, null); } @Override @@ -204,13 +208,15 @@ public void sendEmailVerification(User user) { emailService.sendVerificationEmail(user, verificationToken.getToken()); } - private AuthenticationResponse createAuthenticationResponse(User user) { + private AuthenticationResponse createAuthenticationResponse(User user, Long workspaceId) { String sessionId = UUID.randomUUID().toString(); Token accessToken = tokenManagementService.createAndSaveToken(user, TokenType.ACCESS, sessionId); Token refreshToken = tokenManagementService.createAndSaveToken(user, TokenType.REFRESH, sessionId); return new AuthenticationResponse( - userMapper.mapToUserGetDto(user), new TokenPair(accessToken.getToken(), refreshToken.getToken())); + userMapper.mapToUserGetDto(user), + new TokenPair(accessToken.getToken(), refreshToken.getToken()), + workspaceId); } private void authenticateUser(LoginRequest request) { @@ -222,9 +228,9 @@ private void authenticateUser(LoginRequest request) { } } - private void createDefaultDashboardWidget(User user) { + private void createDefaultDashboardWidget(Workspace workspace) { Widget widget = Widget.builder() - .user(user) + .workspace(workspace) .type(WidgetType.DASHBOARD_BALANCE_TREND) .title("Balance Trend") .timeframe(Timeframe.YTD) @@ -238,14 +244,12 @@ private void createDefaultDashboardWidget(User user) { widgetRepository.save(widget); } - private void createUserSettings(User user, SupportedCurrency baseCurrency) { + private void createUserSettings(User user) { UserSettings settings = UserSettings.builder() .user(user) .language("en") .primaryTheme(Theme.DARK) .secondaryTheme(Theme.BLUE_DOLPHIN) - .baseCurrency(baseCurrency) - .showBaseCurrency(false) .build(); userSettingsRepository.save(settings); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/auth/service/impl/UserServiceImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/auth/service/impl/UserServiceImpl.java index d9920692..ca7cf2e3 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/auth/service/impl/UserServiceImpl.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/auth/service/impl/UserServiceImpl.java @@ -86,6 +86,11 @@ public Long getCurrentUserId() { return getCurrentUser().getId(); } + @ReadTransactional + public User getUserByEmail(String email) { + return userRepository.findByEmail(email).orElseThrow(() -> new ExenceException(ErrorCode.USER_NOT_FOUND)); + } + @WriteTransactional @CacheEvict( value = {"currentUser", "currentUserId"}, diff --git a/backend/exence/src/main/java/com/exence/finance/modules/auth/service/impl/UserSettingsServiceImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/auth/service/impl/UserSettingsServiceImpl.java index 6efcdcc4..94827a2a 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/auth/service/impl/UserSettingsServiceImpl.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/auth/service/impl/UserSettingsServiceImpl.java @@ -3,6 +3,8 @@ import com.exence.finance.common.annotations.transaction.ReadTransactional; import com.exence.finance.common.annotations.transaction.WriteTransactional; import com.exence.finance.common.dto.SupportedCurrency; +import com.exence.finance.common.exception.ErrorCode; +import com.exence.finance.common.exception.ExenceException; import com.exence.finance.modules.auth.dto.request.UpdateUserSettingsRequest; import com.exence.finance.modules.auth.dto.response.UserSettingsResponse; import com.exence.finance.modules.auth.entity.UserSettings; @@ -10,10 +12,10 @@ import com.exence.finance.modules.auth.repository.UserSettingsRepository; import com.exence.finance.modules.auth.service.UserService; import com.exence.finance.modules.auth.service.UserSettingsService; -import com.exence.finance.modules.transaction.event.BaseCurrencyChangedEvent; +import com.exence.finance.modules.workspace.context.WorkspaceContextHolder; +import com.exence.finance.modules.workspace.repository.WorkspaceSettingsRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; @Service @@ -23,7 +25,7 @@ public class UserSettingsServiceImpl implements UserSettingsService { private final UserSettingsRepository userSettingsRepository; private final UserSettingsMapper userSettingsMapper; private final UserService userService; - private final ApplicationEventPublisher eventPublisher; + private final WorkspaceSettingsRepository workspaceSettingsRepository; @Override @ReadTransactional @@ -35,23 +37,20 @@ public UserSettingsResponse getCurrentUserSettings() { @WriteTransactional public UserSettingsResponse updateCurrentUserSettings(UpdateUserSettingsRequest request) { UserSettings settings = getCurrentSettings(); - SupportedCurrency oldBaseCurrency = settings.getBaseCurrency(); - SupportedCurrency newBaseCurrency = request.baseCurrency(); - userSettingsMapper.updateFromRequest(request, settings); settings = userSettingsRepository.save(settings); + return userSettingsMapper.toResponse(settings); + } - if (newBaseCurrency != null && newBaseCurrency != oldBaseCurrency) { - log.info( - "Base currency changed from {} to {} for user {}", - oldBaseCurrency, - newBaseCurrency, - settings.getUser().getId()); - // publish event instead of circular transactionService dependency - eventPublisher.publishEvent(new BaseCurrencyChangedEvent(newBaseCurrency)); + @Override + public SupportedCurrency getUserBaseCurrency() { + Long workspaceId = WorkspaceContextHolder.getWorkspaceId(); + if (workspaceId == null) { + throw new ExenceException(ErrorCode.WORKSPACE_HEADER_MISSING); } - - return userSettingsMapper.toResponse(settings); + return workspaceSettingsRepository + .findBaseCurrencyByWorkspaceId(workspaceId) + .orElseThrow(() -> new IllegalStateException("Settings not found for workspace " + workspaceId)); } private UserSettings getCurrentSettings() { @@ -60,11 +59,4 @@ private UserSettings getCurrentSettings() { .findByUserId(userId) .orElseThrow(() -> new IllegalStateException("Settings not found for user " + userId)); } - - public SupportedCurrency getUserBaseCurrency() { - Long userId = userService.getCurrentUserId(); - return userSettingsRepository - .findBaseCurrencyByUserId(userId) - .orElseThrow(() -> new IllegalStateException("Settings not found for user " + userId)); - } } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/category/entity/Category.java b/backend/exence/src/main/java/com/exence/finance/modules/category/entity/Category.java index 6596b110..67a600b2 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/category/entity/Category.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/category/entity/Category.java @@ -4,8 +4,7 @@ import static com.exence.finance.common.util.ValidationConstants.CATEGORY_NAME_MAX_LENGTH; import static com.exence.finance.common.util.ValidationConstants.CATEGORY_NOTE_MAX_LENGTH; -import com.exence.finance.common.entity.BaseAuditableEntity; -import com.exence.finance.modules.auth.entity.User; +import com.exence.finance.common.entity.BaseWorkspaceEntity; import com.exence.finance.modules.category.dto.CategoryType; import com.exence.finance.modules.category.dto.MaterialIcon; import com.exence.finance.modules.transaction.entity.Transaction; @@ -15,8 +14,6 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToMany; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; @@ -39,13 +36,13 @@ @AllArgsConstructor @EqualsAndHashCode( callSuper = false, - exclude = {"user", "transactions"}) + exclude = {"transactions"}) @ToString( callSuper = true, - exclude = {"user", "transactions"}) + exclude = {"transactions"}) @Table(name = "category") -@Filter(name = "userFilter", condition = "user_id = :userId") -public class Category extends BaseAuditableEntity { +@Filter(name = "workspaceFilter", condition = "workspace_id = :workspaceId") +public class Category extends BaseWorkspaceEntity { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "category_id_seq") @@ -74,10 +71,6 @@ public class Category extends BaseAuditableEntity { @Column(name = "note", length = CATEGORY_NOTE_MAX_LENGTH) private String note; - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "user_id", nullable = false) - private User user; - @OneToMany(mappedBy = "category", fetch = FetchType.LAZY) private List transactions; } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/category/mapper/CategoryMapper.java b/backend/exence/src/main/java/com/exence/finance/modules/category/mapper/CategoryMapper.java index a51a5663..ce3d68ea 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/category/mapper/CategoryMapper.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/category/mapper/CategoryMapper.java @@ -22,7 +22,7 @@ public interface CategoryMapper { CategoryGetDTO mapToCategoryGetDTO(Category category, BigDecimal balance); @Mapping(target = "id", ignore = true) - @Mapping(target = "user", ignore = true) + @Mapping(target = "workspace", ignore = true) @Mapping(target = "transactions", ignore = true) @Mapping(target = "createdAt", ignore = true) @Mapping(target = "updatedAt", ignore = true) @@ -31,7 +31,7 @@ public interface CategoryMapper { Category mapToCategory(CategoryCreateDTO categoryCreateDTO); @Mapping(target = "id", ignore = true) - @Mapping(target = "user", ignore = true) + @Mapping(target = "workspace", ignore = true) @Mapping(target = "transactions", ignore = true) @Mapping(target = "createdAt", ignore = true) @Mapping(target = "updatedAt", ignore = true) diff --git a/backend/exence/src/main/java/com/exence/finance/modules/category/service/impl/CategoryServiceImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/category/service/impl/CategoryServiceImpl.java index 84b3e824..40530bb9 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/category/service/impl/CategoryServiceImpl.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/category/service/impl/CategoryServiceImpl.java @@ -4,8 +4,6 @@ import com.exence.finance.common.annotations.transaction.WriteTransactional; import com.exence.finance.common.exception.ErrorCode; import com.exence.finance.common.exception.ExenceException; -import com.exence.finance.modules.auth.entity.User; -import com.exence.finance.modules.auth.service.UserService; import com.exence.finance.modules.category.dto.CategoryCreateDTO; import com.exence.finance.modules.category.dto.CategoryFilter; import com.exence.finance.modules.category.dto.CategoryGetDTO; @@ -17,6 +15,7 @@ import com.exence.finance.modules.category.repository.CategoryRepository; import com.exence.finance.modules.category.service.CategoryService; import com.exence.finance.modules.statistics.event.MaterializedViewRefreshEvent; +import com.exence.finance.modules.workspace.service.WorkspaceMembershipService; import com.exence.finance.modules.transaction.dto.TransactionType; import java.math.BigDecimal; import java.util.List; @@ -31,8 +30,8 @@ public class CategoryServiceImpl implements CategoryService { private final CategoryRepository categoryRepository; private final CategoryMapper categoryMapper; - private final UserService userService; private final ApplicationEventPublisher eventPublisher; + private final WorkspaceMembershipService workspaceMembershipService; @ReadTransactional public Category getCategory(Long id) { @@ -80,14 +79,12 @@ public List getTopCategoriesByTotalAmount(CategoryFilte @WriteTransactional public CategoryGetDTO createCategory(CategoryCreateDTO categoryCreateDTO) { - User user = userService.getCurrentUser(); - if (categoryRepository.existsByName(categoryCreateDTO.name())) { throw new ExenceException(ErrorCode.CATEGORY_ALREADY_EXISTS); } Category category = categoryMapper.mapToCategory(categoryCreateDTO); - category.setUser(user); + category.setWorkspace(workspaceMembershipService.getWorkspaceReference()); Category savedCategory = categoryRepository.save(category); return categoryMapper.mapToCategoryGetDTO(savedCategory); diff --git a/backend/exence/src/main/java/com/exence/finance/modules/debt/entity/Debt.java b/backend/exence/src/main/java/com/exence/finance/modules/debt/entity/Debt.java index ef730da6..7dfe6fba 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/debt/entity/Debt.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/debt/entity/Debt.java @@ -8,8 +8,7 @@ import static com.exence.finance.common.util.ValidationConstants.TRANSACTION_AMOUNT_PRECISION; import com.exence.finance.common.dto.SupportedCurrency; -import com.exence.finance.common.entity.BaseAuditableEntity; -import com.exence.finance.modules.auth.entity.User; +import com.exence.finance.common.entity.BaseWorkspaceEntity; import com.exence.finance.modules.category.entity.Category; import com.exence.finance.modules.debt.enums.DebtStatus; import com.exence.finance.modules.debt.enums.DebtType; @@ -48,13 +47,13 @@ @FieldNameConstants @EqualsAndHashCode( callSuper = false, - exclude = {"user", "category"}) + exclude = {"category"}) @ToString( callSuper = true, - exclude = {"user", "category"}) + exclude = {"category"}) @Table(name = "debt") -@Filter(name = "userFilter", condition = "user_id = :userId") -public class Debt extends BaseAuditableEntity { +@Filter(name = "workspaceFilter", condition = "workspace_id = :workspaceId") +public class Debt extends BaseWorkspaceEntity { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "debt_id_seq") @@ -130,8 +129,4 @@ public class Debt extends BaseAuditableEntity { @ManyToOne(fetch = FetchType.LAZY, optional = false) @JoinColumn(name = "category_id", nullable = false) private Category category; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "user_id", nullable = false) - private User user; } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/debt/event/DebtCreatedEvent.java b/backend/exence/src/main/java/com/exence/finance/modules/debt/event/DebtCreatedEvent.java index 9960b631..f5781fe5 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/debt/event/DebtCreatedEvent.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/debt/event/DebtCreatedEvent.java @@ -1,3 +1,3 @@ package com.exence.finance.modules.debt.event; -public record DebtCreatedEvent(Long userId) {} +public record DebtCreatedEvent(Long workspaceId) {} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/debt/event/DebtSettledEvent.java b/backend/exence/src/main/java/com/exence/finance/modules/debt/event/DebtSettledEvent.java index 4f388f6c..99023938 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/debt/event/DebtSettledEvent.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/debt/event/DebtSettledEvent.java @@ -1,3 +1,3 @@ package com.exence.finance.modules.debt.event; -public record DebtSettledEvent(Long userId) {} +public record DebtSettledEvent(Long workspaceId) {} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/debt/mapper/DebtMapper.java b/backend/exence/src/main/java/com/exence/finance/modules/debt/mapper/DebtMapper.java index b9ee0320..817c3d93 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/debt/mapper/DebtMapper.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/debt/mapper/DebtMapper.java @@ -24,7 +24,7 @@ public interface DebtMapper { DebtGetDTO mapToGetDTO(Debt debt); @Mapping(target = "id", ignore = true) - @Mapping(target = "user", ignore = true) + @Mapping(target = "workspace", ignore = true) @Mapping(target = "category", ignore = true) @Mapping(target = "status", ignore = true) @Mapping(target = "remainingAmount", ignore = true) @@ -37,7 +37,7 @@ public interface DebtMapper { Debt mapFromCreateDTO(DebtCreateDTO dto); @Mapping(target = "id", ignore = true) - @Mapping(target = "user", ignore = true) + @Mapping(target = "workspace", ignore = true) @Mapping(target = "category", ignore = true) @Mapping(target = "currency", ignore = true) @Mapping(target = "originalAmount", ignore = true) diff --git a/backend/exence/src/main/java/com/exence/finance/modules/debt/repository/DebtRepository.java b/backend/exence/src/main/java/com/exence/finance/modules/debt/repository/DebtRepository.java index c2440ee1..cf30186f 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/debt/repository/DebtRepository.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/debt/repository/DebtRepository.java @@ -19,7 +19,7 @@ public interface DebtRepository extends JpaRepository { Optional find(Long id); @Query("SELECT d FROM Debt d") - List findAllUserFiltered(); + List findAllWorkspaceFiltered(); @Query("SELECT d FROM Debt d WHERE d.status IN :statuses") List findByStatusIn(List statuses); @@ -41,9 +41,9 @@ public interface DebtRepository extends JpaRepository { + "AND d.status = :activeStatus") int expireOverdueDebts(DebtStatus newStatus, LocalDate today, DebtStatus activeStatus); - @Query("SELECT COUNT(d) FROM Debt d WHERE d.user.id = :userId") - long countAllByUserId(Long userId); + @Query("SELECT COUNT(d) FROM Debt d WHERE d.workspace.id = :workspaceId") + long countAllByWorkspaceId(Long workspaceId); - @Query("SELECT COUNT(d) FROM Debt d WHERE d.user.id = :userId AND d.status = :status") - long countByUserIdAndStatus(Long userId, DebtStatus status); + @Query("SELECT COUNT(d) FROM Debt d WHERE d.workspace.id = :workspaceId AND d.status = :status") + long countByWorkspaceIdAndStatus(Long workspaceId, DebtStatus status); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/debt/service/impl/DebtServiceImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/debt/service/impl/DebtServiceImpl.java index 4aae5851..5c5d1d8e 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/debt/service/impl/DebtServiceImpl.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/debt/service/impl/DebtServiceImpl.java @@ -5,7 +5,6 @@ import com.exence.finance.common.dto.SupportedCurrency; import com.exence.finance.common.exception.ErrorCode; import com.exence.finance.common.exception.ExenceException; -import com.exence.finance.modules.auth.service.UserService; import com.exence.finance.modules.category.service.CategoryService; import com.exence.finance.modules.debt.dto.DebtCreateDTO; import com.exence.finance.modules.debt.dto.DebtGetDTO; @@ -14,11 +13,14 @@ import com.exence.finance.modules.debt.entity.Debt; import com.exence.finance.modules.debt.enums.DebtStatus; import com.exence.finance.modules.debt.enums.DebtType; +import com.exence.finance.modules.debt.event.DebtCreatedEvent; import com.exence.finance.modules.debt.event.DebtSettledEvent; import com.exence.finance.modules.debt.mapper.DebtMapper; import com.exence.finance.modules.debt.repository.DebtRepository; import com.exence.finance.modules.debt.service.DebtService; import com.exence.finance.modules.exchangerate.service.ExchangeRateService; +import com.exence.finance.modules.workspace.context.WorkspaceContextHolder; +import com.exence.finance.modules.workspace.service.WorkspaceMembershipService; import java.math.BigDecimal; import java.time.LocalDate; import java.util.List; @@ -32,10 +34,10 @@ public class DebtServiceImpl implements DebtService { private final DebtRepository debtRepository; private final CategoryService categoryService; - private final UserService userService; private final ExchangeRateService exchangeRateService; private final DebtMapper debtMapper; private final ApplicationEventPublisher eventPublisher; + private final WorkspaceMembershipService workspaceMembershipService; @ReadTransactional public List getDebts(List statuses, DebtType type) { @@ -51,7 +53,7 @@ public List getDebts(List statuses, DebtType type) { } else if (hasType) { debts = debtRepository.findByType(type); } else { - debts = debtRepository.findAllUserFiltered(); + debts = debtRepository.findAllWorkspaceFiltered(); } return debts.stream().map(debtMapper::mapToGetDTO).toList(); } @@ -64,7 +66,7 @@ public DebtGetDTO getDebtById(Long id) { @WriteTransactional public DebtGetDTO createDebt(DebtCreateDTO dto) { Debt debt = debtMapper.mapFromCreateDTO(dto); - debt.setUser(userService.getCurrentUser()); + debt.setWorkspace(workspaceMembershipService.getWorkspaceReference()); debt.setCategory(categoryService.getCategory(dto.categoryId())); debt.setRemainingAmount(dto.originalAmount()); debt.setStatus(DebtStatus.ACTIVE); @@ -75,7 +77,7 @@ public DebtGetDTO createDebt(DebtCreateDTO dto) { debt.setRemainingBaseCurrencyAmount(originalBaseCurrencyAmount); Debt savedDebt = debtRepository.save(debt); - eventPublisher.publishEvent(savedDebt.getUser().getId()); + eventPublisher.publishEvent(new DebtCreatedEvent(WorkspaceContextHolder.getWorkspaceId())); return debtMapper.mapToGetDTO(savedDebt); } @@ -93,7 +95,7 @@ public DebtGetDTO patchDebt(Long id, DebtPatchDTO dto) { Debt savedDebt = debtRepository.save(debt); if (savedDebt.getStatus() == DebtStatus.SETTLED && previousStatus != DebtStatus.SETTLED) { - eventPublisher.publishEvent(new DebtSettledEvent(savedDebt.getUser().getId())); + eventPublisher.publishEvent(new DebtSettledEvent(WorkspaceContextHolder.getWorkspaceId())); } return debtMapper.mapToGetDTO(savedDebt); @@ -125,7 +127,7 @@ public DebtGetDTO makePayment(Long id, DebtPaymentDTO dto) { Debt savedDebt = debtRepository.save(debt); if (nowSettled) { - eventPublisher.publishEvent(new DebtSettledEvent(savedDebt.getUser().getId())); + eventPublisher.publishEvent(new DebtSettledEvent(WorkspaceContextHolder.getWorkspaceId())); } return debtMapper.mapToGetDTO(savedDebt); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/goal/entity/Goal.java b/backend/exence/src/main/java/com/exence/finance/modules/goal/entity/Goal.java index 4fb7a91f..ff09a5f0 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/goal/entity/Goal.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/goal/entity/Goal.java @@ -8,8 +8,7 @@ import static com.exence.finance.common.util.ValidationConstants.TRANSACTION_AMOUNT_PRECISION; import com.exence.finance.common.dto.SupportedCurrency; -import com.exence.finance.common.entity.BaseAuditableEntity; -import com.exence.finance.modules.auth.entity.User; +import com.exence.finance.common.entity.BaseWorkspaceEntity; import com.exence.finance.modules.category.entity.Category; import com.exence.finance.modules.goal.enums.GoalStatus; import jakarta.persistence.Column; @@ -46,13 +45,13 @@ @FieldNameConstants @EqualsAndHashCode( callSuper = false, - exclude = {"user", "category"}) + exclude = {"category"}) @ToString( callSuper = true, - exclude = {"user", "category"}) + exclude = {"category"}) @Table(name = "goal") -@Filter(name = "userFilter", condition = "user_id = :userId") -public class Goal extends BaseAuditableEntity { +@Filter(name = "workspaceFilter", condition = "workspace_id = :workspaceId") +public class Goal extends BaseWorkspaceEntity { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "goal_id_seq") @@ -120,8 +119,4 @@ public class Goal extends BaseAuditableEntity { @ManyToOne(fetch = FetchType.LAZY, optional = false) @JoinColumn(name = "category_id", nullable = false) private Category category; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "user_id", nullable = false) - private User user; } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/goal/event/GoalCompletedEvent.java b/backend/exence/src/main/java/com/exence/finance/modules/goal/event/GoalCompletedEvent.java index 9f77ed7b..3da95071 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/goal/event/GoalCompletedEvent.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/goal/event/GoalCompletedEvent.java @@ -1,3 +1,3 @@ package com.exence.finance.modules.goal.event; -public record GoalCompletedEvent(Long userId) {} +public record GoalCompletedEvent(Long workspaceId) {} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/goal/event/GoalCreatedEvent.java b/backend/exence/src/main/java/com/exence/finance/modules/goal/event/GoalCreatedEvent.java index 93ecc6b3..94dea4f8 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/goal/event/GoalCreatedEvent.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/goal/event/GoalCreatedEvent.java @@ -1,3 +1,3 @@ package com.exence.finance.modules.goal.event; -public record GoalCreatedEvent(Long userId) {} +public record GoalCreatedEvent(Long workspaceId) {} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/goal/mapper/GoalMapper.java b/backend/exence/src/main/java/com/exence/finance/modules/goal/mapper/GoalMapper.java index b830268b..77fff676 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/goal/mapper/GoalMapper.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/goal/mapper/GoalMapper.java @@ -24,7 +24,7 @@ public interface GoalMapper { GoalGetDTO mapToGetDTO(Goal goal); @Mapping(target = "id", ignore = true) - @Mapping(target = "user", ignore = true) + @Mapping(target = "workspace", ignore = true) @Mapping(target = "category", ignore = true) @Mapping(target = "status", ignore = true) @Mapping(target = "currentAmount", ignore = true) @@ -37,7 +37,7 @@ public interface GoalMapper { Goal mapFromCreateDTO(GoalCreateDTO dto); @Mapping(target = "id", ignore = true) - @Mapping(target = "user", ignore = true) + @Mapping(target = "workspace", ignore = true) @Mapping(target = "category", ignore = true) @Mapping(target = "status", ignore = true) @Mapping(target = "currentAmount", ignore = true) diff --git a/backend/exence/src/main/java/com/exence/finance/modules/goal/repository/GoalRepository.java b/backend/exence/src/main/java/com/exence/finance/modules/goal/repository/GoalRepository.java index 03556db8..708c6e62 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/goal/repository/GoalRepository.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/goal/repository/GoalRepository.java @@ -21,7 +21,7 @@ public interface GoalRepository extends JpaRepository { List findByStatusIn(List statuses); @Query("SELECT g FROM Goal g") - List findAllUserFiltered(); + List findAllWorkspaceFiltered(); @Query("SELECT COUNT(g) FROM Goal g WHERE g.status = :status") long countByStatus(GoalStatus status); @@ -41,9 +41,9 @@ public interface GoalRepository extends JpaRepository { + "AND g.status IN :activeStatuses") int expireOverdueGoals(GoalStatus newStatus, LocalDate today, List activeStatuses); - @Query("SELECT COUNT(g) FROM Goal g WHERE g.user.id = :userId") - long countAllByUserId(Long userId); + @Query("SELECT COUNT(g) FROM Goal g WHERE g.workspace.id = :workspaceId") + long countAllByWorkspaceId(Long workspaceId); - @Query("SELECT COUNT(g) FROM Goal g WHERE g.user.id = :userId AND g.status = :status") - long countByUserIdAndStatus(Long userId, GoalStatus status); + @Query("SELECT COUNT(g) FROM Goal g WHERE g.workspace.id = :workspaceId AND g.status = :status") + long countByWorkspaceIdAndStatus(Long workspaceId, GoalStatus status); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/goal/service/impl/GoalServiceImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/goal/service/impl/GoalServiceImpl.java index 7064928d..5037ebbb 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/goal/service/impl/GoalServiceImpl.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/goal/service/impl/GoalServiceImpl.java @@ -5,7 +5,6 @@ import com.exence.finance.common.dto.SupportedCurrency; import com.exence.finance.common.exception.ErrorCode; import com.exence.finance.common.exception.ExenceException; -import com.exence.finance.modules.auth.service.UserService; import com.exence.finance.modules.category.service.CategoryService; import com.exence.finance.modules.exchangerate.service.ExchangeRateService; import com.exence.finance.modules.goal.dto.GoalCreateDTO; @@ -20,6 +19,8 @@ import com.exence.finance.modules.goal.repository.GoalProgressRepository; import com.exence.finance.modules.goal.repository.GoalRepository; import com.exence.finance.modules.goal.service.GoalService; +import com.exence.finance.modules.workspace.context.WorkspaceContextHolder; +import com.exence.finance.modules.workspace.service.WorkspaceMembershipService; import java.math.BigDecimal; import java.time.LocalDate; import java.util.List; @@ -34,10 +35,10 @@ public class GoalServiceImpl implements GoalService { private final GoalRepository goalRepository; private final GoalProgressRepository goalProgressRepository; private final CategoryService categoryService; - private final UserService userService; private final ExchangeRateService exchangeRateService; private final GoalMapper goalMapper; private final ApplicationEventPublisher eventPublisher; + private final WorkspaceMembershipService workspaceMembershipService; @ReadTransactional public Goal getGoal(Long id) { @@ -47,7 +48,7 @@ public Goal getGoal(Long id) { @ReadTransactional public List getGoalsByStatuses(List statuses) { List goals = statuses == null || statuses.isEmpty() - ? goalRepository.findAllUserFiltered() + ? goalRepository.findAllWorkspaceFiltered() : goalRepository.findByStatusIn(statuses); return goals.stream().map(goalMapper::mapToGetDTO).toList(); } @@ -60,7 +61,7 @@ public GoalGetDTO getGoalById(Long id) { @WriteTransactional public GoalGetDTO createGoal(GoalCreateDTO dto) { Goal goal = goalMapper.mapFromCreateDTO(dto); - goal.setUser(userService.getCurrentUser()); + goal.setWorkspace(workspaceMembershipService.getWorkspaceReference()); goal.setCategory(categoryService.getCategory(dto.categoryId())); BigDecimal initialAmount = dto.initialAmount() != null ? dto.initialAmount() : BigDecimal.ZERO; @@ -79,10 +80,10 @@ public GoalGetDTO createGoal(GoalCreateDTO dto) { Goal savedGoal = goalRepository.save(goal); recordProgress(savedGoal, initialAmount); - eventPublisher.publishEvent(new GoalCreatedEvent(savedGoal.getUser().getId())); + Long workspaceId = WorkspaceContextHolder.getWorkspaceId(); + eventPublisher.publishEvent(new GoalCreatedEvent(workspaceId)); if (status == GoalStatus.COMPLETED) { - eventPublisher.publishEvent( - new GoalCompletedEvent(savedGoal.getUser().getId())); + eventPublisher.publishEvent(new GoalCompletedEvent(workspaceId)); } return goalMapper.mapToGetDTO(savedGoal); @@ -124,8 +125,7 @@ public GoalGetDTO patchGoal(Long id, GoalPatchDTO dto) { Goal savedGoal = goalRepository.save(goal); if (savedGoal.getStatus() == GoalStatus.COMPLETED && previousStatus != GoalStatus.COMPLETED) { - eventPublisher.publishEvent( - new GoalCompletedEvent(savedGoal.getUser().getId())); + eventPublisher.publishEvent(new GoalCompletedEvent(WorkspaceContextHolder.getWorkspaceId())); } return goalMapper.mapToGetDTO(savedGoal); diff --git a/backend/exence/src/main/java/com/exence/finance/modules/investment/entity/Investment.java b/backend/exence/src/main/java/com/exence/finance/modules/investment/entity/Investment.java index 57e640c4..dde99d59 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/investment/entity/Investment.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/investment/entity/Investment.java @@ -8,17 +8,13 @@ import static com.exence.finance.common.util.ValidationConstants.TRANSACTION_AMOUNT_PRECISION; import com.exence.finance.common.dto.SupportedCurrency; -import com.exence.finance.common.entity.BaseAuditableEntity; -import com.exence.finance.modules.auth.entity.User; +import com.exence.finance.common.entity.BaseWorkspaceEntity; import com.exence.finance.modules.investment.enums.InvestmentType; import jakarta.persistence.Column; import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; import jakarta.validation.constraints.DecimalMin; @@ -45,14 +41,12 @@ @AllArgsConstructor @FieldNameConstants @EqualsAndHashCode( - callSuper = false, - exclude = {"user"}) + callSuper = false) @ToString( - callSuper = true, - exclude = {"user"}) + callSuper = true) @Table(name = "investment") -@Filter(name = "userFilter", condition = "user_id = :userId") -public class Investment extends BaseAuditableEntity { +@Filter(name = "workspaceFilter", condition = "workspace_id = :workspaceId") +public class Investment extends BaseWorkspaceEntity { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "investment_id_seq") @@ -101,8 +95,4 @@ public class Investment extends BaseAuditableEntity { @Size(max = INVESTMENT_NOTE_MAX_LENGTH) @Column(name = "note", length = INVESTMENT_NOTE_MAX_LENGTH) private String note; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "user_id", nullable = false) - private User user; } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/investment/mapper/InvestmentMapper.java b/backend/exence/src/main/java/com/exence/finance/modules/investment/mapper/InvestmentMapper.java index f8632b68..3bd38ef2 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/investment/mapper/InvestmentMapper.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/investment/mapper/InvestmentMapper.java @@ -16,7 +16,7 @@ public interface InvestmentMapper { InvestmentGetDTO mapToGetDTO(Investment investment); @Mapping(target = "id", ignore = true) - @Mapping(target = "user", ignore = true) + @Mapping(target = "workspace", ignore = true) @Mapping(target = "baseCurrencyAmount", ignore = true) @Mapping(target = "createdAt", ignore = true) @Mapping(target = "updatedAt", ignore = true) @@ -25,7 +25,7 @@ public interface InvestmentMapper { Investment mapFromCreateDTO(InvestmentCreateDTO dto); @Mapping(target = "id", ignore = true) - @Mapping(target = "user", ignore = true) + @Mapping(target = "workspace", ignore = true) @Mapping(target = "currency", ignore = true) @Mapping(target = "baseCurrencyAmount", ignore = true) @Mapping(target = "createdAt", ignore = true) diff --git a/backend/exence/src/main/java/com/exence/finance/modules/investment/repository/InvestmentRepository.java b/backend/exence/src/main/java/com/exence/finance/modules/investment/repository/InvestmentRepository.java index 023d51f3..30cec59f 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/investment/repository/InvestmentRepository.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/investment/repository/InvestmentRepository.java @@ -15,11 +15,11 @@ public interface InvestmentRepository extends JpaRepository { Optional find(Long id); @Query("SELECT i FROM Investment i") - List findAllUserFiltered(); + List findAllWorkspaceFiltered(); - @Query("SELECT COALESCE(SUM(i.baseCurrencyAmount), 0) FROM Investment i WHERE i.user.id = :userId") - BigDecimal sumBaseCurrencyAmountByUserId(Long userId); + @Query("SELECT COALESCE(SUM(i.baseCurrencyAmount), 0) FROM Investment i WHERE i.workspace.id = :workspaceId") + BigDecimal sumBaseCurrencyAmountByWorkspaceId(Long workspaceId); - @Query("SELECT COUNT(DISTINCT i.asset) FROM Investment i WHERE i.user.id = :userId") - long countDistinctAssetsByUserId(Long userId); + @Query("SELECT COUNT(DISTINCT i.asset) FROM Investment i WHERE i.workspace.id = :workspaceId") + long countDistinctAssetsByWorkspaceId(Long workspaceId); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/investment/service/impl/InvestmentServiceImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/investment/service/impl/InvestmentServiceImpl.java index c1333e34..ae6c5aba 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/investment/service/impl/InvestmentServiceImpl.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/investment/service/impl/InvestmentServiceImpl.java @@ -4,7 +4,6 @@ import com.exence.finance.common.annotations.transaction.WriteTransactional; import com.exence.finance.common.exception.ErrorCode; import com.exence.finance.common.exception.ExenceException; -import com.exence.finance.modules.auth.service.UserService; import com.exence.finance.modules.exchangerate.service.ExchangeRateService; import com.exence.finance.modules.investment.dto.InvestmentCreateDTO; import com.exence.finance.modules.investment.dto.InvestmentGetDTO; @@ -14,6 +13,7 @@ import com.exence.finance.modules.investment.mapper.InvestmentMapper; import com.exence.finance.modules.investment.repository.InvestmentRepository; import com.exence.finance.modules.investment.service.InvestmentService; +import com.exence.finance.modules.workspace.service.WorkspaceMembershipService; import java.math.BigDecimal; import java.time.LocalDate; import java.time.temporal.ChronoUnit; @@ -29,14 +29,14 @@ public class InvestmentServiceImpl implements InvestmentService { private final InvestmentRepository investmentRepository; - private final UserService userService; private final ExchangeRateService exchangeRateService; private final InvestmentMapper investmentMapper; + private final WorkspaceMembershipService workspaceMembershipService; @Override @ReadTransactional public List getInvestments() { - return investmentRepository.findAllUserFiltered().stream() + return investmentRepository.findAllWorkspaceFiltered().stream() .map(investmentMapper::mapToGetDTO) .toList(); } @@ -44,7 +44,7 @@ public List getInvestments() { @Override @ReadTransactional public List getGroupedInvestments() { - List investments = investmentRepository.findAllUserFiltered(); + List investments = investmentRepository.findAllWorkspaceFiltered(); Map> grouped = investments.stream().collect(Collectors.groupingBy(Investment::getAsset)); @@ -80,7 +80,7 @@ public List getGroupedInvestments() { @WriteTransactional public InvestmentGetDTO createInvestment(InvestmentCreateDTO dto) { Investment investment = investmentMapper.mapFromCreateDTO(dto); - investment.setUser(userService.getCurrentUser()); + investment.setWorkspace(workspaceMembershipService.getWorkspaceReference()); investment.setBaseCurrencyAmount( exchangeRateService.calculateBaseCurrencyAmount(dto.amount(), dto.currency(), dto.purchaseDate())); diff --git a/backend/exence/src/main/java/com/exence/finance/modules/statistics/entity/DailyCategoryStat.java b/backend/exence/src/main/java/com/exence/finance/modules/statistics/entity/DailyCategoryStat.java index 51f5852b..8dc80900 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/statistics/entity/DailyCategoryStat.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/statistics/entity/DailyCategoryStat.java @@ -14,7 +14,7 @@ @Entity @Immutable @Table(name = "mv_daily_category_stat") -@Filter(name = "userFilter", condition = "user_id = :userId") +@Filter(name = "workspaceFilter", condition = "workspace_id = :workspaceId") @Data @NoArgsConstructor @AllArgsConstructor diff --git a/backend/exence/src/main/java/com/exence/finance/modules/statistics/entity/DailyCategoryStatId.java b/backend/exence/src/main/java/com/exence/finance/modules/statistics/entity/DailyCategoryStatId.java index 74bae76e..9a287ad0 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/statistics/entity/DailyCategoryStatId.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/statistics/entity/DailyCategoryStatId.java @@ -18,8 +18,8 @@ @AllArgsConstructor public class DailyCategoryStatId implements Serializable { - @Column(name = "user_id", nullable = false) - private Long userId; + @Column(name = "workspace_id", nullable = false) + private Long workspaceId; @Column(name = "stat_date", nullable = false) private LocalDate statDate; diff --git a/backend/exence/src/main/java/com/exence/finance/modules/statistics/entity/Widget.java b/backend/exence/src/main/java/com/exence/finance/modules/statistics/entity/Widget.java index c8885e1f..6f5f49a2 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/statistics/entity/Widget.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/statistics/entity/Widget.java @@ -1,9 +1,9 @@ package com.exence.finance.modules.statistics.entity; -import com.exence.finance.modules.auth.entity.User; import com.exence.finance.modules.statistics.dto.Timeframe; import com.exence.finance.modules.statistics.dto.WidgetSetting; import com.exence.finance.modules.statistics.dto.WidgetType; +import com.exence.finance.modules.workspace.entity.Workspace; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; @@ -31,7 +31,7 @@ @Data @NoArgsConstructor @AllArgsConstructor -@Filter(name = "userFilter", condition = "user_id = :userId") +@Filter(name = "workspaceFilter", condition = "workspace_id = :workspaceId") public class Widget { @Id @@ -71,6 +71,6 @@ public class Widget { private Map settings; @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "user_id", nullable = false) - private User user; + @JoinColumn(name = "workspace_id", nullable = false) + private Workspace workspace; } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/statistics/mapper/WidgetMapper.java b/backend/exence/src/main/java/com/exence/finance/modules/statistics/mapper/WidgetMapper.java index 1f8715d0..bf2a8099 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/statistics/mapper/WidgetMapper.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/statistics/mapper/WidgetMapper.java @@ -20,6 +20,6 @@ public interface WidgetMapper { List mapToChartDTOList(List widgets); @Mapping(target = "id", ignore = true) - @Mapping(target = "user", ignore = true) + @Mapping(target = "workspace", ignore = true) Widget mapToWidget(WidgetCreateDTO dto); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/statistics/repository/AdminStatisticsQueryService.java b/backend/exence/src/main/java/com/exence/finance/modules/statistics/repository/AdminStatisticsQueryService.java index 3fac5eb3..18811eb3 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/statistics/repository/AdminStatisticsQueryService.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/statistics/repository/AdminStatisticsQueryService.java @@ -40,7 +40,7 @@ public List findDailyActiveUsers(LocalDate start, LocalDate en return queryFactory .select(Projections.constructor( - DailyCountResult.class, activityDate, transaction.user.id.countDistinct())) + DailyCountResult.class, activityDate, transaction.createdBy.countDistinct())) .from(transaction) .where(transaction .createdAt @@ -62,7 +62,7 @@ public List findMonthlyActiveUsers(LocalDate start, LocalDat MonthlyCountResult.class, transaction.createdAt.year(), transaction.createdAt.month(), - transaction.user.id.countDistinct())) + transaction.createdBy.countDistinct())) .from(transaction) .where(transaction .createdAt @@ -169,11 +169,10 @@ public List findTransactionTypeDistribution(LocalDate start, Lo public List findTopActiveUsers(LocalDate start, LocalDate end, int limit) { return queryFactory - .select(Projections.constructor(TopUserResult.class, user.username, transaction.count())) + .select(Projections.constructor(TopUserResult.class, transaction.createdBy, transaction.count())) .from(transaction) - .join(transaction.user, user) .where(transaction.date.goe(start).and(transaction.date.loe(end))) - .groupBy(user.id, user.username) + .groupBy(transaction.createdBy) .orderBy(transaction.count().desc()) .limit(limit) .fetch(); diff --git a/backend/exence/src/main/java/com/exence/finance/modules/statistics/repository/StatisticsQueryService.java b/backend/exence/src/main/java/com/exence/finance/modules/statistics/repository/StatisticsQueryService.java index c82f0520..85a56ee8 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/statistics/repository/StatisticsQueryService.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/statistics/repository/StatisticsQueryService.java @@ -1,6 +1,5 @@ package com.exence.finance.modules.statistics.repository; -import com.exence.finance.modules.auth.service.UserService; import com.exence.finance.modules.statistics.dto.StatisticsFilter; import com.exence.finance.modules.statistics.dto.result.CategoryAmountResult; import com.exence.finance.modules.statistics.dto.result.CategoryAverageResult; @@ -20,6 +19,7 @@ import com.exence.finance.modules.statistics.entity.QDailyCategoryStat; import com.exence.finance.modules.transaction.dto.TransactionType; import com.exence.finance.modules.transaction.entity.QTransaction; +import com.exence.finance.modules.workspace.context.WorkspaceContextHolder; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.CaseBuilder; @@ -45,7 +45,6 @@ public class StatisticsQueryService { private final JPAQueryFactory queryFactory; private final JdbcClient jdbcClient; - private final UserService userService; // --- General --- @@ -94,12 +93,13 @@ public List findCumulativeDailyBalance(StatisticsFilter filter + " SUM(CASE WHEN CAST(type AS TEXT) = 'INCOME'" + " THEN total_amount ELSE -total_amount END) AS daily_balance" + " FROM mv_daily_category_stat" - + " WHERE user_id = :userId"); + + " WHERE workspace_id = :workspaceId"); appendDateFilter(sql, filter, "stat_date"); appendCategoryFilter(sql, filter, "category_id"); sql.append(" GROUP BY stat_date) daily ORDER BY daily.stat_date"); - JdbcClient.StatementSpec spec = jdbcClient.sql(sql.toString()).param("userId", userService.getCurrentUserId()); + JdbcClient.StatementSpec spec = + jdbcClient.sql(sql.toString()).param("workspaceId", WorkspaceContextHolder.getWorkspaceId()); spec = applyDateParams(spec, filter); spec = applyCategoryParams(spec, filter); @@ -374,14 +374,14 @@ public Long countNoSpendDays(StatisticsFilter filter) { + " FROM generate_series(CAST(:startDate AS date), " + endBound + "," + " '1 day'::interval) d(day)" + " LEFT JOIN mv_daily_category_stat s ON CAST(s.stat_date AS date) = d.day" - + " AND s.user_id = :userId" + + " AND s.workspace_id = :workspaceId" + " AND CAST(s.type AS TEXT) = 'EXPENSE'"); appendCategoryFilter(sql, filter, "s.category_id"); sql.append(" WHERE s.stat_date IS NULL"); JdbcClient.StatementSpec spec = jdbcClient .sql(sql.toString()) - .param("userId", userService.getCurrentUserId()) + .param("workspaceId", WorkspaceContextHolder.getWorkspaceId()) .param("startDate", toSqlDate(filter.startDate())); if (filter.endDate() != null) { spec = spec.param("endDate", toSqlDate(filter.endDate())); @@ -398,14 +398,15 @@ public List findWeeklyHeatmapExpense(StatisticsFilter filter) { + " EXTRACT(WEEK FROM stat_date)::int," + " COALESCE(SUM(total_amount), 0)" + " FROM mv_daily_category_stat" - + " WHERE user_id = :userId" + + " WHERE workspace_id = :workspaceId" + " AND CAST(type AS TEXT) = 'EXPENSE'"); appendDateFilter(sql, filter, "stat_date"); appendCategoryFilter(sql, filter, "category_id"); sql.append(" GROUP BY EXTRACT(ISODOW FROM stat_date), EXTRACT(WEEK FROM stat_date)"); sql.append(" ORDER BY 2, 1"); - JdbcClient.StatementSpec spec = jdbcClient.sql(sql.toString()).param("userId", userService.getCurrentUserId()); + JdbcClient.StatementSpec spec = + jdbcClient.sql(sql.toString()).param("workspaceId", WorkspaceContextHolder.getWorkspaceId()); spec = applyDateParams(spec, filter); spec = applyCategoryParams(spec, filter); @@ -426,7 +427,7 @@ public List findBoxplotByMonthExpense(StatisticsFilter fil + " stat_date," + " SUM(total_amount) AS daily_total" + " FROM mv_daily_category_stat" - + " WHERE user_id = :userId" + + " WHERE workspace_id = :workspaceId" + " AND CAST(type AS TEXT) = 'EXPENSE'"); appendDateFilter(sql, filter, "stat_date"); appendCategoryFilter(sql, filter, "category_id"); @@ -434,7 +435,8 @@ public List findBoxplotByMonthExpense(StatisticsFilter fil sql.append(" GROUP BY sub.yr, sub.mn"); sql.append(" ORDER BY sub.yr, sub.mn"); - JdbcClient.StatementSpec spec = jdbcClient.sql(sql.toString()).param("userId", userService.getCurrentUserId()); + JdbcClient.StatementSpec spec = + jdbcClient.sql(sql.toString()).param("workspaceId", WorkspaceContextHolder.getWorkspaceId()); spec = applyDateParams(spec, filter); spec = applyCategoryParams(spec, filter); @@ -476,14 +478,15 @@ public List findBoxplotByExpenseCategory(StatisticsFilter + " MAX(t.base_currency_amount)" + " FROM \"transaction\" t" + " JOIN category c ON t.category_id = c.id" - + " WHERE t.user_id = :userId" + + " WHERE t.workspace_id = :workspaceId" + " AND CAST(t.type AS TEXT) = 'EXPENSE'"); appendDateFilter(sql, filter, "t.date"); appendCategoryFilter(sql, filter, "t.category_id"); sql.append(" GROUP BY c.name, c.color"); sql.append(" ORDER BY c.name"); - JdbcClient.StatementSpec spec = jdbcClient.sql(sql.toString()).param("userId", userService.getCurrentUserId()); + JdbcClient.StatementSpec spec = + jdbcClient.sql(sql.toString()).param("workspaceId", WorkspaceContextHolder.getWorkspaceId()); spec = applyDateParams(spec, filter); spec = applyCategoryParams(spec, filter); diff --git a/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/impl/WidgetServiceImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/impl/WidgetServiceImpl.java index b7137b3b..5566899b 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/impl/WidgetServiceImpl.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/impl/WidgetServiceImpl.java @@ -4,7 +4,6 @@ import com.exence.finance.common.annotations.transaction.WriteTransactional; import com.exence.finance.common.exception.ErrorCode; import com.exence.finance.common.exception.ExenceException; -import com.exence.finance.modules.auth.service.UserService; import com.exence.finance.modules.statistics.dto.Timeframe; import com.exence.finance.modules.statistics.dto.UpdateLayoutRequest; import com.exence.finance.modules.statistics.dto.WidgetCreateDTO; @@ -20,6 +19,8 @@ import com.exence.finance.modules.statistics.service.WidgetService; import com.exence.finance.modules.statistics.service.WidgetSettingsValidator; import com.exence.finance.modules.statistics.service.provider.WidgetDataProvider; +import com.exence.finance.modules.workspace.context.WorkspaceContextHolder; +import com.exence.finance.modules.workspace.service.WorkspaceService; import jakarta.annotation.PostConstruct; import java.time.LocalDate; import java.util.HashMap; @@ -41,7 +42,7 @@ public class WidgetServiceImpl implements WidgetService { private final WidgetMapper widgetMapper; private final WidgetRepository widgetRepository; private final StatisticsQueryService statisticsQueryService; - private final UserService userService; + private final WorkspaceService workspaceService; private final WidgetSettingsValidator widgetSettingsValidator; private final List providers; @@ -80,7 +81,7 @@ public WidgetLayoutResponse getLayout() { public WidgetLayoutResponse createWidget(WidgetCreateDTO widgetCreateDTO) { widgetSettingsValidator.validate(widgetCreateDTO.settings()); Widget widget = widgetMapper.mapToWidget(widgetCreateDTO); - widget.setUser(userService.getCurrentUser()); + widget.setWorkspace(workspaceService.getWorkspace(WorkspaceContextHolder.getWorkspaceId())); widgetRepository.save(widget); diff --git a/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/ProviderHelper.java b/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/ProviderHelper.java index a8ec6f3d..c500944d 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/ProviderHelper.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/ProviderHelper.java @@ -3,8 +3,6 @@ import com.exence.finance.common.dto.SupportedCurrency; import com.exence.finance.common.i18n.I18nService; import com.exence.finance.common.util.DateUtils; -import com.exence.finance.modules.auth.repository.UserSettingsRepository; -import com.exence.finance.modules.auth.service.UserService; import com.exence.finance.modules.statistics.dto.Timeframe; import com.exence.finance.modules.statistics.dto.WidgetRequest; import com.exence.finance.modules.statistics.dto.payload.DataPoint; @@ -20,6 +18,8 @@ import com.exence.finance.modules.statistics.dto.result.MonthlyResult; import com.exence.finance.modules.statistics.dto.result.TypeAmountResult; import com.exence.finance.modules.transaction.dto.TransactionType; +import com.exence.finance.modules.workspace.context.WorkspaceContextHolder; +import com.exence.finance.modules.workspace.repository.WorkspaceSettingsRepository; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; @@ -41,8 +41,7 @@ public class ProviderHelper { private final I18nService i18n; - private final UserSettingsRepository userSettingsRepository; - private final UserService userService; + private final WorkspaceSettingsRepository workspaceSettingsRepository; private static final int DIVISION_SCALE = 4; private static final int PERCENTAGE_MULTIPLIER = 100; @@ -219,10 +218,10 @@ public Map toTypeAmountMap(List p } public String getUserCurrencySymbol() { - Long userId = userService.getCurrentUserId(); - SupportedCurrency currency = userSettingsRepository - .findBaseCurrencyByUserId(userId) - .orElseThrow(() -> new IllegalStateException("Settings not found for user " + userId)); + Long workspaceId = WorkspaceContextHolder.getWorkspaceId(); + SupportedCurrency currency = workspaceSettingsRepository + .findBaseCurrencyByWorkspaceId(workspaceId) + .orElseThrow(() -> new IllegalStateException("Settings not found for workspace " + workspaceId)); return i18n.getCurrencySymbol(currency); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/goal/GoalTotalSavedThisYearStatCardProvider.java b/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/goal/GoalTotalSavedThisYearStatCardProvider.java index 4ab6a60c..bb1c20ec 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/goal/GoalTotalSavedThisYearStatCardProvider.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/goal/GoalTotalSavedThisYearStatCardProvider.java @@ -52,7 +52,7 @@ public StatCardPayload getData(WidgetRequest request) { } private BigDecimal calculateTotalSaved(LocalDate startDate, LocalDate endDate) { - List allGoals = goalRepository.findAllUserFiltered(); + List allGoals = goalRepository.findAllWorkspaceFiltered(); if (allGoals.isEmpty()) { return BigDecimal.ZERO; diff --git a/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/investment/InvestmentAssetCountStatCardProvider.java b/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/investment/InvestmentAssetCountStatCardProvider.java index 9a1700d2..0ca9ba78 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/investment/InvestmentAssetCountStatCardProvider.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/investment/InvestmentAssetCountStatCardProvider.java @@ -1,10 +1,10 @@ package com.exence.finance.modules.statistics.service.provider.investment; import com.exence.finance.common.i18n.I18nService; -import com.exence.finance.modules.auth.service.UserService; import com.exence.finance.modules.investment.repository.InvestmentRepository; import com.exence.finance.modules.statistics.dto.investment.InvestmentWidgetType; import com.exence.finance.modules.statistics.dto.payload.StatCardPayload; +import com.exence.finance.modules.workspace.context.WorkspaceContextHolder; import java.math.BigDecimal; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -14,7 +14,6 @@ public final class InvestmentAssetCountStatCardProvider implements InvestmentWidgetDataProvider { private final InvestmentRepository investmentRepository; - private final UserService userService; private final I18nService i18n; @Override @@ -24,8 +23,7 @@ public InvestmentWidgetType getSupportedType() { @Override public StatCardPayload getData() { - Long userId = userService.getCurrentUserId(); - long count = investmentRepository.countDistinctAssetsByUserId(userId); + long count = investmentRepository.countDistinctAssetsByWorkspaceId(WorkspaceContextHolder.getWorkspaceId()); return new StatCardPayload( BigDecimal.valueOf(count), i18n.get("label.investment.assets"), null, null, null, null, null); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/investment/InvestmentTotalValueStatCardProvider.java b/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/investment/InvestmentTotalValueStatCardProvider.java index c502398e..4b4edd8d 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/investment/InvestmentTotalValueStatCardProvider.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/statistics/service/provider/investment/InvestmentTotalValueStatCardProvider.java @@ -1,10 +1,10 @@ package com.exence.finance.modules.statistics.service.provider.investment; -import com.exence.finance.modules.auth.service.UserService; import com.exence.finance.modules.investment.repository.InvestmentRepository; import com.exence.finance.modules.statistics.dto.investment.InvestmentWidgetType; import com.exence.finance.modules.statistics.dto.payload.StatCardPayload; import com.exence.finance.modules.statistics.service.provider.ProviderHelper; +import com.exence.finance.modules.workspace.context.WorkspaceContextHolder; import java.math.BigDecimal; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -14,7 +14,6 @@ public final class InvestmentTotalValueStatCardProvider implements InvestmentWidgetDataProvider { private final InvestmentRepository investmentRepository; - private final UserService userService; private final ProviderHelper providerHelper; @Override @@ -24,8 +23,8 @@ public InvestmentWidgetType getSupportedType() { @Override public StatCardPayload getData() { - Long userId = userService.getCurrentUserId(); - BigDecimal total = investmentRepository.sumBaseCurrencyAmountByUserId(userId); + BigDecimal total = + investmentRepository.sumBaseCurrencyAmountByWorkspaceId(WorkspaceContextHolder.getWorkspaceId()); return new StatCardPayload(total, providerHelper.getUserCurrencySymbol(), null, null, null, null, null); } } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/transaction/entity/RecurringTransaction.java b/backend/exence/src/main/java/com/exence/finance/modules/transaction/entity/RecurringTransaction.java index 5baf9933..e324ea56 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/transaction/entity/RecurringTransaction.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/transaction/entity/RecurringTransaction.java @@ -7,8 +7,7 @@ import static com.exence.finance.common.util.ValidationConstants.TRANSACTION_NOTE_MAX_LENGTH; import com.exence.finance.common.dto.SupportedCurrency; -import com.exence.finance.common.entity.BaseAuditableEntity; -import com.exence.finance.modules.auth.entity.User; +import com.exence.finance.common.entity.BaseWorkspaceEntity; import com.exence.finance.modules.category.entity.Category; import com.exence.finance.modules.transaction.dto.EndCondition; import com.exence.finance.modules.transaction.dto.RecurrenceFrequency; @@ -50,13 +49,13 @@ @FieldNameConstants @EqualsAndHashCode( callSuper = false, - exclude = {"user", "category"}) + exclude = {"category"}) @ToString( callSuper = true, - exclude = {"user", "category"}) + exclude = {"category"}) @Table(name = "recurring_transaction") -@Filter(name = "userFilter", condition = "user_id = :userId") -public class RecurringTransaction extends BaseAuditableEntity { +@Filter(name = "workspaceFilter", condition = "workspace_id = :workspaceId") +public class RecurringTransaction extends BaseWorkspaceEntity { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "recurring_transaction_id_seq") @@ -136,8 +135,4 @@ public class RecurringTransaction extends BaseAuditableEntity { @ManyToOne(fetch = FetchType.LAZY, optional = false) @JoinColumn(name = "category_id", nullable = false) private Category category; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "user_id", nullable = false) - private User user; } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/transaction/entity/Transaction.java b/backend/exence/src/main/java/com/exence/finance/modules/transaction/entity/Transaction.java index d94480e8..0b0b3992 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/transaction/entity/Transaction.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/transaction/entity/Transaction.java @@ -10,8 +10,7 @@ import static com.exence.finance.common.util.ValidationConstants.TRANSACTION_NOTE_MAX_LENGTH; import com.exence.finance.common.dto.SupportedCurrency; -import com.exence.finance.common.entity.BaseAuditableEntity; -import com.exence.finance.modules.auth.entity.User; +import com.exence.finance.common.entity.BaseWorkspaceEntity; import com.exence.finance.modules.category.entity.Category; import com.exence.finance.modules.transaction.dto.TransactionType; import jakarta.persistence.Column; @@ -48,13 +47,13 @@ @FieldNameConstants @EqualsAndHashCode( callSuper = false, - exclude = {"user", "category", "recurringTransaction"}) + exclude = {"category", "recurringTransaction"}) @ToString( callSuper = true, - exclude = {"user", "category", "recurringTransaction"}) + exclude = {"category", "recurringTransaction"}) @Table(name = "transaction") -@Filter(name = "userFilter", condition = "user_id = :userId") -public class Transaction extends BaseAuditableEntity { +@Filter(name = "workspaceFilter", condition = "workspace_id = :workspaceId") +public class Transaction extends BaseWorkspaceEntity { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "transaction_id_seq") @@ -123,8 +122,4 @@ public class Transaction extends BaseAuditableEntity { @ManyToOne(fetch = FetchType.LAZY, optional = false) @JoinColumn(name = "category_id", nullable = false) private Category category; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "user_id", nullable = false) - private User user; } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/transaction/event/TransactionCreatedEvent.java b/backend/exence/src/main/java/com/exence/finance/modules/transaction/event/TransactionCreatedEvent.java index 863c4115..353696af 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/transaction/event/TransactionCreatedEvent.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/transaction/event/TransactionCreatedEvent.java @@ -1,3 +1,3 @@ package com.exence.finance.modules.transaction.event; -public record TransactionCreatedEvent(Long userId) {} +public record TransactionCreatedEvent(Long workspaceId) {} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/transaction/mapper/RecurringTransactionMapper.java b/backend/exence/src/main/java/com/exence/finance/modules/transaction/mapper/RecurringTransactionMapper.java index 8d812f88..fe1ddd4e 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/transaction/mapper/RecurringTransactionMapper.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/transaction/mapper/RecurringTransactionMapper.java @@ -17,7 +17,7 @@ public interface RecurringTransactionMapper { RecurringTransactionGetDTO mapToGetDTO(RecurringTransaction recurringTransaction); @Mapping(target = "id", ignore = true) - @Mapping(target = "user", ignore = true) + @Mapping(target = "workspace", ignore = true) @Mapping(target = "category", ignore = true) @Mapping(target = "currency", ignore = true) @Mapping(target = "currentOccurrences", ignore = true) @@ -30,7 +30,7 @@ public interface RecurringTransactionMapper { RecurringTransaction mapToEntity(RecurringTransactionCreateDTO dto); @Mapping(target = "id", ignore = true) - @Mapping(target = "user", ignore = true) + @Mapping(target = "workspace", ignore = true) @Mapping(target = "category", ignore = true) @Mapping(target = "currency", ignore = true) @Mapping(target = "currentOccurrences", ignore = true) diff --git a/backend/exence/src/main/java/com/exence/finance/modules/transaction/mapper/TransactionMapper.java b/backend/exence/src/main/java/com/exence/finance/modules/transaction/mapper/TransactionMapper.java index 5c7f7b5a..d130613a 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/transaction/mapper/TransactionMapper.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/transaction/mapper/TransactionMapper.java @@ -18,7 +18,7 @@ public interface TransactionMapper { TransactionGetDTO mapToTransactionGetDTO(Transaction transaction); @Mapping(target = "id", ignore = true) - @Mapping(target = "user", ignore = true) + @Mapping(target = "workspace", ignore = true) @Mapping(target = "category", ignore = true) @Mapping(target = "currency", ignore = true) @Mapping(target = "exchangeRate", ignore = true) @@ -32,7 +32,7 @@ public interface TransactionMapper { Transaction mapToTransaction(TransactionCreateDTO transactionCreateDTO); @Mapping(target = "id", ignore = true) - @Mapping(target = "user", ignore = true) + @Mapping(target = "workspace", ignore = true) @Mapping(target = "category", ignore = true) @Mapping(target = "currency", ignore = true) @Mapping(target = "exchangeRate", ignore = true) diff --git a/backend/exence/src/main/java/com/exence/finance/modules/transaction/repository/RecurringTransactionRepository.java b/backend/exence/src/main/java/com/exence/finance/modules/transaction/repository/RecurringTransactionRepository.java index 12b6942f..9c0eb3be 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/transaction/repository/RecurringTransactionRepository.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/transaction/repository/RecurringTransactionRepository.java @@ -19,10 +19,10 @@ public interface RecurringTransactionRepository extends JpaRepository find(@Param("id") Long id); @Query("SELECT rt FROM RecurringTransaction rt") - Page findAllUserFiltered(Pageable pageable); + Page findAllWorkspaceFiltered(Pageable pageable); @Query("SELECT rt FROM RecurringTransaction rt WHERE rt.type = :type") - Page findAllUserFilteredByType(@Param("type") TransactionType type, Pageable pageable); + Page findAllWorkspaceFilteredByType(@Param("type") TransactionType type, Pageable pageable); @Query("SELECT rt FROM RecurringTransaction rt WHERE rt.active = true AND rt.nextExecutionDate <= :date") List findAllDue(@Param("date") LocalDate date); diff --git a/backend/exence/src/main/java/com/exence/finance/modules/transaction/repository/TransactionRepository.java b/backend/exence/src/main/java/com/exence/finance/modules/transaction/repository/TransactionRepository.java index 0b444b89..8603cd62 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/transaction/repository/TransactionRepository.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/transaction/repository/TransactionRepository.java @@ -3,6 +3,7 @@ import com.exence.finance.modules.transaction.dto.TransactionType; import com.exence.finance.modules.transaction.entity.Transaction; import java.math.BigDecimal; +import java.sql.Date; import java.time.LocalDate; import java.util.List; import java.util.Optional; @@ -23,15 +24,16 @@ public interface TransactionRepository BigDecimal sumByType(@Param("type") TransactionType type); @Query("SELECT t FROM Transaction t") - List findAllUserFiltered(); + List findAllWorkspaceFiltered(); @Query("SELECT COUNT(t) > 0 FROM Transaction t WHERE t.recurringTransaction.id = :rid AND t.date = :d") boolean existsByRecurringTransactionAndDate(@Param("rid") Long recurringTransactionId, @Param("d") LocalDate date); - // event listeners needs userId, hibernate filter does not apply - @Query("SELECT COUNT(t) FROM Transaction t WHERE t.user.id = :userId") - long countByUserId(@Param("userId") Long userId); + // achievement listeners need workspaceId, hibernate filter does not apply there + @Query("SELECT COUNT(t) FROM Transaction t WHERE t.workspace.id = :workspaceId") + long countByWorkspaceId(@Param("workspaceId") Long workspaceId); - @Query("SELECT DISTINCT t.createdAt FROM Transaction t WHERE t.user.id = :userId ORDER BY t.createdAt ASC") - List findDistinctCreatedAtByUserId(@Param("userId") Long userId); + @Query("SELECT DISTINCT CAST(t.createdAt AS date) FROM Transaction t" + + " WHERE t.workspace.id = :workspaceId ORDER BY CAST(t.createdAt AS date) ASC") + List findDistinctCreatedAtByWorkspaceId(@Param("workspaceId") Long workspaceId); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/transaction/scheduler/RecurringTransactionScheduler.java b/backend/exence/src/main/java/com/exence/finance/modules/transaction/scheduler/RecurringTransactionScheduler.java index 90a0d548..66014470 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/transaction/scheduler/RecurringTransactionScheduler.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/transaction/scheduler/RecurringTransactionScheduler.java @@ -2,7 +2,6 @@ import com.exence.finance.common.annotations.transaction.WriteTransactional; import com.exence.finance.common.dto.SupportedCurrency; -import com.exence.finance.modules.auth.repository.UserSettingsRepository; import com.exence.finance.modules.exchangerate.service.ExchangeRateService; import com.exence.finance.modules.statistics.event.MaterializedViewRefreshEvent; import com.exence.finance.modules.transaction.dto.EndCondition; @@ -11,6 +10,7 @@ import com.exence.finance.modules.transaction.repository.RecurringTransactionRepository; import com.exence.finance.modules.transaction.repository.TransactionRepository; import com.exence.finance.modules.transaction.service.impl.RecurringTransactionServiceImpl; +import com.exence.finance.modules.workspace.repository.WorkspaceSettingsRepository; import java.math.BigDecimal; import java.time.LocalDate; import java.util.List; @@ -27,7 +27,7 @@ public class RecurringTransactionScheduler { private final RecurringTransactionRepository recurringTransactionRepository; private final TransactionRepository transactionRepository; - private final UserSettingsRepository userSettingsRepository; + private final WorkspaceSettingsRepository workspaceSettingsRepository; private final ExchangeRateService exchangeRateService; private final ApplicationEventPublisher eventPublisher; @@ -78,10 +78,10 @@ public boolean processOne(RecurringTransaction rt, LocalDate executionDate) { } private Transaction buildTransaction(RecurringTransaction rt, LocalDate executionDate) { - SupportedCurrency baseCurrency = userSettingsRepository - .findBaseCurrencyByUserId(rt.getUser().getId()) + SupportedCurrency baseCurrency = workspaceSettingsRepository + .findBaseCurrencyByWorkspaceId(rt.getWorkspace().getId()) .orElseThrow(() -> new IllegalStateException( - "Settings not found for user " + rt.getUser().getId())); + "Settings not found for workspace " + rt.getWorkspace().getId())); SupportedCurrency currency = rt.getCurrency(); @@ -109,7 +109,7 @@ private Transaction buildTransaction(RecurringTransaction rt, LocalDate executio .createdByRecurringJob(true) .recurringTransaction(rt) .category(rt.getCategory()) - .user(rt.getUser()) + .workspace(rt.getWorkspace()) .build(); } diff --git a/backend/exence/src/main/java/com/exence/finance/modules/transaction/service/impl/RecurringTransactionServiceImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/transaction/service/impl/RecurringTransactionServiceImpl.java index 980dd298..f0d18ab0 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/transaction/service/impl/RecurringTransactionServiceImpl.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/transaction/service/impl/RecurringTransactionServiceImpl.java @@ -5,8 +5,6 @@ import com.exence.finance.common.dto.SupportedCurrency; import com.exence.finance.common.exception.ErrorCode; import com.exence.finance.common.exception.ExenceException; -import com.exence.finance.modules.auth.entity.User; -import com.exence.finance.modules.auth.service.UserService; import com.exence.finance.modules.auth.service.UserSettingsService; import com.exence.finance.modules.category.entity.Category; import com.exence.finance.modules.category.service.CategoryService; @@ -20,6 +18,7 @@ import com.exence.finance.modules.transaction.mapper.RecurringTransactionMapper; import com.exence.finance.modules.transaction.repository.RecurringTransactionRepository; import com.exence.finance.modules.transaction.service.RecurringTransactionService; +import com.exence.finance.modules.workspace.service.WorkspaceMembershipService; import java.time.LocalDate; import java.time.YearMonth; import lombok.RequiredArgsConstructor; @@ -33,9 +32,9 @@ public class RecurringTransactionServiceImpl implements RecurringTransactionServ private final RecurringTransactionRepository recurringTransactionRepository; private final CategoryService categoryService; - private final UserService userService; private final UserSettingsService userSettingsService; private final RecurringTransactionMapper mapper; + private final WorkspaceMembershipService workspaceMembershipService; @ReadTransactional public RecurringTransactionGetDTO getById(Long id) { @@ -49,21 +48,20 @@ public RecurringTransactionGetDTO getById(Long id) { public Page getAll(Pageable pageable, TransactionType type) { if (type != null) { return recurringTransactionRepository - .findAllUserFilteredByType(type, pageable) + .findAllWorkspaceFilteredByType(type, pageable) .map(mapper::mapToGetDTO); } - return recurringTransactionRepository.findAllUserFiltered(pageable).map(mapper::mapToGetDTO); + return recurringTransactionRepository.findAllWorkspaceFiltered(pageable).map(mapper::mapToGetDTO); } @WriteTransactional public RecurringTransactionGetDTO create(RecurringTransactionCreateDTO dto) { - User user = userService.getCurrentUser(); Category category = categoryService.getCategory(dto.categoryId()); SupportedCurrency currency = resolveCurrency(dto.currency()); RecurringTransaction entity = mapper.mapToEntity(dto); - entity.setUser(user); + entity.setWorkspace(workspaceMembershipService.getWorkspaceReference()); entity.setCategory(category); entity.setCurrency(currency); entity.setCurrentOccurrences(0); diff --git a/backend/exence/src/main/java/com/exence/finance/modules/transaction/service/impl/TransactionServiceImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/transaction/service/impl/TransactionServiceImpl.java index b92ac255..c440d9b5 100644 --- a/backend/exence/src/main/java/com/exence/finance/modules/transaction/service/impl/TransactionServiceImpl.java +++ b/backend/exence/src/main/java/com/exence/finance/modules/transaction/service/impl/TransactionServiceImpl.java @@ -5,8 +5,6 @@ import com.exence.finance.common.dto.SupportedCurrency; import com.exence.finance.common.exception.ErrorCode; import com.exence.finance.common.exception.ExenceException; -import com.exence.finance.modules.auth.entity.User; -import com.exence.finance.modules.auth.service.UserService; import com.exence.finance.modules.auth.service.UserSettingsService; import com.exence.finance.modules.category.entity.Category; import com.exence.finance.modules.category.service.CategoryService; @@ -25,6 +23,8 @@ import com.exence.finance.modules.transaction.repository.TransactionPredicateBuilder; import com.exence.finance.modules.transaction.repository.TransactionRepository; import com.exence.finance.modules.transaction.service.TransactionService; +import com.exence.finance.modules.workspace.context.WorkspaceContextHolder; +import com.exence.finance.modules.workspace.service.WorkspaceMembershipService; import com.querydsl.core.types.Predicate; import java.math.BigDecimal; import java.time.LocalDate; @@ -46,11 +46,11 @@ public class TransactionServiceImpl implements TransactionService { private final TransactionRepository transactionRepository; private final CategoryService categoryService; - private final UserService userService; private final ExchangeRateService exchangeRateService; private final TransactionMapper transactionMapper; private final ApplicationEventPublisher eventPublisher; private final UserSettingsService userSettingsService; + private final WorkspaceMembershipService workspaceMembershipService; @ReadTransactional public TransactionGetDTO getTransactionById(Long id) { @@ -76,20 +76,19 @@ public Page getTransactions(TransactionFilter filter, Pageabl @WriteTransactional public TransactionGetDTO createTransaction(TransactionCreateDTO transactionCreateDTO) { - User user = userService.getCurrentUser(); Transaction transaction = transactionMapper.mapToTransaction(transactionCreateDTO); Category category = categoryService.getCategory(transactionCreateDTO.categoryId()); transaction.setCategory(category); - transaction.setUser(user); + transaction.setWorkspace(workspaceMembershipService.getWorkspaceReference()); transaction.setCreatedByRecurringJob(false); applyCurrencyFields(transaction, transactionCreateDTO.currency(), transactionCreateDTO.exchangeRate()); Transaction savedTransaction = transactionRepository.save(transaction); eventPublisher.publishEvent(new MaterializedViewRefreshEvent()); - eventPublisher.publishEvent(new TransactionCreatedEvent(user.getId())); + eventPublisher.publishEvent(new TransactionCreatedEvent(WorkspaceContextHolder.getWorkspaceId())); return transactionMapper.mapToTransactionGetDTO(savedTransaction); } @@ -138,7 +137,7 @@ public void handleBaseCurrencyChanged(BaseCurrencyChangedEvent event) { } private void recalculateBaseCurrencyAmounts(SupportedCurrency newBaseCurrency) { - List transactions = transactionRepository.findAllUserFiltered(); + List transactions = transactionRepository.findAllWorkspaceFiltered(); LocalDate startDate = transactions.stream() .map(Transaction::getDate) @@ -166,8 +165,8 @@ private void recalculateBaseCurrencyAmounts(SupportedCurrency newBaseCurrency) { BigDecimal exchangeRate = exchangeRateService.getRate(txCurrency, newBaseCurrency, txDate, rates); - BigDecimal baseAmount = - exchangeRateService.calculateBaseCurrencyAmount(transaction.getAmount(), txCurrency, txDate, rates); + BigDecimal baseAmount = exchangeRateService.calculateBaseCurrencyAmount( + transaction.getAmount(), txCurrency, txDate, exchangeRate); transaction.setExchangeRate(exchangeRate); transaction.setBaseCurrencyAmount(baseAmount); diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/context/WorkspaceContextHolder.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/context/WorkspaceContextHolder.java new file mode 100644 index 00000000..74cd176d --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/context/WorkspaceContextHolder.java @@ -0,0 +1,25 @@ +package com.exence.finance.modules.workspace.context; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public class WorkspaceContextHolder { + + private static final ThreadLocal CONTEXT = new ThreadLocal<>(); + + public static void setWorkspaceId(Long workspaceId) { + CONTEXT.set(workspaceId); + } + + public static Long getWorkspaceId() { + return CONTEXT.get(); + } + + public static void clear() { + CONTEXT.remove(); + } + + public static boolean isSet() { + return CONTEXT.get() != null; + } +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/controller/WorkspaceController.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/controller/WorkspaceController.java new file mode 100644 index 00000000..41bc99fa --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/controller/WorkspaceController.java @@ -0,0 +1,28 @@ +package com.exence.finance.modules.workspace.controller; + +import com.exence.finance.modules.workspace.dto.WorkspaceCreateRequest; +import com.exence.finance.modules.workspace.dto.WorkspaceGetDTO; +import com.exence.finance.modules.workspace.dto.WorkspaceMemberEmailRequest; +import com.exence.finance.modules.workspace.dto.WorkspaceMemberGetDTO; +import com.exence.finance.modules.workspace.dto.WorkspaceRenameRequest; +import java.util.List; +import org.springframework.http.ResponseEntity; + +public interface WorkspaceController { + + ResponseEntity createWorkspace(WorkspaceCreateRequest request); + + ResponseEntity> getMyWorkspaces(); + + ResponseEntity renameWorkspace(Long workspaceId, WorkspaceRenameRequest request); + + ResponseEntity deleteWorkspace(Long workspaceId); + + ResponseEntity addMember(Long workspaceId, WorkspaceMemberEmailRequest request); + + ResponseEntity> getMembers(Long workspaceId); + + ResponseEntity removeSelf(Long workspaceId); + + ResponseEntity removeMemberByEmail(Long workspaceId, WorkspaceMemberEmailRequest request); +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/controller/WorkspaceSettingsController.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/controller/WorkspaceSettingsController.java new file mode 100644 index 00000000..bea84889 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/controller/WorkspaceSettingsController.java @@ -0,0 +1,12 @@ +package com.exence.finance.modules.workspace.controller; + +import com.exence.finance.modules.workspace.dto.WorkspaceSettingsGetDTO; +import com.exence.finance.modules.workspace.dto.WorkspaceSettingsPatchRequest; +import org.springframework.http.ResponseEntity; + +public interface WorkspaceSettingsController { + + ResponseEntity getWorkspaceSettings(); + + ResponseEntity updateWorkspaceSettings(WorkspaceSettingsPatchRequest request); +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/controller/impl/WorkspaceControllerImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/controller/impl/WorkspaceControllerImpl.java new file mode 100644 index 00000000..2ca3b29f --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/controller/impl/WorkspaceControllerImpl.java @@ -0,0 +1,83 @@ +package com.exence.finance.modules.workspace.controller.impl; + +import com.exence.finance.modules.workspace.controller.WorkspaceController; +import com.exence.finance.modules.workspace.dto.WorkspaceCreateRequest; +import com.exence.finance.modules.workspace.dto.WorkspaceGetDTO; +import com.exence.finance.modules.workspace.dto.WorkspaceMemberEmailRequest; +import com.exence.finance.modules.workspace.dto.WorkspaceMemberGetDTO; +import com.exence.finance.modules.workspace.dto.WorkspaceRenameRequest; +import com.exence.finance.modules.workspace.service.WorkspaceService; +import jakarta.validation.Valid; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +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("/api/workspaces") +@RequiredArgsConstructor +public class WorkspaceControllerImpl implements WorkspaceController { + + private final WorkspaceService workspaceService; + + @Override + @PostMapping + public ResponseEntity createWorkspace(@RequestBody @Valid WorkspaceCreateRequest request) { + return ResponseEntity.ok(workspaceService.createWorkspace(request)); + } + + @Override + @GetMapping + public ResponseEntity> getMyWorkspaces() { + return ResponseEntity.ok(workspaceService.getMyWorkspaces()); + } + + @Override + @PatchMapping("/{workspaceId}") + public ResponseEntity renameWorkspace( + @PathVariable Long workspaceId, @RequestBody @Valid WorkspaceRenameRequest request) { + return ResponseEntity.ok(workspaceService.renameWorkspace(workspaceId, request)); + } + + @Override + @DeleteMapping("/{workspaceId}") + public ResponseEntity deleteWorkspace(@PathVariable Long workspaceId) { + workspaceService.deleteWorkspace(workspaceId); + return ResponseEntity.noContent().build(); + } + + @Override + @PostMapping("/{workspaceId}/members") + public ResponseEntity addMember( + @PathVariable Long workspaceId, @RequestBody @Valid WorkspaceMemberEmailRequest request) { + return ResponseEntity.ok(workspaceService.addMember(workspaceId, request)); + } + + @Override + @GetMapping("/{workspaceId}/members") + public ResponseEntity> getMembers(@PathVariable Long workspaceId) { + return ResponseEntity.ok(workspaceService.getMembers(workspaceId)); + } + + @Override + @DeleteMapping("/{workspaceId}/members/me") + public ResponseEntity removeSelf(@PathVariable Long workspaceId) { + workspaceService.removeSelf(workspaceId); + return ResponseEntity.noContent().build(); + } + + @Override + @DeleteMapping("/{workspaceId}/members") + public ResponseEntity removeMemberByEmail( + @PathVariable Long workspaceId, @RequestBody @Valid WorkspaceMemberEmailRequest request) { + workspaceService.removeMemberByEmail(workspaceId, request); + return ResponseEntity.noContent().build(); + } +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/controller/impl/WorkspaceSettingsControllerImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/controller/impl/WorkspaceSettingsControllerImpl.java new file mode 100644 index 00000000..1120a1f2 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/controller/impl/WorkspaceSettingsControllerImpl.java @@ -0,0 +1,36 @@ +package com.exence.finance.modules.workspace.controller.impl; + +import com.exence.finance.common.util.ResponseFactory; +import com.exence.finance.modules.workspace.controller.WorkspaceSettingsController; +import com.exence.finance.modules.workspace.dto.WorkspaceSettingsGetDTO; +import com.exence.finance.modules.workspace.dto.WorkspaceSettingsPatchRequest; +import com.exence.finance.modules.workspace.service.WorkspaceSettingsService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/workspaces/settings") +@RequiredArgsConstructor +public class WorkspaceSettingsControllerImpl implements WorkspaceSettingsController { + + private final WorkspaceSettingsService workspaceSettingsService; + + @Override + @GetMapping + public ResponseEntity getWorkspaceSettings() { + return ResponseFactory.ok(workspaceSettingsService.getWorkspaceSettings()); + } + + @Override + @PatchMapping + public ResponseEntity updateWorkspaceSettings( + @Valid @RequestBody WorkspaceSettingsPatchRequest request) { + return ResponseFactory.ok(workspaceSettingsService.updateWorkspaceSettings(request)); + } +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceCreateRequest.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceCreateRequest.java new file mode 100644 index 00000000..59ce3955 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceCreateRequest.java @@ -0,0 +1,11 @@ +package com.exence.finance.modules.workspace.dto; + +import com.exence.finance.common.dto.SupportedCurrency; +import com.exence.finance.common.util.ValidationConstants; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; + +public record WorkspaceCreateRequest( + @NotBlank @Size(max = ValidationConstants.WORKSPACE_NAME_MAX_LENGTH) String name, + @NotNull SupportedCurrency baseCurrency) {} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceGetDTO.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceGetDTO.java new file mode 100644 index 00000000..5fffb7c7 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceGetDTO.java @@ -0,0 +1,5 @@ +package com.exence.finance.modules.workspace.dto; + +import com.exence.finance.modules.workspace.enums.WorkspaceRole; + +public record WorkspaceGetDTO(Long id, String name, WorkspaceRole role) {} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceMemberEmailRequest.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceMemberEmailRequest.java new file mode 100644 index 00000000..946ce5f9 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceMemberEmailRequest.java @@ -0,0 +1,5 @@ +package com.exence.finance.modules.workspace.dto; + +import com.exence.finance.common.annotations.ValidStrictEmail; + +public record WorkspaceMemberEmailRequest(@ValidStrictEmail String email) {} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceMemberGetDTO.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceMemberGetDTO.java new file mode 100644 index 00000000..dface8f5 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceMemberGetDTO.java @@ -0,0 +1,6 @@ +package com.exence.finance.modules.workspace.dto; + +import com.exence.finance.modules.workspace.enums.WorkspaceRole; +import java.time.Instant; + +public record WorkspaceMemberGetDTO(Long userId, String username, String email, WorkspaceRole role, Instant joinedAt) {} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceRenameRequest.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceRenameRequest.java new file mode 100644 index 00000000..e1e0d372 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceRenameRequest.java @@ -0,0 +1,8 @@ +package com.exence.finance.modules.workspace.dto; + +import com.exence.finance.common.util.ValidationConstants; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; + +public record WorkspaceRenameRequest( + @NotBlank @Size(max = ValidationConstants.WORKSPACE_NAME_MAX_LENGTH) String name) {} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceSettingsGetDTO.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceSettingsGetDTO.java new file mode 100644 index 00000000..c40366d0 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceSettingsGetDTO.java @@ -0,0 +1,5 @@ +package com.exence.finance.modules.workspace.dto; + +import com.exence.finance.common.dto.SupportedCurrency; + +public record WorkspaceSettingsGetDTO(SupportedCurrency baseCurrency, boolean showBaseCurrency) {} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceSettingsPatchRequest.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceSettingsPatchRequest.java new file mode 100644 index 00000000..4456a6b0 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/dto/WorkspaceSettingsPatchRequest.java @@ -0,0 +1,5 @@ +package com.exence.finance.modules.workspace.dto; + +import com.exence.finance.common.dto.SupportedCurrency; + +public record WorkspaceSettingsPatchRequest(SupportedCurrency baseCurrency, Boolean showBaseCurrency) {} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/entity/Workspace.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/entity/Workspace.java new file mode 100644 index 00000000..09c1444f --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/entity/Workspace.java @@ -0,0 +1,58 @@ +package com.exence.finance.modules.workspace.entity; + +import static com.exence.finance.common.util.ValidationConstants.WORKSPACE_NAME_MAX_LENGTH; + +import com.exence.finance.common.entity.BaseAuditableEntity; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.validation.constraints.NotNull; +import java.util.ArrayList; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; +import lombok.experimental.SuperBuilder; + +@SuperBuilder +@Entity +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode( + callSuper = false, + exclude = {"members", "settings"}) +@ToString( + callSuper = true, + exclude = {"members", "settings"}) +@Table(name = "workspace") +public class Workspace extends BaseAuditableEntity { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "workspace_id_seq") + @SequenceGenerator(name = "workspace_id_seq", sequenceName = "workspace_id_seq", allocationSize = 1) + @Column(name = "id") + private Long id; + + @NotNull + @Column(name = "name", nullable = false, length = WORKSPACE_NAME_MAX_LENGTH) + private String name; + + @OneToMany(mappedBy = "workspace", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + @Builder.Default + private List members = new ArrayList<>(); + + @OneToOne(mappedBy = "workspace", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + private WorkspaceSettings settings; +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/entity/WorkspaceMember.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/entity/WorkspaceMember.java new file mode 100644 index 00000000..f3e16644 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/entity/WorkspaceMember.java @@ -0,0 +1,65 @@ +package com.exence.finance.modules.workspace.entity; + +import static com.exence.finance.common.util.ValidationConstants.ROLE_MAX_LENGTH; + +import com.exence.finance.modules.auth.entity.User; +import com.exence.finance.modules.workspace.enums.WorkspaceRole; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import java.time.Instant; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +@Entity +@Table( + name = "workspace_member", + uniqueConstraints = + @UniqueConstraint( + columnNames = {"workspace_id", "user_id"}, + name = "uq_workspace_member")) +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(exclude = {"workspace", "user"}) +@ToString(exclude = {"workspace", "user"}) +public class WorkspaceMember { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "workspace_member_id_seq") + @SequenceGenerator(name = "workspace_member_id_seq", sequenceName = "workspace_member_id_seq", allocationSize = 1) + @Column(name = "id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "workspace_id", nullable = false) + private Workspace workspace; + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "user_id", nullable = false) + private User user; + + @JdbcTypeCode(SqlTypes.NAMED_ENUM) + @Column(name = "role", nullable = false, length = ROLE_MAX_LENGTH) + private WorkspaceRole role; + + @CreationTimestamp + @Column(name = "joined_at", nullable = false, updatable = false) + private Instant joinedAt; +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/entity/WorkspaceSettings.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/entity/WorkspaceSettings.java new file mode 100644 index 00000000..d643f45d --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/entity/WorkspaceSettings.java @@ -0,0 +1,55 @@ +package com.exence.finance.modules.workspace.entity; + +import com.exence.finance.common.dto.SupportedCurrency; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +@Entity +@Table(name = "workspace_settings") +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(exclude = {"workspace"}) +@ToString(exclude = {"workspace"}) +public class WorkspaceSettings { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "workspace_settings_id_seq") + @SequenceGenerator( + name = "workspace_settings_id_seq", + sequenceName = "workspace_settings_id_seq", + allocationSize = 1) + @Column(name = "id") + private Long id; + + @OneToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "workspace_id", nullable = false, unique = true) + private Workspace workspace; + + @NotNull + @JdbcTypeCode(SqlTypes.NAMED_ENUM) + @Column(name = "base_currency", nullable = false) + private SupportedCurrency baseCurrency; + + @NotNull + @Column(name = "show_base_currency", nullable = false) + private Boolean showBaseCurrency; +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/enums/WorkspaceRole.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/enums/WorkspaceRole.java new file mode 100644 index 00000000..811aa3d4 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/enums/WorkspaceRole.java @@ -0,0 +1,6 @@ +package com.exence.finance.modules.workspace.enums; + +public enum WorkspaceRole { + OWNER, + MEMBER +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/mapper/WorkspaceMapper.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/mapper/WorkspaceMapper.java new file mode 100644 index 00000000..3c141296 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/mapper/WorkspaceMapper.java @@ -0,0 +1,32 @@ +package com.exence.finance.modules.workspace.mapper; + +import com.exence.finance.modules.workspace.dto.WorkspaceGetDTO; +import com.exence.finance.modules.workspace.dto.WorkspaceMemberGetDTO; +import com.exence.finance.modules.workspace.entity.Workspace; +import com.exence.finance.modules.workspace.entity.WorkspaceMember; +import com.exence.finance.modules.workspace.enums.WorkspaceRole; +import org.mapstruct.Context; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Named; + +@Mapper(componentModel = "spring") +public interface WorkspaceMapper { + + @Mapping(target = "role", source = "workspace", qualifiedByName = "resolveRole") + WorkspaceGetDTO mapToGetDTO(Workspace workspace, @Context Long currentUserId); + + @Mapping(target = "userId", source = "member.user.id") + @Mapping(target = "username", source = "member.user.username") + @Mapping(target = "email", source = "member.user.email") + WorkspaceMemberGetDTO mapMemberToGetDTO(WorkspaceMember member); + + @Named("resolveRole") + default WorkspaceRole resolveRole(Workspace workspace, @Context Long userId) { + return workspace.getMembers().stream() + .filter(m -> m.getUser().getId().equals(userId)) + .map(WorkspaceMember::getRole) + .findFirst() + .orElse(null); + } +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/mapper/WorkspaceSettingsMapper.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/mapper/WorkspaceSettingsMapper.java new file mode 100644 index 00000000..314fafa7 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/mapper/WorkspaceSettingsMapper.java @@ -0,0 +1,21 @@ +package com.exence.finance.modules.workspace.mapper; + +import com.exence.finance.modules.workspace.dto.WorkspaceSettingsGetDTO; +import com.exence.finance.modules.workspace.dto.WorkspaceSettingsPatchRequest; +import com.exence.finance.modules.workspace.entity.WorkspaceSettings; +import org.mapstruct.BeanMapping; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.NullValuePropertyMappingStrategy; + +@Mapper(componentModel = "spring") +public interface WorkspaceSettingsMapper { + + WorkspaceSettingsGetDTO toGetDTO(WorkspaceSettings entity); + + @Mapping(target = "id", ignore = true) + @Mapping(target = "workspace", ignore = true) + @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) + void updateFromRequest(WorkspaceSettingsPatchRequest request, @MappingTarget WorkspaceSettings entity); +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/repository/WorkspaceMemberRepository.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/repository/WorkspaceMemberRepository.java new file mode 100644 index 00000000..9e6d62a5 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/repository/WorkspaceMemberRepository.java @@ -0,0 +1,30 @@ +package com.exence.finance.modules.workspace.repository; + +import com.exence.finance.modules.workspace.entity.WorkspaceMember; +import java.util.List; +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +@Repository +public interface WorkspaceMemberRepository extends JpaRepository { + + Optional findByWorkspaceIdAndUserId(Long workspaceId, Long userId); + + @Query("SELECT COUNT(wm) FROM WorkspaceMember wm WHERE wm.user.id = :userId") + long countByUserId(@Param("userId") Long userId); + + boolean existsByWorkspaceIdAndUserId(Long workspaceId, Long userId); + + @Query( + """ + SELECT wm FROM WorkspaceMember wm + WHERE wm.workspace.id = :workspaceId AND wm.user.email = :email + """) + Optional findByWorkspaceIdAndUserEmail( + @Param("workspaceId") Long workspaceId, @Param("email") String email); + + List findAllByWorkspaceId(Long workspaceId); +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/repository/WorkspaceRepository.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/repository/WorkspaceRepository.java new file mode 100644 index 00000000..45299216 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/repository/WorkspaceRepository.java @@ -0,0 +1,15 @@ +package com.exence.finance.modules.workspace.repository; + +import com.exence.finance.modules.workspace.entity.Workspace; +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +@Repository +public interface WorkspaceRepository extends JpaRepository { + + @Query("SELECT w FROM Workspace w JOIN w.members m WHERE m.user.id = :userId") + List findAllByUserId(@Param("userId") Long userId); +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/repository/WorkspaceSettingsRepository.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/repository/WorkspaceSettingsRepository.java new file mode 100644 index 00000000..27f01810 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/repository/WorkspaceSettingsRepository.java @@ -0,0 +1,18 @@ +package com.exence.finance.modules.workspace.repository; + +import com.exence.finance.common.dto.SupportedCurrency; +import com.exence.finance.modules.workspace.entity.WorkspaceSettings; +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +@Repository +public interface WorkspaceSettingsRepository extends JpaRepository { + + Optional findByWorkspaceId(Long workspaceId); + + @Query("SELECT ws.baseCurrency FROM WorkspaceSettings ws WHERE ws.workspace.id = :workspaceId") + Optional findBaseCurrencyByWorkspaceId(@Param("workspaceId") Long workspaceId); +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/WorkspaceMembershipService.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/WorkspaceMembershipService.java new file mode 100644 index 00000000..9b0633ff --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/WorkspaceMembershipService.java @@ -0,0 +1,43 @@ +package com.exence.finance.modules.workspace.service; + +import com.exence.finance.common.dto.SupportedCurrency; +import com.exence.finance.modules.auth.entity.User; +import com.exence.finance.modules.workspace.entity.Workspace; +import com.exence.finance.modules.workspace.entity.WorkspaceMember; +import com.exence.finance.modules.workspace.enums.WorkspaceRole; +import java.util.List; + +public interface WorkspaceMembershipService { + + /** + * Validates that the given user is a member of the given workspace. + * Throws WORKSPACE_NOT_FOUND (403) if not a member. Result is cached. + */ + void validateMembership(Long userId, Long workspaceId); + + /** + * Creates a new workspace with the given name, assigns the user as OWNER, + * and creates default WorkspaceSettings with the given base currency. + */ + Workspace createDefaultWorkspace(User user, String workspaceName, SupportedCurrency baseCurrency); + + WorkspaceMember getWorkspaceMember(Long workspaceId, Long userId); + + WorkspaceMember getWorkspaceMemberByEmail(Long workspaceId, String email); + + boolean hasMemberByEmail(Long workspaceId, String email); + + long countMembershipsByUserId(Long userId); + + List getWorkspaceMembers(Long workspaceId); + + WorkspaceMember addMember(Workspace workspace, User user, WorkspaceRole role); + + void removeMember(WorkspaceMember member); + + /** + * Returns a JPA proxy reference for the current workspace (no DB hit). + * Throws WORKSPACE_HEADER_MISSING if no workspace is set in context. + */ + Workspace getWorkspaceReference(); +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/WorkspaceService.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/WorkspaceService.java new file mode 100644 index 00000000..dd435e29 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/WorkspaceService.java @@ -0,0 +1,30 @@ +package com.exence.finance.modules.workspace.service; + +import com.exence.finance.modules.workspace.dto.WorkspaceCreateRequest; +import com.exence.finance.modules.workspace.dto.WorkspaceGetDTO; +import com.exence.finance.modules.workspace.dto.WorkspaceMemberEmailRequest; +import com.exence.finance.modules.workspace.dto.WorkspaceMemberGetDTO; +import com.exence.finance.modules.workspace.dto.WorkspaceRenameRequest; +import com.exence.finance.modules.workspace.entity.Workspace; +import java.util.List; + +public interface WorkspaceService { + + Workspace getWorkspace(Long workspaceId); + + WorkspaceGetDTO createWorkspace(WorkspaceCreateRequest request); + + List getMyWorkspaces(); + + WorkspaceGetDTO renameWorkspace(Long workspaceId, WorkspaceRenameRequest request); + + void deleteWorkspace(Long workspaceId); + + WorkspaceMemberGetDTO addMember(Long workspaceId, WorkspaceMemberEmailRequest request); + + List getMembers(Long workspaceId); + + void removeSelf(Long workspaceId); + + void removeMemberByEmail(Long workspaceId, WorkspaceMemberEmailRequest request); +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/WorkspaceSettingsService.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/WorkspaceSettingsService.java new file mode 100644 index 00000000..7172f816 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/WorkspaceSettingsService.java @@ -0,0 +1,11 @@ +package com.exence.finance.modules.workspace.service; + +import com.exence.finance.modules.workspace.dto.WorkspaceSettingsGetDTO; +import com.exence.finance.modules.workspace.dto.WorkspaceSettingsPatchRequest; + +public interface WorkspaceSettingsService { + + WorkspaceSettingsGetDTO getWorkspaceSettings(); + + WorkspaceSettingsGetDTO updateWorkspaceSettings(WorkspaceSettingsPatchRequest request); +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/impl/WorkspaceMembershipServiceImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/impl/WorkspaceMembershipServiceImpl.java new file mode 100644 index 00000000..e25cfd60 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/impl/WorkspaceMembershipServiceImpl.java @@ -0,0 +1,122 @@ +package com.exence.finance.modules.workspace.service.impl; + +import com.exence.finance.common.annotations.transaction.WriteTransactional; +import com.exence.finance.common.dto.SupportedCurrency; +import com.exence.finance.common.exception.ErrorCode; +import com.exence.finance.common.exception.ExenceException; +import com.exence.finance.modules.auth.entity.User; +import com.exence.finance.modules.workspace.context.WorkspaceContextHolder; +import com.exence.finance.modules.workspace.entity.Workspace; +import com.exence.finance.modules.workspace.entity.WorkspaceMember; +import com.exence.finance.modules.workspace.entity.WorkspaceSettings; +import com.exence.finance.modules.workspace.enums.WorkspaceRole; +import com.exence.finance.modules.workspace.repository.WorkspaceMemberRepository; +import com.exence.finance.modules.workspace.repository.WorkspaceRepository; +import com.exence.finance.modules.workspace.repository.WorkspaceSettingsRepository; +import com.exence.finance.modules.workspace.service.WorkspaceMembershipService; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class WorkspaceMembershipServiceImpl implements WorkspaceMembershipService { + + private final WorkspaceRepository workspaceRepository; + private final WorkspaceMemberRepository workspaceMemberRepository; + private final WorkspaceSettingsRepository workspaceSettingsRepository; + + @PersistenceContext + private EntityManager entityManager; + + @Override + @Cacheable(value = "workspaceMembership", key = "#userId + ':' + #workspaceId") + public void validateMembership(Long userId, Long workspaceId) { + if (!workspaceMemberRepository.existsByWorkspaceIdAndUserId(workspaceId, userId)) { + throw new ExenceException(ErrorCode.WORKSPACE_NOT_FOUND); + } + } + + @Override + @WriteTransactional + public Workspace createDefaultWorkspace(User user, String workspaceName, SupportedCurrency baseCurrency) { + Workspace workspace = Workspace.builder().name(workspaceName).build(); + workspace = workspaceRepository.save(workspace); + + WorkspaceMember owner = WorkspaceMember.builder() + .workspace(workspace) + .user(user) + .role(WorkspaceRole.OWNER) + .build(); + workspaceMemberRepository.save(owner); + workspace.setMembers(List.of(owner)); + + WorkspaceSettings settings = WorkspaceSettings.builder() + .workspace(workspace) + .baseCurrency(baseCurrency) + .showBaseCurrency(false) + .build(); + workspaceSettingsRepository.save(settings); + workspace.setSettings(settings); + + return workspace; + } + + @Override + public WorkspaceMember getWorkspaceMember(Long workspaceId, Long userId) { + return workspaceMemberRepository + .findByWorkspaceIdAndUserId(workspaceId, userId) + .orElseThrow(() -> new ExenceException(ErrorCode.WORKSPACE_NOT_FOUND)); + } + + @Override + public WorkspaceMember getWorkspaceMemberByEmail(Long workspaceId, String email) { + return workspaceMemberRepository + .findByWorkspaceIdAndUserEmail(workspaceId, email) + .orElseThrow(() -> new ExenceException(ErrorCode.WORKSPACE_NOT_FOUND)); + } + + @Override + public boolean hasMemberByEmail(Long workspaceId, String email) { + return workspaceMemberRepository + .findByWorkspaceIdAndUserEmail(workspaceId, email) + .isPresent(); + } + + @Override + public long countMembershipsByUserId(Long userId) { + return workspaceMemberRepository.countByUserId(userId); + } + + @Override + public List getWorkspaceMembers(Long workspaceId) { + return workspaceMemberRepository.findAllByWorkspaceId(workspaceId); + } + + @Override + public WorkspaceMember addMember(Workspace workspace, User user, WorkspaceRole role) { + WorkspaceMember member = WorkspaceMember.builder() + .workspace(workspace) + .user(user) + .role(role) + .build(); + return workspaceMemberRepository.save(member); + } + + @Override + public void removeMember(WorkspaceMember member) { + workspaceMemberRepository.delete(member); + } + + @Override + public Workspace getWorkspaceReference() { + Long workspaceId = WorkspaceContextHolder.getWorkspaceId(); + if (workspaceId == null) { + throw new ExenceException(ErrorCode.WORKSPACE_HEADER_MISSING); + } + return entityManager.getReference(Workspace.class, workspaceId); + } +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/impl/WorkspaceServiceImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/impl/WorkspaceServiceImpl.java new file mode 100644 index 00000000..fa7b40f9 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/impl/WorkspaceServiceImpl.java @@ -0,0 +1,132 @@ +package com.exence.finance.modules.workspace.service.impl; + +import com.exence.finance.common.annotations.transaction.ReadTransactional; +import com.exence.finance.common.annotations.transaction.WriteTransactional; +import com.exence.finance.common.exception.ErrorCode; +import com.exence.finance.common.exception.ExenceException; +import com.exence.finance.modules.auth.entity.User; +import com.exence.finance.modules.auth.service.UserService; +import com.exence.finance.modules.workspace.dto.WorkspaceCreateRequest; +import com.exence.finance.modules.workspace.dto.WorkspaceGetDTO; +import com.exence.finance.modules.workspace.dto.WorkspaceMemberEmailRequest; +import com.exence.finance.modules.workspace.dto.WorkspaceMemberGetDTO; +import com.exence.finance.modules.workspace.dto.WorkspaceRenameRequest; +import com.exence.finance.modules.workspace.entity.Workspace; +import com.exence.finance.modules.workspace.entity.WorkspaceMember; +import com.exence.finance.modules.workspace.enums.WorkspaceRole; +import com.exence.finance.modules.workspace.mapper.WorkspaceMapper; +import com.exence.finance.modules.workspace.repository.WorkspaceRepository; +import com.exence.finance.modules.workspace.service.WorkspaceMembershipService; +import com.exence.finance.modules.workspace.service.WorkspaceService; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class WorkspaceServiceImpl implements WorkspaceService { + + private final WorkspaceRepository workspaceRepository; + private final WorkspaceMembershipService workspaceMembershipService; + private final WorkspaceMapper workspaceMapper; + private final UserService userService; + + @Override + @ReadTransactional + public Workspace getWorkspace(Long workspaceId) { + return workspaceRepository + .findById(workspaceId) + .orElseThrow(() -> new ExenceException(ErrorCode.WORKSPACE_NOT_FOUND)); + } + + @Override + @WriteTransactional + public WorkspaceGetDTO createWorkspace(WorkspaceCreateRequest request) { + User currentUser = userService.getCurrentUser(); + Workspace workspace = + workspaceMembershipService.createDefaultWorkspace(currentUser, request.name(), request.baseCurrency()); + return workspaceMapper.mapToGetDTO(workspace, currentUser.getId()); + } + + @Override + @ReadTransactional + public List getMyWorkspaces() { + Long userId = userService.getCurrentUserId(); + return workspaceRepository.findAllByUserId(userId).stream() + .map(w -> workspaceMapper.mapToGetDTO(w, userId)) + .toList(); + } + + @Override + @WriteTransactional + public WorkspaceGetDTO renameWorkspace(Long workspaceId, WorkspaceRenameRequest request) { + Workspace workspace = getWorkspace(workspaceId); + workspace.setName(request.name()); + workspace = workspaceRepository.save(workspace); + return workspaceMapper.mapToGetDTO(workspace, userService.getCurrentUserId()); + } + + @Override + @WriteTransactional + @CacheEvict(value = "workspaceMembership", allEntries = true) + public void deleteWorkspace(Long workspaceId) { + Long userId = userService.getCurrentUserId(); + WorkspaceMember member = workspaceMembershipService.getWorkspaceMember(workspaceId, userId); + + if (workspaceMembershipService.countMembershipsByUserId(userId) <= 1) { + throw new ExenceException(ErrorCode.WORKSPACE_CANNOT_DELETE_LAST); + } + + workspaceRepository.delete(member.getWorkspace()); + } + + @Override + @WriteTransactional + public WorkspaceMemberGetDTO addMember(Long workspaceId, WorkspaceMemberEmailRequest request) { + Workspace workspace = getWorkspace(workspaceId); + + if (workspaceMembershipService.hasMemberByEmail(workspaceId, request.email())) { + throw new ExenceException(ErrorCode.WORKSPACE_MEMBER_ALREADY_EXISTS); + } + + User newMemberUser = userService.getUserByEmail(request.email()); + + WorkspaceMember member = workspaceMembershipService.addMember(workspace, newMemberUser, WorkspaceRole.MEMBER); + return workspaceMapper.mapMemberToGetDTO(member); + } + + @Override + @ReadTransactional + public List getMembers(Long workspaceId) { + return workspaceMembershipService.getWorkspaceMembers(workspaceId).stream() + .map(workspaceMapper::mapMemberToGetDTO) + .toList(); + } + + @Override + @WriteTransactional + @CacheEvict(value = "workspaceMembership", key = "@userServiceImpl.getCurrentUserId() + ':' + #workspaceId") + public void removeSelf(Long workspaceId) { + Long userId = userService.getCurrentUserId(); + WorkspaceMember member = workspaceMembershipService.getWorkspaceMember(workspaceId, userId); + + if (member.getRole() == WorkspaceRole.OWNER) { + throw new ExenceException(ErrorCode.WORKSPACE_OWNER_CANNOT_LEAVE); + } + + workspaceMembershipService.removeMember(member); + } + + @Override + @WriteTransactional + public void removeMemberByEmail(Long workspaceId, WorkspaceMemberEmailRequest request) { + WorkspaceMember member = workspaceMembershipService.getWorkspaceMemberByEmail(workspaceId, request.email()); + + if (member.getRole() == WorkspaceRole.OWNER) { + throw new ExenceException(ErrorCode.WORKSPACE_OWNER_CANNOT_BE_REMOVED); + } + + workspaceMembershipService.removeMember(member); + } +} diff --git a/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/impl/WorkspaceSettingsServiceImpl.java b/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/impl/WorkspaceSettingsServiceImpl.java new file mode 100644 index 00000000..2c1d44bf --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/modules/workspace/service/impl/WorkspaceSettingsServiceImpl.java @@ -0,0 +1,75 @@ +package com.exence.finance.modules.workspace.service.impl; + +import com.exence.finance.common.annotations.transaction.ReadTransactional; +import com.exence.finance.common.annotations.transaction.WriteTransactional; +import com.exence.finance.common.dto.SupportedCurrency; +import com.exence.finance.common.exception.ErrorCode; +import com.exence.finance.common.exception.ExenceException; +import com.exence.finance.modules.auth.service.UserService; +import com.exence.finance.modules.transaction.event.BaseCurrencyChangedEvent; +import com.exence.finance.modules.workspace.context.WorkspaceContextHolder; +import com.exence.finance.modules.workspace.dto.WorkspaceSettingsGetDTO; +import com.exence.finance.modules.workspace.dto.WorkspaceSettingsPatchRequest; +import com.exence.finance.modules.workspace.entity.WorkspaceMember; +import com.exence.finance.modules.workspace.entity.WorkspaceSettings; +import com.exence.finance.modules.workspace.enums.WorkspaceRole; +import com.exence.finance.modules.workspace.mapper.WorkspaceSettingsMapper; +import com.exence.finance.modules.workspace.repository.WorkspaceSettingsRepository; +import com.exence.finance.modules.workspace.service.WorkspaceMembershipService; +import com.exence.finance.modules.workspace.service.WorkspaceSettingsService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class WorkspaceSettingsServiceImpl implements WorkspaceSettingsService { + + private final WorkspaceSettingsRepository workspaceSettingsRepository; + private final WorkspaceSettingsMapper workspaceSettingsMapper; + private final WorkspaceMembershipService workspaceMembershipService; + private final UserService userService; + private final ApplicationEventPublisher eventPublisher; + + @Override + @ReadTransactional + public WorkspaceSettingsGetDTO getWorkspaceSettings() { + return workspaceSettingsMapper.toGetDTO(getCurrentSettings()); + } + + @Override + @WriteTransactional + public WorkspaceSettingsGetDTO updateWorkspaceSettings(WorkspaceSettingsPatchRequest request) { + Long workspaceId = WorkspaceContextHolder.getWorkspaceId(); + Long userId = userService.getCurrentUserId(); + WorkspaceMember member = workspaceMembershipService.getWorkspaceMember(workspaceId, userId); + + if (member.getRole() != WorkspaceRole.OWNER) { + throw new ExenceException(ErrorCode.WORKSPACE_OWNER_REQUIRED); + } + + WorkspaceSettings settings = getCurrentSettings(); + + SupportedCurrency oldBaseCurrency = settings.getBaseCurrency(); + SupportedCurrency newBaseCurrency = request.baseCurrency(); + + if (newBaseCurrency != null && newBaseCurrency != oldBaseCurrency) { + log.info("Base currency changed from {} to {} for user {}", oldBaseCurrency, newBaseCurrency, userId); + // publish event instead of circular transactionService dependency + eventPublisher.publishEvent(new BaseCurrencyChangedEvent(newBaseCurrency)); + } + + workspaceSettingsMapper.updateFromRequest(request, settings); + settings = workspaceSettingsRepository.save(settings); + return workspaceSettingsMapper.toGetDTO(settings); + } + + private WorkspaceSettings getCurrentSettings() { + Long workspaceId = WorkspaceContextHolder.getWorkspaceId(); + return workspaceSettingsRepository + .findByWorkspaceId(workspaceId) + .orElseThrow(() -> new IllegalStateException("Settings not found for workspace " + workspaceId)); + } +} diff --git a/backend/exence/src/main/java/com/exence/finance/package-info.java b/backend/exence/src/main/java/com/exence/finance/package-info.java index 4a8e1364..81de9e52 100644 --- a/backend/exence/src/main/java/com/exence/finance/package-info.java +++ b/backend/exence/src/main/java/com/exence/finance/package-info.java @@ -1,4 +1,4 @@ -@FilterDef(name = "userFilter", parameters = @ParamDef(name = "userId", type = Long.class)) +@FilterDef(name = "workspaceFilter", parameters = @ParamDef(name = "workspaceId", type = Long.class)) package com.exence.finance; import org.hibernate.annotations.FilterDef; diff --git a/backend/exence/src/main/java/com/exence/finance/security/WorkspaceInterceptor.java b/backend/exence/src/main/java/com/exence/finance/security/WorkspaceInterceptor.java new file mode 100644 index 00000000..524fe9d4 --- /dev/null +++ b/backend/exence/src/main/java/com/exence/finance/security/WorkspaceInterceptor.java @@ -0,0 +1,58 @@ +package com.exence.finance.security; + +import com.exence.finance.common.exception.ErrorCode; +import com.exence.finance.common.exception.ExenceException; +import com.exence.finance.modules.auth.service.UserService; +import com.exence.finance.modules.workspace.context.WorkspaceContextHolder; +import com.exence.finance.modules.workspace.service.WorkspaceMembershipService; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +@Component +@RequiredArgsConstructor +public class WorkspaceInterceptor implements HandlerInterceptor { + + private static final String WORKSPACE_ID_HEADER = "X-Workspace-ID"; + + private final WorkspaceMembershipService workspaceMembershipService; + private final UserService userService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + String uri = request.getRequestURI(); + String method = request.getMethod(); + + // Bare workspace collection endpoints do not require a workspace context + if ("/api/workspaces".equals(uri) && ("GET".equals(method) || "POST".equals(method))) { + return true; + } + + String headerValue = request.getHeader(WORKSPACE_ID_HEADER); + if (headerValue == null) { + throw new ExenceException(ErrorCode.WORKSPACE_HEADER_MISSING); + } + + Long workspaceId; + try { + workspaceId = Long.parseLong(headerValue); + } catch (NumberFormatException e) { + throw new ExenceException(ErrorCode.WORKSPACE_HEADER_MISSING); + } + + Long userId = userService.getCurrentUserId(); + workspaceMembershipService.validateMembership(userId, workspaceId); + WorkspaceContextHolder.setWorkspaceId(workspaceId); + + return true; + } + + @Override + public void afterCompletion( + HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { + WorkspaceContextHolder.clear(); + } +} diff --git a/backend/exence/src/main/resources/db/changelog/data/test-data.yaml b/backend/exence/src/main/resources/db/changelog/data/test-data.yaml index 1f9fd4bc..355d27b1 100644 --- a/backend/exence/src/main/resources/db/changelog/data/test-data.yaml +++ b/backend/exence/src/main/resources/db/changelog/data/test-data.yaml @@ -87,6 +87,36 @@ databaseChangeLog: name: role value: ADMIN + # Workspace + - insert: + tableName: workspace + columns: + - column: { name: id, valueNumeric: 1 } + - column: { name: name, value: "Winston's Workspace" } + - column: { name: created_at, valueComputed: "${now}" } + - column: { name: updated_at, valueComputed: "${now}" } + - column: { name: created_by, value: 'captainwinnie@exence.com' } + - column: { name: updated_by, value: 'captainwinnie@exence.com' } + + # Workspace Member + - insert: + tableName: workspace_member + columns: + - column: { name: id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } + - column: { name: user_id, valueNumeric: 1 } + - column: { name: role, value: 'OWNER' } + - column: { name: joined_at, valueComputed: "${now}" } + + # Workspace Settings + - insert: + tableName: workspace_settings + columns: + - column: { name: id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } + - column: { name: base_currency, value: 'HUF' } + - column: { name: show_base_currency, valueBoolean: false } + # Categories # EXPENSE Categories - insert: @@ -111,7 +141,7 @@ databaseChangeLog: name: note value: Food and household items - column: - name: user_id + name: workspace_id valueNumeric: 1 - column: name: created_at @@ -142,7 +172,7 @@ databaseChangeLog: name: note value: Monthly housing costs - column: - name: user_id + name: workspace_id valueNumeric: 1 - column: name: created_at @@ -173,7 +203,7 @@ databaseChangeLog: name: note value: Gas, public transport, car maintenance - column: - name: user_id + name: workspace_id valueNumeric: 1 - column: name: created_at @@ -204,7 +234,7 @@ databaseChangeLog: name: note value: Electricity, water, internet - column: - name: user_id + name: workspace_id valueNumeric: 1 - column: name: created_at @@ -235,7 +265,7 @@ databaseChangeLog: name: note value: Restaurants, cafes, takeout - column: - name: user_id + name: workspace_id valueNumeric: 1 - column: name: created_at @@ -266,7 +296,7 @@ databaseChangeLog: name: note value: Movies, games, hobbies - column: - name: user_id + name: workspace_id valueNumeric: 1 - column: name: created_at @@ -297,7 +327,7 @@ databaseChangeLog: name: note value: Medical, dental, pharmacy - column: - name: user_id + name: workspace_id valueNumeric: 1 - column: name: created_at @@ -328,7 +358,7 @@ databaseChangeLog: name: note value: Clothing, electronics, personal items - column: - name: user_id + name: workspace_id valueNumeric: 1 - column: name: created_at @@ -360,7 +390,7 @@ databaseChangeLog: name: note value: Monthly salary - column: - name: user_id + name: workspace_id valueNumeric: 1 - column: name: created_at @@ -391,7 +421,7 @@ databaseChangeLog: name: note value: Freelance projects and side gigs - column: - name: user_id + name: workspace_id valueNumeric: 1 - column: name: created_at @@ -422,7 +452,7 @@ databaseChangeLog: name: note value: Dividends, interest, capital gains - column: - name: user_id + name: workspace_id valueNumeric: 1 - column: name: created_at @@ -454,7 +484,7 @@ databaseChangeLog: name: note value: Money transfers between accounts - column: - name: user_id + name: workspace_id valueNumeric: 1 - column: name: created_at @@ -485,7 +515,7 @@ databaseChangeLog: name: note value: Gifts given and received - column: - name: user_id + name: workspace_id valueNumeric: 1 - column: name: created_at @@ -505,7 +535,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -522,7 +552,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -539,7 +569,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -556,7 +586,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -573,7 +603,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -590,7 +620,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -607,7 +637,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -624,7 +654,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -641,7 +671,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -658,7 +688,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -675,7 +705,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -692,7 +722,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -709,7 +739,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -726,7 +756,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -743,7 +773,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -760,7 +790,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -777,7 +807,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -794,7 +824,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -812,7 +842,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -829,7 +859,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -846,7 +876,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -863,7 +893,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -880,7 +910,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -897,7 +927,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -914,7 +944,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -931,7 +961,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -948,7 +978,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -965,7 +995,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -982,7 +1012,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -999,7 +1029,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1016,7 +1046,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1033,7 +1063,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1050,7 +1080,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1067,7 +1097,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1084,7 +1114,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1101,7 +1131,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1118,7 +1148,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1134,7 +1164,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1150,7 +1180,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1166,7 +1196,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1182,7 +1212,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1198,7 +1228,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1214,7 +1244,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1230,7 +1260,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1246,7 +1276,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1262,7 +1292,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 10 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1278,7 +1308,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1294,7 +1324,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1310,7 +1340,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1326,7 +1356,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1342,7 +1372,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1358,7 +1388,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1374,7 +1404,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 7 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1390,7 +1420,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1406,7 +1436,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1422,7 +1452,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1438,7 +1468,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1454,7 +1484,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1470,7 +1500,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1486,7 +1516,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1502,7 +1532,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1518,7 +1548,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1534,7 +1564,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1550,7 +1580,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1566,7 +1596,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1582,7 +1612,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1598,7 +1628,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1614,7 +1644,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1630,7 +1660,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1646,7 +1676,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1662,7 +1692,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1678,7 +1708,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1694,7 +1724,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1710,7 +1740,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1726,7 +1756,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1742,7 +1772,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1758,7 +1788,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1774,7 +1804,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1790,7 +1820,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1806,7 +1836,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1822,7 +1852,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 13 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1838,7 +1868,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1854,7 +1884,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1870,7 +1900,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1886,7 +1916,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1902,7 +1932,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1919,7 +1949,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 10 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1935,7 +1965,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1951,7 +1981,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1967,7 +1997,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1983,7 +2013,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -1999,7 +2029,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 7 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2015,7 +2045,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2031,7 +2061,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2047,7 +2077,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2063,7 +2093,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2079,7 +2109,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2095,7 +2125,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2111,7 +2141,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2127,7 +2157,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 10 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2143,7 +2173,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2159,7 +2189,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2175,7 +2205,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2191,7 +2221,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2207,7 +2237,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2223,7 +2253,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2239,7 +2269,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2255,7 +2285,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2271,7 +2301,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2287,7 +2317,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2303,7 +2333,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2319,7 +2349,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2335,7 +2365,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2351,7 +2381,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2367,7 +2397,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2383,7 +2413,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2399,7 +2429,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2415,7 +2445,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2431,7 +2461,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2447,7 +2477,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2463,7 +2493,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2479,7 +2509,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2495,7 +2525,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2511,7 +2541,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2527,7 +2557,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2543,7 +2573,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2559,7 +2589,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2575,7 +2605,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2591,7 +2621,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2607,7 +2637,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2623,7 +2653,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2639,7 +2669,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 7 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2655,7 +2685,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2671,7 +2701,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2687,7 +2717,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2703,7 +2733,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2720,7 +2750,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2736,7 +2766,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2752,7 +2782,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2768,7 +2798,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2784,7 +2814,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2800,7 +2830,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2816,7 +2846,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2832,7 +2862,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2848,7 +2878,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2864,7 +2894,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2880,7 +2910,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2896,7 +2926,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2912,7 +2942,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2928,7 +2958,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2944,7 +2974,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2961,7 +2991,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2977,7 +3007,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -2993,7 +3023,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 7 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3009,7 +3039,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3025,7 +3055,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3041,7 +3071,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3057,7 +3087,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3073,7 +3103,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3089,7 +3119,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3105,7 +3135,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3121,7 +3151,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3137,7 +3167,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3153,7 +3183,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3169,7 +3199,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3185,7 +3215,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3201,7 +3231,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3217,7 +3247,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3233,7 +3263,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 10 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3249,7 +3279,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3265,7 +3295,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3281,7 +3311,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3297,7 +3327,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3313,7 +3343,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3329,7 +3359,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3345,7 +3375,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3361,7 +3391,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3377,7 +3407,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3393,7 +3423,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3409,7 +3439,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3425,7 +3455,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3441,7 +3471,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3457,7 +3487,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3473,7 +3503,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3489,7 +3519,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3505,7 +3535,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3522,7 +3552,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3538,7 +3568,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3554,7 +3584,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3570,7 +3600,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 7 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3586,7 +3616,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 13 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3602,7 +3632,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3618,7 +3648,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3634,7 +3664,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3650,7 +3680,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3666,7 +3696,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3682,7 +3712,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 10 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3698,7 +3728,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3714,7 +3744,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3730,7 +3760,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3746,7 +3776,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3762,7 +3792,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3778,7 +3808,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3794,7 +3824,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3810,7 +3840,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3826,7 +3856,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3842,7 +3872,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3858,7 +3888,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3874,7 +3904,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3890,7 +3920,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3906,7 +3936,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3922,7 +3952,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3938,7 +3968,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 10 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3954,7 +3984,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3970,7 +4000,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -3986,7 +4016,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4002,7 +4032,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4018,7 +4048,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4034,7 +4064,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4050,7 +4080,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4066,7 +4096,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4082,7 +4112,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4098,7 +4128,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4114,7 +4144,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4130,7 +4160,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4146,7 +4176,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 13 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4162,7 +4192,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4178,7 +4208,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4194,7 +4224,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4210,7 +4240,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4226,7 +4256,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4242,7 +4272,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4258,7 +4288,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4274,7 +4304,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4290,7 +4320,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4306,7 +4336,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4323,7 +4353,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 7 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4340,7 +4370,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4356,7 +4386,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4372,7 +4402,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4388,7 +4418,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4404,7 +4434,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4420,7 +4450,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4436,7 +4466,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4452,7 +4482,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4468,7 +4498,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4484,7 +4514,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4500,7 +4530,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4516,7 +4546,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4532,7 +4562,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 10 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4548,7 +4578,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4564,7 +4594,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4580,7 +4610,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4596,7 +4626,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4612,7 +4642,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4628,7 +4658,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4644,7 +4674,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4660,7 +4690,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4676,7 +4706,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4692,7 +4722,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4708,7 +4738,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4724,7 +4754,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4740,7 +4770,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4756,7 +4786,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4772,7 +4802,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4788,7 +4818,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4804,7 +4834,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4820,7 +4850,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4836,7 +4866,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4852,7 +4882,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4868,7 +4898,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4884,7 +4914,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4900,7 +4930,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4916,7 +4946,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 13 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4932,7 +4962,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 10 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4948,7 +4978,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4964,7 +4994,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4980,7 +5010,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -4996,7 +5026,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5012,7 +5042,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5028,7 +5058,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5044,7 +5074,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5060,7 +5090,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5077,7 +5107,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5093,7 +5123,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5109,7 +5139,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5126,7 +5156,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5142,7 +5172,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5158,7 +5188,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5174,7 +5204,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5190,7 +5220,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5206,7 +5236,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5222,7 +5252,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5238,7 +5268,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5254,7 +5284,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5270,7 +5300,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5286,7 +5316,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5302,7 +5332,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5318,7 +5348,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5334,7 +5364,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5350,7 +5380,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5366,7 +5396,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5382,7 +5412,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5398,7 +5428,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 7 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5414,7 +5444,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5430,7 +5460,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5446,7 +5476,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5462,7 +5492,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5478,7 +5508,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5494,7 +5524,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5510,7 +5540,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5526,7 +5556,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5542,7 +5572,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5558,7 +5588,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 13 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5574,7 +5604,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 10 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5590,7 +5620,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5606,7 +5636,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5622,7 +5652,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5638,7 +5668,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 10 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5654,7 +5684,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5670,7 +5700,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5686,7 +5716,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5702,7 +5732,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5718,7 +5748,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5734,7 +5764,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5750,7 +5780,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5766,7 +5796,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5782,7 +5812,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5798,7 +5828,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5814,7 +5844,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5830,7 +5860,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 7 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5846,7 +5876,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5862,7 +5892,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5878,7 +5908,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5894,7 +5924,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5910,7 +5940,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5927,7 +5957,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5943,7 +5973,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5959,7 +5989,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5975,7 +6005,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -5991,7 +6021,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6007,7 +6037,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6023,7 +6053,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6039,7 +6069,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6055,7 +6085,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6071,7 +6101,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6087,7 +6117,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6103,7 +6133,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6119,7 +6149,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6135,7 +6165,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6151,7 +6181,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6167,7 +6197,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6183,7 +6213,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6199,7 +6229,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 10 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6215,7 +6245,7 @@ databaseChangeLog: - column: { name: type, value: 'INCOME' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6231,7 +6261,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6247,7 +6277,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6263,7 +6293,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6279,7 +6309,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6295,7 +6325,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6311,7 +6341,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6327,7 +6357,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6343,7 +6373,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6359,7 +6389,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6375,7 +6405,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6391,7 +6421,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6407,7 +6437,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6423,7 +6453,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6439,7 +6469,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6455,7 +6485,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'HUF' } @@ -6473,7 +6503,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'EUR' } @@ -6489,7 +6519,7 @@ databaseChangeLog: - column: { name: type, value: 'EXPENSE' } - column: { name: created_by_recurring_job, valueBoolean: false } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } - column: { name: currency, value: 'USD' } @@ -6520,7 +6550,7 @@ databaseChangeLog: valueComputed: "CASE WHEN EXTRACT(DAY FROM CURRENT_DATE) < 8 THEN (DATE_TRUNC('month', CURRENT_DATE) + INTERVAL '7 days')::DATE ELSE (DATE_TRUNC('month', CURRENT_DATE + INTERVAL '1 month') + INTERVAL '7 days')::DATE END" - column: { name: active, valueBoolean: true } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: updated_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -6544,7 +6574,7 @@ databaseChangeLog: valueComputed: "CASE WHEN EXTRACT(DAY FROM CURRENT_DATE) < 4 THEN (DATE_TRUNC('month', CURRENT_DATE) + INTERVAL '3 days')::DATE ELSE (DATE_TRUNC('month', CURRENT_DATE + INTERVAL '1 month') + INTERVAL '3 days')::DATE END" - column: { name: active, valueBoolean: true } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: updated_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -6568,7 +6598,7 @@ databaseChangeLog: valueComputed: "CASE WHEN EXTRACT(DAY FROM CURRENT_DATE) < 12 THEN (DATE_TRUNC('month', CURRENT_DATE) + INTERVAL '11 days')::DATE ELSE (DATE_TRUNC('month', CURRENT_DATE + INTERVAL '1 month') + INTERVAL '11 days')::DATE END" - column: { name: active, valueBoolean: true } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: updated_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -6592,7 +6622,7 @@ databaseChangeLog: valueComputed: "DATE_TRUNC('month', CURRENT_DATE + INTERVAL '1 month')::DATE" - column: { name: active, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: updated_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -6617,7 +6647,7 @@ databaseChangeLog: valueComputed: "CASE WHEN EXTRACT(DAY FROM CURRENT_DATE) < 15 THEN (DATE_TRUNC('month', CURRENT_DATE) + INTERVAL '14 days')::DATE ELSE (DATE_TRUNC('month', CURRENT_DATE + INTERVAL '1 month') + INTERVAL '14 days')::DATE END" - column: { name: active, valueBoolean: true } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: updated_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -6641,7 +6671,7 @@ databaseChangeLog: valueComputed: "(DATE_TRUNC('month', CURRENT_DATE + INTERVAL '2 months') + INTERVAL '19 days')::DATE" - column: { name: active, valueBoolean: true } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: updated_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -6665,7 +6695,7 @@ databaseChangeLog: valueComputed: "CASE WHEN CURRENT_DATE < (DATE_TRUNC('year', CURRENT_DATE)::DATE + INTERVAL '2 months') THEN (DATE_TRUNC('year', CURRENT_DATE)::DATE + INTERVAL '2 months') ELSE (DATE_TRUNC('year', CURRENT_DATE + INTERVAL '1 year')::DATE + INTERVAL '2 months') END" - column: { name: active, valueBoolean: true } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: updated_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -6689,7 +6719,7 @@ databaseChangeLog: valueComputed: "DATE_TRUNC('week', CURRENT_DATE + INTERVAL '7 days')::DATE" - column: { name: active, valueBoolean: true } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "${now}" } - column: { name: updated_at, valueComputed: "${now}" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -6711,7 +6741,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 1 } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'HUF' } - column: { name: exchange_rate, valueNumeric: 1.0 } - column: { name: base_currency_amount, valueNumeric: 11208.00 } @@ -6731,7 +6761,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 1 } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'HUF' } - column: { name: exchange_rate, valueNumeric: 1.0 } - column: { name: base_currency_amount, valueNumeric: 11208.00 } @@ -6753,7 +6783,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 2 } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'EUR' } - column: { name: exchange_rate, valueNumeric: 400.0 } - column: { name: base_currency_amount, valueNumeric: 6000.00 } @@ -6773,7 +6803,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 2 } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'EUR' } - column: { name: exchange_rate, valueNumeric: 398.0 } - column: { name: base_currency_amount, valueNumeric: 5970.00 } @@ -6793,7 +6823,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 2 } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'EUR' } - column: { name: exchange_rate, valueNumeric: 402.0 } - column: { name: base_currency_amount, valueNumeric: 6030.00 } @@ -6813,7 +6843,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 2 } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'EUR' } - column: { name: exchange_rate, valueNumeric: 395.0 } - column: { name: base_currency_amount, valueNumeric: 5925.00 } @@ -6833,7 +6863,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 2 } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'EUR' } - column: { name: exchange_rate, valueNumeric: 397.0 } - column: { name: base_currency_amount, valueNumeric: 5955.00 } @@ -6855,7 +6885,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 3 } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'USD' } - column: { name: exchange_rate, valueNumeric: 362.0 } - column: { name: base_currency_amount, valueNumeric: 362.00 } @@ -6875,7 +6905,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 3 } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'USD' } - column: { name: exchange_rate, valueNumeric: 358.0 } - column: { name: base_currency_amount, valueNumeric: 358.00 } @@ -6895,7 +6925,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 3 } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'USD' } - column: { name: exchange_rate, valueNumeric: 365.0 } - column: { name: base_currency_amount, valueNumeric: 365.00 } @@ -6915,7 +6945,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 3 } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'USD' } - column: { name: exchange_rate, valueNumeric: 360.0 } - column: { name: base_currency_amount, valueNumeric: 360.00 } @@ -6937,7 +6967,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 4 } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'HUF' } - column: { name: exchange_rate, valueNumeric: 1.0 } - column: { name: base_currency_amount, valueNumeric: 560000.00 } @@ -6957,7 +6987,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 4 } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'HUF' } - column: { name: exchange_rate, valueNumeric: 1.0 } - column: { name: base_currency_amount, valueNumeric: 560000.00 } @@ -6977,7 +7007,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 4 } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'HUF' } - column: { name: exchange_rate, valueNumeric: 1.0 } - column: { name: base_currency_amount, valueNumeric: 560000.00 } @@ -6999,7 +7029,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 5 } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'HUF' } - column: { name: exchange_rate, valueNumeric: 1.0 } - column: { name: base_currency_amount, valueNumeric: 98000.00 } @@ -7019,7 +7049,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 5 } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'HUF' } - column: { name: exchange_rate, valueNumeric: 1.0 } - column: { name: base_currency_amount, valueNumeric: 98000.00 } @@ -7039,7 +7069,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 5 } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'HUF' } - column: { name: exchange_rate, valueNumeric: 1.0 } - column: { name: base_currency_amount, valueNumeric: 98000.00 } @@ -7059,7 +7089,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 5 } - column: { name: category_id, valueNumeric: 9 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'HUF' } - column: { name: exchange_rate, valueNumeric: 1.0 } - column: { name: base_currency_amount, valueNumeric: 98000.00 } @@ -7081,7 +7111,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 6 } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'EUR' } - column: { name: exchange_rate, valueNumeric: 401.0 } - column: { name: base_currency_amount, valueNumeric: 56942.00 } @@ -7101,7 +7131,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 6 } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'EUR' } - column: { name: exchange_rate, valueNumeric: 396.0 } - column: { name: base_currency_amount, valueNumeric: 56232.00 } @@ -7121,7 +7151,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 6 } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'EUR' } - column: { name: exchange_rate, valueNumeric: 390.0 } - column: { name: base_currency_amount, valueNumeric: 55380.00 } @@ -7143,7 +7173,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 7 } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'EUR' } - column: { name: exchange_rate, valueNumeric: 388.0 } - column: { name: base_currency_amount, valueNumeric: 88464.00 } @@ -7165,7 +7195,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 8 } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'HUF' } - column: { name: exchange_rate, valueNumeric: 1.0 } - column: { name: base_currency_amount, valueNumeric: 3450.00 } @@ -7185,7 +7215,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 8 } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'HUF' } - column: { name: exchange_rate, valueNumeric: 1.0 } - column: { name: base_currency_amount, valueNumeric: 3450.00 } @@ -7205,7 +7235,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 8 } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'HUF' } - column: { name: exchange_rate, valueNumeric: 1.0 } - column: { name: base_currency_amount, valueNumeric: 3450.00 } @@ -7225,7 +7255,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 8 } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'HUF' } - column: { name: exchange_rate, valueNumeric: 1.0 } - column: { name: base_currency_amount, valueNumeric: 3450.00 } @@ -7245,7 +7275,7 @@ databaseChangeLog: - column: { name: created_by_recurring_job, valueBoolean: true } - column: { name: recurring_transaction_id, valueNumeric: 8 } - column: { name: category_id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: currency, value: 'HUF' } - column: { name: exchange_rate, valueNumeric: 1.0 } - column: { name: base_currency_amount, valueNumeric: 3450.00 } @@ -7264,8 +7294,6 @@ databaseChangeLog: - column: { name: language, value: 'en' } - column: { name: primary_theme, value: 'DARK' } - column: { name: secondary_theme, value: 'BLUE_DOLPHIN' } - - column: { name: base_currency, value: 'HUF' } - - column: { name: show_base_currency, valueBoolean: false } # Widgets - insert: @@ -7302,7 +7330,7 @@ databaseChangeLog: name: settings value: '{}' - column: - name: user_id + name: workspace_id valueNumeric: 1 # Stat cards @@ -7314,7 +7342,7 @@ databaseChangeLog: - column: { name: title, value: 'Expense frequency' } - column: { name: timeframe, value: 'YTD' } - column: { name: display_order, valueNumeric: 0 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - insert: tableName: widget @@ -7324,7 +7352,7 @@ databaseChangeLog: - column: { name: title, value: 'Number of days without spending' } - column: { name: timeframe, value: 'YTD' } - column: { name: display_order, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - insert: tableName: widget @@ -7334,7 +7362,7 @@ databaseChangeLog: - column: { name: title, value: 'Savings rate' } - column: { name: timeframe, value: 'YTD' } - column: { name: display_order, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - insert: tableName: widget @@ -7344,7 +7372,7 @@ databaseChangeLog: - column: { name: title, value: 'Top income' } - column: { name: timeframe, value: 'YTD' } - column: { name: display_order, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } # Chart widgets - insert: @@ -7358,7 +7386,7 @@ databaseChangeLog: - column: { name: y, valueNumeric: 0 } - column: { name: cols, valueNumeric: 1 } - column: { name: rows, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - insert: tableName: widget @@ -7371,7 +7399,7 @@ databaseChangeLog: - column: { name: y, valueNumeric: 0 } - column: { name: cols, valueNumeric: 1 } - column: { name: rows, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - insert: tableName: widget @@ -7384,7 +7412,7 @@ databaseChangeLog: - column: { name: y, valueNumeric: 1 } - column: { name: cols, valueNumeric: 2 } - column: { name: rows, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } # Goals # Goal 1: Smart TV - COMPLETED (HUF, Shopping) @@ -7402,7 +7430,7 @@ databaseChangeLog: - column: { name: deadline, valueDate: '2025-12-31' } - column: { name: status, value: 'COMPLETED' } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '450 days' + TIME '10:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '220 days' + TIME '14:30')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7423,7 +7451,7 @@ databaseChangeLog: - column: { name: deadline, valueDate: '2026-08-01' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '210 days' + TIME '09:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '5 days' + TIME '11:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7444,7 +7472,7 @@ databaseChangeLog: - column: { name: deadline, valueDate: '2026-06-30' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '700 days' + TIME '08:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '85 days' + TIME '16:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7465,7 +7493,7 @@ databaseChangeLog: - column: { name: deadline, valueDate: '2030-06-01' } - column: { name: status, value: 'PAUSED' } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '820 days' + TIME '10:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '280 days' + TIME '09:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7486,7 +7514,7 @@ databaseChangeLog: - column: { name: deadline, valueDate: '2025-03-31' } - column: { name: status, value: 'EXPIRED' } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '540 days' + TIME '12:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '370 days' + TIME '07:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7506,7 +7534,7 @@ databaseChangeLog: - column: { name: current_base_currency_amount, valueNumeric: 700000.00 } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '280 days' + TIME '09:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '5 days' + TIME '10:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7759,7 +7787,7 @@ databaseChangeLog: - column: { name: type, value: 'BORROWED' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '60 days' + TIME '10:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '15 days' + TIME '14:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7781,7 +7809,7 @@ databaseChangeLog: - column: { name: type, value: 'BORROWED' } - column: { name: status, value: 'SETTLED' } - column: { name: category_id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '90 days' + TIME '09:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '10 days' + TIME '11:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7803,7 +7831,7 @@ databaseChangeLog: - column: { name: type, value: 'BORROWED' } - column: { name: status, value: 'EXPIRED' } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '120 days' + TIME '08:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '5 days' + TIME '00:01')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7824,7 +7852,7 @@ databaseChangeLog: - column: { name: type, value: 'BORROWED' } - column: { name: status, value: 'FORGIVEN' } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '200 days' + TIME '15:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '100 days' + TIME '12:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7846,7 +7874,7 @@ databaseChangeLog: - column: { name: type, value: 'BORROWED' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '45 days' + TIME '10:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '7 days' + TIME '16:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7867,7 +7895,7 @@ databaseChangeLog: - column: { name: type, value: 'BORROWED' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '30 days' + TIME '20:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '15 days' + TIME '09:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7889,7 +7917,7 @@ databaseChangeLog: - column: { name: type, value: 'BORROWED' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '20 days' + TIME '11:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '20 days' + TIME '11:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7911,7 +7939,7 @@ databaseChangeLog: - column: { name: type, value: 'BORROWED' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '10 days' + TIME '13:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '10 days' + TIME '13:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7933,7 +7961,7 @@ databaseChangeLog: - column: { name: type, value: 'BORROWED' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '14 days' + TIME '10:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '14 days' + TIME '10:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7955,7 +7983,7 @@ databaseChangeLog: - column: { name: type, value: 'BORROWED' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '50 days' + TIME '09:30')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '20 days' + TIME '15:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7977,7 +8005,7 @@ databaseChangeLog: - column: { name: type, value: 'LENT' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '80 days' + TIME '14:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '30 days' + TIME '10:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -7999,7 +8027,7 @@ databaseChangeLog: - column: { name: type, value: 'LENT' } - column: { name: status, value: 'SETTLED' } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '100 days' + TIME '09:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '20 days' + TIME '16:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8021,7 +8049,7 @@ databaseChangeLog: - column: { name: type, value: 'LENT' } - column: { name: status, value: 'EXPIRED' } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '180 days' + TIME '10:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '30 days' + TIME '00:01')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8042,7 +8070,7 @@ databaseChangeLog: - column: { name: type, value: 'LENT' } - column: { name: status, value: 'FORGIVEN' } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '150 days' + TIME '18:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '60 days' + TIME '12:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8064,7 +8092,7 @@ databaseChangeLog: - column: { name: type, value: 'LENT' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '40 days' + TIME '08:30')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '10 days' + TIME '11:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8086,7 +8114,7 @@ databaseChangeLog: - column: { name: type, value: 'LENT' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '25 days' + TIME '17:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '25 days' + TIME '17:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8107,7 +8135,7 @@ databaseChangeLog: - column: { name: type, value: 'LENT' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '70 days' + TIME '10:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '35 days' + TIME '14:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8129,7 +8157,7 @@ databaseChangeLog: - column: { name: type, value: 'LENT' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '5 days' + TIME '09:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '5 days' + TIME '09:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8151,7 +8179,7 @@ databaseChangeLog: - column: { name: type, value: 'LENT' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '35 days' + TIME '11:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '12 days' + TIME '15:30')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8173,7 +8201,7 @@ databaseChangeLog: - column: { name: type, value: 'LENT' } - column: { name: status, value: 'ACTIVE' } - column: { name: category_id, valueNumeric: 11 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '8 days' + TIME '14:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '8 days' + TIME '14:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8369,61 +8397,61 @@ databaseChangeLog: - column: { name: type, value: 'APP_STREAK' } - column: { name: requirement_value, valueNumeric: 90 } - # User achievements (unlocked by test user) + # Workspace achievements (unlocked by test workspace) - insert: - tableName: user_achievement + tableName: workspace_achievement columns: - column: { name: id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: achievement_id, valueNumeric: 1 } - column: { name: unlocked_at, valueComputed: "(CURRENT_DATE - INTERVAL '300 days' + TIME '10:00')::timestamptz" } - insert: - tableName: user_achievement + tableName: workspace_achievement columns: - column: { name: id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: achievement_id, valueNumeric: 2 } - column: { name: unlocked_at, valueComputed: "(CURRENT_DATE - INTERVAL '200 days' + TIME '11:00')::timestamptz" } - insert: - tableName: user_achievement + tableName: workspace_achievement columns: - column: { name: id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: achievement_id, valueNumeric: 3 } - column: { name: unlocked_at, valueComputed: "(CURRENT_DATE - INTERVAL '100 days' + TIME '09:30')::timestamptz" } - insert: - tableName: user_achievement + tableName: workspace_achievement columns: - column: { name: id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: achievement_id, valueNumeric: 4 } - column: { name: unlocked_at, valueComputed: "(CURRENT_DATE - INTERVAL '250 days' + TIME '14:00')::timestamptz" } - insert: - tableName: user_achievement + tableName: workspace_achievement columns: - column: { name: id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: achievement_id, valueNumeric: 5 } - column: { name: unlocked_at, valueComputed: "(CURRENT_DATE - INTERVAL '80 days' + TIME '16:00')::timestamptz" } - insert: - tableName: user_achievement + tableName: workspace_achievement columns: - column: { name: id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: achievement_id, valueNumeric: 7 } - column: { name: unlocked_at, valueComputed: "(CURRENT_DATE - INTERVAL '60 days' + TIME '12:00')::timestamptz" } - insert: - tableName: user_achievement + tableName: workspace_achievement columns: - column: { name: id, valueNumeric: 7 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: achievement_id, valueNumeric: 10 } - column: { name: unlocked_at, valueComputed: "(CURRENT_DATE - INTERVAL '50 days' + TIME '10:30')::timestamptz" } - insert: - tableName: user_achievement + tableName: workspace_achievement columns: - column: { name: id, valueNumeric: 8 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: achievement_id, valueNumeric: 11 } - column: { name: unlocked_at, valueComputed: "(CURRENT_DATE - INTERVAL '30 days' + TIME '15:00')::timestamptz" } @@ -8432,42 +8460,42 @@ databaseChangeLog: tableName: achievement_progress columns: - column: { name: id, valueNumeric: 1 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: achievement_type, value: 'TRANSACTION_COUNT' } - column: { name: current_value, valueNumeric: 400 } - insert: tableName: achievement_progress columns: - column: { name: id, valueNumeric: 2 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: achievement_type, value: 'GOAL_COUNT' } - column: { name: current_value, valueNumeric: 6 } - insert: tableName: achievement_progress columns: - column: { name: id, valueNumeric: 3 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: achievement_type, value: 'GOAL_COMPLETED' } - column: { name: current_value, valueNumeric: 1 } - insert: tableName: achievement_progress columns: - column: { name: id, valueNumeric: 4 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: achievement_type, value: 'DEBT_COUNT' } - column: { name: current_value, valueNumeric: 20 } - insert: tableName: achievement_progress columns: - column: { name: id, valueNumeric: 5 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: achievement_type, value: 'DEBT_SETTLED' } - column: { name: current_value, valueNumeric: 5 } - insert: tableName: achievement_progress columns: - column: { name: id, valueNumeric: 6 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: achievement_type, value: 'APP_STREAK' } - column: { name: current_value, valueNumeric: 14 } @@ -8483,7 +8511,7 @@ databaseChangeLog: - column: { name: currency, value: 'USD' } - column: { name: base_currency_amount, valueNumeric: 1140000.00 } - column: { name: note, value: 'First BTC purchase — long-term hold' } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '420 days' + TIME '09:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '420 days' + TIME '09:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8499,7 +8527,7 @@ databaseChangeLog: - column: { name: currency, value: 'USD' } - column: { name: base_currency_amount, valueNumeric: 760000.00 } - column: { name: note, value: 'DCA purchase' } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '200 days' + TIME '10:30')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '200 days' + TIME '10:30')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8515,7 +8543,7 @@ databaseChangeLog: - column: { name: currency, value: 'USD' } - column: { name: base_currency_amount, valueNumeric: 855000.00 } - column: { name: note, value: 'Index ETF — passive strategy' } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '380 days' + TIME '11:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '380 days' + TIME '11:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8531,7 +8559,7 @@ databaseChangeLog: - column: { name: currency, value: 'USD' } - column: { name: base_currency_amount, valueNumeric: 988000.00 } - column: { name: note, value: 'Monthly DCA' } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '90 days' + TIME '09:15')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '90 days' + TIME '09:15')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8547,7 +8575,7 @@ databaseChangeLog: - column: { name: currency, value: 'USD' } - column: { name: base_currency_amount, valueNumeric: 684000.00 } - column: { name: note, value: 'Safe haven allocation' } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '310 days' + TIME '14:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '310 days' + TIME '14:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8563,7 +8591,7 @@ databaseChangeLog: - column: { name: currency, value: 'USD' } - column: { name: base_currency_amount, valueNumeric: 798000.00 } - column: { name: note, value: 'Added to gold position' } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '60 days' + TIME '15:30')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '60 days' + TIME '15:30')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8579,7 +8607,7 @@ databaseChangeLog: - column: { name: currency, value: 'USD' } - column: { name: base_currency_amount, valueNumeric: 1900000.00 } - column: { name: note, value: '6-month T-bill' } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '180 days' + TIME '08:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '180 days' + TIME '08:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8595,7 +8623,7 @@ databaseChangeLog: - column: { name: currency, value: 'USD' } - column: { name: base_currency_amount, valueNumeric: 570000.00 } - column: { name: note, value: 'Long-term hold' } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '450 days' + TIME '13:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '450 days' + TIME '13:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8611,7 +8639,7 @@ databaseChangeLog: - column: { name: currency, value: 'USD' } - column: { name: base_currency_amount, valueNumeric: 665000.00 } - column: { name: note, value: 'Added on dip' } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '150 days' + TIME '10:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '150 days' + TIME '10:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8627,7 +8655,7 @@ databaseChangeLog: - column: { name: currency, value: 'USD' } - column: { name: base_currency_amount, valueNumeric: 456000.00 } - column: { name: note, value: 'Nasdaq 100 non-financial companies' } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '270 days' + TIME '16:00')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '270 days' + TIME '16:00')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8642,7 +8670,7 @@ databaseChangeLog: - column: { name: amount, valueNumeric: 960.00 } - column: { name: currency, value: 'USD' } - column: { name: base_currency_amount, valueNumeric: 364800.00 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '30 days' + TIME '11:30')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '30 days' + TIME '11:30')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8657,7 +8685,7 @@ databaseChangeLog: - column: { name: amount, valueNumeric: 1250.00 } - column: { name: currency, value: 'USD' } - column: { name: base_currency_amount, valueNumeric: 475000.00 } - - column: { name: user_id, valueNumeric: 1 } + - column: { name: workspace_id, valueNumeric: 1 } - column: { name: created_at, valueComputed: "(CURRENT_DATE - INTERVAL '30 days' + TIME '11:30')::timestamptz" } - column: { name: updated_at, valueComputed: "(CURRENT_DATE - INTERVAL '30 days' + TIME '11:30')::timestamptz" } - column: { name: created_by, value: 'captainwinnie@exence.com' } @@ -8666,9 +8694,15 @@ databaseChangeLog: - sql: sql: SELECT setval('achievement_id_seq', (SELECT COALESCE(MAX(id), 1) FROM achievement)); - sql: - sql: SELECT setval('user_achievement_id_seq', (SELECT COALESCE(MAX(id), 1) FROM user_achievement)); + sql: SELECT setval('workspace_achievement_id_seq', (SELECT COALESCE(MAX(id), 1) FROM workspace_achievement)); - sql: sql: SELECT setval('achievement_progress_id_seq', (SELECT COALESCE(MAX(id), 1) FROM achievement_progress)); - sql: sql: SELECT setval('investment_id_seq', (SELECT COALESCE(MAX(id), 1) FROM investment)); + - sql: + sql: SELECT setval('workspace_id_seq', (SELECT COALESCE(MAX(id), 1) FROM workspace)); + - sql: + sql: SELECT setval('workspace_member_id_seq', (SELECT COALESCE(MAX(id), 1) FROM workspace_member)); + - sql: + sql: SELECT setval('workspace_settings_id_seq', (SELECT COALESCE(MAX(id), 1) FROM workspace_settings)); diff --git a/backend/exence/src/main/resources/db/changelog/db.changelog-master.yaml b/backend/exence/src/main/resources/db/changelog/db.changelog-master.yaml index da843179..0c33e3fc 100644 --- a/backend/exence/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/backend/exence/src/main/resources/db/changelog/db.changelog-master.yaml @@ -20,6 +20,9 @@ databaseChangeLog: file: v1.4.0/changelog-v1.4.0.yaml relativeToChangelogFile: true + - include: + file: v1.5.0/changelog-v1.5.0.yaml + relativeToChangelogFile: true # Test data - include: file: data/test-data.yaml diff --git a/backend/exence/src/main/resources/db/changelog/v1.5.0/changelog-v1.5.0.yaml b/backend/exence/src/main/resources/db/changelog/v1.5.0/changelog-v1.5.0.yaml new file mode 100644 index 00000000..cf19b842 --- /dev/null +++ b/backend/exence/src/main/resources/db/changelog/v1.5.0/changelog-v1.5.0.yaml @@ -0,0 +1,26 @@ +databaseChangeLog: + - include: + file: create-workspace-sequences.yaml + relativeToChangelogFile: true + - include: + file: create-workspace-role-enum.yaml + relativeToChangelogFile: true + - include: + file: create-workspace-table.yaml + relativeToChangelogFile: true + - include: + file: create-workspace-member-table.yaml + relativeToChangelogFile: true + - include: + file: create-workspace-settings-table.yaml + relativeToChangelogFile: true + - include: + file: migrate-business-tables-to-workspace.yaml + relativeToChangelogFile: true + - include: + file: recreate-mv-daily-category-stat-workspace.yaml + relativeToChangelogFile: true + - include: + file: migrate-achievements-to-workspace.yaml + relativeToChangelogFile: true + diff --git a/backend/exence/src/main/resources/db/changelog/v1.5.0/create-workspace-member-table.yaml b/backend/exence/src/main/resources/db/changelog/v1.5.0/create-workspace-member-table.yaml new file mode 100644 index 00000000..7b767b17 --- /dev/null +++ b/backend/exence/src/main/resources/db/changelog/v1.5.0/create-workspace-member-table.yaml @@ -0,0 +1,62 @@ +databaseChangeLog: + - changeSet: + id: create-workspace-member-table + author: hptrk + comment: Create workspace_member junction table with role and joined_at + dbms: postgresql + changes: + - createTable: + tableName: workspace_member + columns: + - column: + name: id + type: BIGINT + constraints: + primaryKey: true + primaryKeyName: pk_workspace_member + nullable: false + - column: + name: workspace_id + type: BIGINT + constraints: + nullable: false + - column: + name: user_id + type: BIGINT + constraints: + nullable: false + - column: + name: role + type: workspace_role + constraints: + nullable: false + - column: + name: joined_at + type: TIMESTAMP WITH TIME ZONE + constraints: + nullable: false + + - addForeignKeyConstraint: + baseTableName: workspace_member + baseColumnNames: workspace_id + constraintName: fk_workspace_member_workspace + referencedTableName: workspace + referencedColumnNames: id + onDelete: CASCADE + + - addForeignKeyConstraint: + baseTableName: workspace_member + baseColumnNames: user_id + constraintName: fk_workspace_member_user + referencedTableName: _user + referencedColumnNames: id + onDelete: CASCADE + + - addUniqueConstraint: + tableName: workspace_member + columnNames: workspace_id, user_id + constraintName: uq_workspace_member + + rollback: + - dropTable: + tableName: workspace_member diff --git a/backend/exence/src/main/resources/db/changelog/v1.5.0/create-workspace-role-enum.yaml b/backend/exence/src/main/resources/db/changelog/v1.5.0/create-workspace-role-enum.yaml new file mode 100644 index 00000000..2f2727f0 --- /dev/null +++ b/backend/exence/src/main/resources/db/changelog/v1.5.0/create-workspace-role-enum.yaml @@ -0,0 +1,12 @@ +databaseChangeLog: + - changeSet: + id: create-workspace-role-enum + author: hptrk + comment: Create workspace_role PostgreSQL ENUM type + dbms: postgresql + changes: + - sql: + sql: CREATE TYPE workspace_role AS ENUM ('OWNER', 'MEMBER') + rollback: + - sql: + sql: DROP TYPE IF EXISTS workspace_role diff --git a/backend/exence/src/main/resources/db/changelog/v1.5.0/create-workspace-sequences.yaml b/backend/exence/src/main/resources/db/changelog/v1.5.0/create-workspace-sequences.yaml new file mode 100644 index 00000000..43334ece --- /dev/null +++ b/backend/exence/src/main/resources/db/changelog/v1.5.0/create-workspace-sequences.yaml @@ -0,0 +1,25 @@ +databaseChangeLog: + - changeSet: + id: create-workspace-sequences + author: hptrk + comment: Create sequences for workspace, workspace_member, and workspace_settings tables + changes: + - createSequence: + sequenceName: workspace_id_seq + startValue: 1 + incrementBy: 1 + - createSequence: + sequenceName: workspace_member_id_seq + startValue: 1 + incrementBy: 1 + - createSequence: + sequenceName: workspace_settings_id_seq + startValue: 1 + incrementBy: 1 + rollback: + - dropSequence: + sequenceName: workspace_id_seq + - dropSequence: + sequenceName: workspace_member_id_seq + - dropSequence: + sequenceName: workspace_settings_id_seq diff --git a/backend/exence/src/main/resources/db/changelog/v1.5.0/create-workspace-settings-table.yaml b/backend/exence/src/main/resources/db/changelog/v1.5.0/create-workspace-settings-table.yaml new file mode 100644 index 00000000..25586574 --- /dev/null +++ b/backend/exence/src/main/resources/db/changelog/v1.5.0/create-workspace-settings-table.yaml @@ -0,0 +1,50 @@ +databaseChangeLog: + - changeSet: + id: create-workspace-settings-table + author: hptrk + comment: Create workspace_settings table for workspace-level preferences + dbms: postgresql + changes: + - createTable: + tableName: workspace_settings + columns: + - column: + name: id + type: BIGINT + constraints: + primaryKey: true + primaryKeyName: pk_workspace_settings + nullable: false + - column: + name: workspace_id + type: BIGINT + constraints: + nullable: false + - column: + name: base_currency + type: supported_currency + constraints: + nullable: false + - column: + name: show_base_currency + type: BOOLEAN + defaultValueBoolean: false + constraints: + nullable: false + + - addForeignKeyConstraint: + baseTableName: workspace_settings + baseColumnNames: workspace_id + constraintName: fk_workspace_settings_workspace + referencedTableName: workspace + referencedColumnNames: id + onDelete: CASCADE + + - addUniqueConstraint: + tableName: workspace_settings + columnNames: workspace_id + constraintName: uq_workspace_settings_workspace + + rollback: + - dropTable: + tableName: workspace_settings diff --git a/backend/exence/src/main/resources/db/changelog/v1.5.0/create-workspace-table.yaml b/backend/exence/src/main/resources/db/changelog/v1.5.0/create-workspace-table.yaml new file mode 100644 index 00000000..09e4311c --- /dev/null +++ b/backend/exence/src/main/resources/db/changelog/v1.5.0/create-workspace-table.yaml @@ -0,0 +1,40 @@ +databaseChangeLog: + - changeSet: + id: create-workspace-table + author: hptrk + comment: Create workspace table + changes: + - createTable: + tableName: workspace + columns: + - column: + name: id + type: BIGINT + constraints: + primaryKey: true + primaryKeyName: pk_workspace + nullable: false + - column: + name: name + type: VARCHAR(100) + constraints: + nullable: false + - column: + name: created_at + type: TIMESTAMP WITH TIME ZONE + constraints: + nullable: false + - column: + name: updated_at + type: TIMESTAMP WITH TIME ZONE + - column: + name: created_by + type: VARCHAR(100) + constraints: + nullable: false + - column: + name: updated_by + type: VARCHAR(100) + rollback: + - dropTable: + tableName: workspace diff --git a/backend/exence/src/main/resources/db/changelog/v1.5.0/migrate-achievements-to-workspace.yaml b/backend/exence/src/main/resources/db/changelog/v1.5.0/migrate-achievements-to-workspace.yaml new file mode 100644 index 00000000..adb40038 --- /dev/null +++ b/backend/exence/src/main/resources/db/changelog/v1.5.0/migrate-achievements-to-workspace.yaml @@ -0,0 +1,149 @@ +databaseChangeLog: + # Step 1: Migrate user_achievement → workspace_achievement + - changeSet: + id: migrate-user-achievement-to-workspace + author: hptrk + comment: Replace user_id with workspace_id on user_achievement and rename table to workspace_achievement + dbms: postgresql + changes: + - dropUniqueConstraint: + tableName: user_achievement + constraintName: uq_user_achievement + - dropForeignKeyConstraint: + baseTableName: user_achievement + constraintName: fk_user_achievement_user + - dropColumn: + tableName: user_achievement + columnName: user_id + - addColumn: + tableName: user_achievement + columns: + - column: + name: workspace_id + type: BIGINT + constraints: + nullable: false + - addForeignKeyConstraint: + baseTableName: user_achievement + baseColumnNames: workspace_id + constraintName: fk_workspace_achievement_workspace + referencedTableName: workspace + referencedColumnNames: id + onDelete: CASCADE + - addUniqueConstraint: + tableName: user_achievement + columnNames: workspace_id, achievement_id + constraintName: uq_workspace_achievement + - renameTable: + oldTableName: user_achievement + newTableName: workspace_achievement + rollback: + - renameTable: + oldTableName: workspace_achievement + newTableName: user_achievement + - dropUniqueConstraint: + tableName: user_achievement + constraintName: uq_workspace_achievement + - dropForeignKeyConstraint: + baseTableName: user_achievement + constraintName: fk_workspace_achievement_workspace + - dropColumn: + tableName: user_achievement + columnName: workspace_id + - addColumn: + tableName: user_achievement + columns: + - column: + name: user_id + type: BIGINT + constraints: + nullable: false + - addForeignKeyConstraint: + baseTableName: user_achievement + baseColumnNames: user_id + constraintName: fk_user_achievement_user + referencedTableName: _user + referencedColumnNames: id + onDelete: CASCADE + - addUniqueConstraint: + tableName: user_achievement + columnNames: user_id, achievement_id + constraintName: uq_user_achievement + + # Step 2: Rename sequence for workspace_achievement + - changeSet: + id: rename-user-achievement-sequence + author: hptrk + comment: Rename user_achievement_id_seq to workspace_achievement_id_seq + dbms: postgresql + changes: + - sql: + sql: ALTER SEQUENCE user_achievement_id_seq RENAME TO workspace_achievement_id_seq + rollback: + - sql: + sql: ALTER SEQUENCE workspace_achievement_id_seq RENAME TO user_achievement_id_seq + + # Step 3: Migrate achievement_progress user_id → workspace_id + - changeSet: + id: migrate-achievement-progress-to-workspace + author: hptrk + comment: Replace user_id with workspace_id on achievement_progress + dbms: postgresql + changes: + - dropUniqueConstraint: + tableName: achievement_progress + constraintName: uq_achievement_progress_user_type + - dropForeignKeyConstraint: + baseTableName: achievement_progress + constraintName: fk_achievement_progress_user + - dropColumn: + tableName: achievement_progress + columnName: user_id + - addColumn: + tableName: achievement_progress + columns: + - column: + name: workspace_id + type: BIGINT + constraints: + nullable: false + - addForeignKeyConstraint: + baseTableName: achievement_progress + baseColumnNames: workspace_id + constraintName: fk_achievement_progress_workspace + referencedTableName: workspace + referencedColumnNames: id + onDelete: CASCADE + - addUniqueConstraint: + tableName: achievement_progress + columnNames: workspace_id, achievement_type + constraintName: uq_achievement_progress_workspace_type + rollback: + - dropUniqueConstraint: + tableName: achievement_progress + constraintName: uq_achievement_progress_workspace_type + - dropForeignKeyConstraint: + baseTableName: achievement_progress + constraintName: fk_achievement_progress_workspace + - dropColumn: + tableName: achievement_progress + columnName: workspace_id + - addColumn: + tableName: achievement_progress + columns: + - column: + name: user_id + type: BIGINT + constraints: + nullable: false + - addForeignKeyConstraint: + baseTableName: achievement_progress + baseColumnNames: user_id + constraintName: fk_achievement_progress_user + referencedTableName: _user + referencedColumnNames: id + onDelete: CASCADE + - addUniqueConstraint: + tableName: achievement_progress + columnNames: user_id, achievement_type + constraintName: uq_achievement_progress_user_type diff --git a/backend/exence/src/main/resources/db/changelog/v1.5.0/migrate-business-tables-to-workspace.yaml b/backend/exence/src/main/resources/db/changelog/v1.5.0/migrate-business-tables-to-workspace.yaml new file mode 100644 index 00000000..d230df73 --- /dev/null +++ b/backend/exence/src/main/resources/db/changelog/v1.5.0/migrate-business-tables-to-workspace.yaml @@ -0,0 +1,259 @@ +databaseChangeLog: + # Step 1: Drop base_currency + show_base_currency from user_settings (moved to workspace_settings) + - changeSet: + id: migrate-drop-currency-from-user-settings + author: hptrk + comment: Remove base_currency and show_base_currency from user_settings (moved to workspace_settings) + changes: + - dropColumn: + tableName: user_settings + columnName: base_currency + - dropColumn: + tableName: user_settings + columnName: show_base_currency + rollback: + - addColumn: + tableName: user_settings + columns: + - column: + name: base_currency + type: supported_currency + - column: + name: show_base_currency + type: BOOLEAN + defaultValueBoolean: false + + # Step 2: Drop old materialized view (references transaction.user_id; must go before dropColumn) + - changeSet: + id: migrate-drop-old-mv-daily-category-stat + author: hptrk + comment: > + Drop the old mv_daily_category_stat (built with user_id) before removing user_id + from the transaction table. The view will be recreated with workspace_id afterwards. + dbms: postgresql + changes: + - sql: + sql: DROP MATERIALIZED VIEW IF EXISTS mv_daily_category_stat + + # Step 3a: Migrate transaction table + - changeSet: + id: migrate-transaction-add-workspace-id + author: hptrk + comment: Replace user_id with workspace_id on the transaction table + dbms: postgresql + changes: + - dropIndex: + tableName: transaction + indexName: idx_transaction_user_id_date + - dropForeignKeyConstraint: + baseTableName: transaction + constraintName: fk_transaction_user + - dropColumn: + tableName: transaction + columnName: user_id + - addColumn: + tableName: transaction + columns: + - column: + name: workspace_id + type: BIGINT + constraints: + nullable: false + - addForeignKeyConstraint: + baseTableName: transaction + baseColumnNames: workspace_id + constraintName: fk_transaction_workspace + referencedTableName: workspace + referencedColumnNames: id + onDelete: CASCADE + - createIndex: + tableName: transaction + indexName: idx_transaction_workspace_id_date + columns: + - column: + name: workspace_id + - column: + name: date + + # Step 3b: Migrate recurring_transaction table + - changeSet: + id: migrate-recurring-transaction-add-workspace-id + author: hptrk + comment: Replace user_id with workspace_id on the recurring_transaction table + dbms: postgresql + changes: + - dropForeignKeyConstraint: + baseTableName: recurring_transaction + constraintName: fk_recurring_transaction_user + - dropColumn: + tableName: recurring_transaction + columnName: user_id + - addColumn: + tableName: recurring_transaction + columns: + - column: + name: workspace_id + type: BIGINT + constraints: + nullable: false + - addForeignKeyConstraint: + baseTableName: recurring_transaction + baseColumnNames: workspace_id + constraintName: fk_recurring_transaction_workspace + referencedTableName: workspace + referencedColumnNames: id + onDelete: CASCADE + + # Step 3c: Migrate category table + - changeSet: + id: migrate-category-add-workspace-id + author: hptrk + comment: Replace user_id with workspace_id on the category table + dbms: postgresql + changes: + - dropForeignKeyConstraint: + baseTableName: category + constraintName: fk_category_user + - dropColumn: + tableName: category + columnName: user_id + - addColumn: + tableName: category + columns: + - column: + name: workspace_id + type: BIGINT + constraints: + nullable: false + - addForeignKeyConstraint: + baseTableName: category + baseColumnNames: workspace_id + constraintName: fk_category_workspace + referencedTableName: workspace + referencedColumnNames: id + onDelete: CASCADE + + # Step 3d: Migrate goal table + - changeSet: + id: migrate-goal-add-workspace-id + author: hptrk + comment: Replace user_id with workspace_id on the goal table + dbms: postgresql + changes: + - dropForeignKeyConstraint: + baseTableName: goal + constraintName: fk_goal_user + - dropColumn: + tableName: goal + columnName: user_id + - addColumn: + tableName: goal + columns: + - column: + name: workspace_id + type: BIGINT + constraints: + nullable: false + - addForeignKeyConstraint: + baseTableName: goal + baseColumnNames: workspace_id + constraintName: fk_goal_workspace + referencedTableName: workspace + referencedColumnNames: id + onDelete: CASCADE + + # Step 3e: Migrate debt table + - changeSet: + id: migrate-debt-add-workspace-id + author: hptrk + comment: Replace user_id with workspace_id on the debt table + dbms: postgresql + changes: + - dropForeignKeyConstraint: + baseTableName: debt + constraintName: fk_debt_user + - dropColumn: + tableName: debt + columnName: user_id + - addColumn: + tableName: debt + columns: + - column: + name: workspace_id + type: BIGINT + constraints: + nullable: false + - addForeignKeyConstraint: + baseTableName: debt + baseColumnNames: workspace_id + constraintName: fk_debt_workspace + referencedTableName: workspace + referencedColumnNames: id + onDelete: CASCADE + + # Step 3f: Migrate widget table + - changeSet: + id: migrate-widget-add-workspace-id + author: hptrk + comment: Replace user_id with workspace_id on the widget table + dbms: postgresql + changes: + - dropIndex: + tableName: widget + indexName: idx_widget_user_id + - dropForeignKeyConstraint: + baseTableName: widget + constraintName: fk_widget_user + - dropColumn: + tableName: widget + columnName: user_id + - addColumn: + tableName: widget + columns: + - column: + name: workspace_id + type: BIGINT + constraints: + nullable: false + - addForeignKeyConstraint: + baseTableName: widget + baseColumnNames: workspace_id + constraintName: fk_widget_workspace + referencedTableName: workspace + referencedColumnNames: id + onDelete: CASCADE + - createIndex: + tableName: widget + indexName: idx_widget_workspace_id + columns: + - column: + name: workspace_id + + # Step 3g: Migrate investment table + - changeSet: + id: migrate-invest-add-workspace-id + author: hptrk + comment: Replace user_id with workspace_id on the investment table + dbms: postgresql + changes: + - dropForeignKeyConstraint: + baseTableName: investment + constraintName: fk_investment_user + - dropColumn: + tableName: investment + columnName: user_id + - addColumn: + tableName: investment + columns: + - column: + name: workspace_id + type: BIGINT + constraints: + nullable: false + - addForeignKeyConstraint: + baseTableName: investment + baseColumnNames: workspace_id + constraintName: fk_investment_workspace + referencedTableName: workspace + referencedColumnNames: id + onDelete: CASCADE diff --git a/backend/exence/src/main/resources/db/changelog/v1.5.0/recreate-mv-daily-category-stat-workspace.yaml b/backend/exence/src/main/resources/db/changelog/v1.5.0/recreate-mv-daily-category-stat-workspace.yaml new file mode 100644 index 00000000..5b31be6a --- /dev/null +++ b/backend/exence/src/main/resources/db/changelog/v1.5.0/recreate-mv-daily-category-stat-workspace.yaml @@ -0,0 +1,60 @@ +databaseChangeLog: + - changeSet: + id: recreate-mv-daily-category-stat-workspace + author: hptrk + comment: > + Drop and recreate mv_daily_category_stat with workspace_id replacing user_id. + All statistics queries now isolate data by workspace instead of by user. + dbms: postgresql + changes: + - sqlFile: + splitStatements: false + path: sql/recreate-mv-daily-category-stat-workspace.sql + relativeToChangelogFile: true + rollback: + - sql: + sql: DROP MATERIALIZED VIEW IF EXISTS mv_daily_category_stat + + - changeSet: + id: create-mv-daily-category-stat-workspace-unique-index + author: hptrk + comment: Unique index required for REFRESH MATERIALIZED VIEW CONCURRENTLY + dbms: postgresql + changes: + - createIndex: + indexName: idx_mv_daily_cat_stat_unique + tableName: mv_daily_category_stat + unique: true + columns: + - column: + name: workspace_id + - column: + name: stat_date + - column: + name: category_id + - column: + name: type + rollback: + - dropIndex: + indexName: idx_mv_daily_cat_stat_unique + tableName: mv_daily_category_stat + + - changeSet: + id: create-mv-daily-category-stat-workspace-lookup-index + author: hptrk + comment: Composite index for fast workspace + date range lookups on the materialized view + dbms: postgresql + changes: + - createIndex: + indexName: idx_mv_daily_cat_stat_workspace_date + tableName: mv_daily_category_stat + columns: + - column: + name: workspace_id + - column: + name: stat_date + rollback: + - dropIndex: + indexName: idx_mv_daily_cat_stat_workspace_date + tableName: mv_daily_category_stat + diff --git a/backend/exence/src/main/resources/db/changelog/v1.5.0/sql/recreate-mv-daily-category-stat-workspace.sql b/backend/exence/src/main/resources/db/changelog/v1.5.0/sql/recreate-mv-daily-category-stat-workspace.sql new file mode 100644 index 00000000..7349906a --- /dev/null +++ b/backend/exence/src/main/resources/db/changelog/v1.5.0/sql/recreate-mv-daily-category-stat-workspace.sql @@ -0,0 +1,16 @@ +CREATE MATERIALIZED VIEW mv_daily_category_stat AS +SELECT + t.workspace_id, + t.date AS stat_date, + t.category_id, + t.type, + c.name AS category_name, + c.color AS category_color, + CAST(c.icon AS TEXT) AS category_icon, + SUM(t.amount) AS total_amount, + COUNT(t.id) AS transaction_count, + MAX(t.amount) AS max_amount +FROM transaction t +JOIN category c ON t.category_id = c.id +GROUP BY t.workspace_id, t.date, t.category_id, t.type, c.name, c.color, c.icon +WITH DATA; diff --git a/backend/exence/src/main/resources/messages.properties b/backend/exence/src/main/resources/messages.properties index 57f697c5..9c458e1c 100644 --- a/backend/exence/src/main/resources/messages.properties +++ b/backend/exence/src/main/resources/messages.properties @@ -257,6 +257,20 @@ label.investment.assets=Assets label.investment.total-value=Total Invested Value label.investment.asset-count=Asset Count +# Workspace error messages +error.workspace-not-found.title=Workspace Not Found +error.workspace-not-found=You are not a member of this workspace. +error.workspace-cannot-delete-last.title=Cannot Delete Last Workspace +error.workspace-cannot-delete-last=You cannot delete your only workspace. Create or join another workspace first. +error.workspace-owner-cannot-leave.title=Cannot Leave Workspace +error.workspace-owner-cannot-leave=The workspace owner cannot leave. Transfer ownership first. +error.workspace-owner-cannot-be-removed.title=Cannot Remove Owner +error.workspace-owner-cannot-be-removed=The workspace owner cannot be removed from the workspace. +error.workspace-header-missing.title=Missing Workspace Header +error.workspace-header-missing=Workspace ID header (X-Workspace-ID) is required. +error.workspace-member-already-exists.title=Member Already Exists +error.workspace-member-already-exists=This user is already a member of the workspace. + # Achievement error messages error.achievement-not-found.title=Achievement Not Found error.achievement-not-found=The requested achievement could not be found. diff --git a/backend/exence/src/main/resources/messages_de.properties b/backend/exence/src/main/resources/messages_de.properties index 4a861b12..ad2982ef 100644 --- a/backend/exence/src/main/resources/messages_de.properties +++ b/backend/exence/src/main/resources/messages_de.properties @@ -310,3 +310,17 @@ achievement.app_streak.silver.name=Monatsdisziplin achievement.app_streak.silver.description=Erfasse Transaktionen jeden Tag für 30 aufeinanderfolgende Tage. achievement.app_streak.gold.name=Unaufhaltbar achievement.app_streak.gold.description=Erfasse Transaktionen jeden Tag für 90 aufeinanderfolgende Tage. + +# Workspace error messages +error.workspace-not-found.title=Workspace Not Found +error.workspace-not-found=You are not a member of this workspace. +error.workspace-cannot-delete-last.title=Cannot Delete Last Workspace +error.workspace-cannot-delete-last=You cannot delete your only workspace. Create or join another workspace first. +error.workspace-owner-cannot-leave.title=Cannot Leave Workspace +error.workspace-owner-cannot-leave=The workspace owner cannot leave. Transfer ownership first. +error.workspace-owner-cannot-be-removed.title=Cannot Remove Owner +error.workspace-owner-cannot-be-removed=The workspace owner cannot be removed from the workspace. +error.workspace-header-missing.title=Missing Workspace Header +error.workspace-header-missing=Workspace ID header (X-Workspace-ID) is required. +error.workspace-member-already-exists.title=Member Already Exists +error.workspace-member-already-exists=This user is already a member of the workspace. diff --git a/backend/exence/src/main/resources/messages_es.properties b/backend/exence/src/main/resources/messages_es.properties index 30b046e9..e85350ba 100644 --- a/backend/exence/src/main/resources/messages_es.properties +++ b/backend/exence/src/main/resources/messages_es.properties @@ -310,3 +310,17 @@ achievement.app_streak.silver.name=Disciplina mensual achievement.app_streak.silver.description=Registra transacciones cada día durante 30 días consecutivos. achievement.app_streak.gold.name=Imparable achievement.app_streak.gold.description=Registra transacciones cada día durante 90 días consecutivos. + +# Workspace error messages +error.workspace-not-found.title=Workspace Not Found +error.workspace-not-found=You are not a member of this workspace. +error.workspace-cannot-delete-last.title=Cannot Delete Last Workspace +error.workspace-cannot-delete-last=You cannot delete your only workspace. Create or join another workspace first. +error.workspace-owner-cannot-leave.title=Cannot Leave Workspace +error.workspace-owner-cannot-leave=The workspace owner cannot leave. Transfer ownership first. +error.workspace-owner-cannot-be-removed.title=Cannot Remove Owner +error.workspace-owner-cannot-be-removed=The workspace owner cannot be removed from the workspace. +error.workspace-header-missing.title=Missing Workspace Header +error.workspace-header-missing=Workspace ID header (X-Workspace-ID) is required. +error.workspace-member-already-exists.title=Member Already Exists +error.workspace-member-already-exists=This user is already a member of the workspace. diff --git a/backend/exence/src/main/resources/messages_fr.properties b/backend/exence/src/main/resources/messages_fr.properties index b63b5d77..bcdc4402 100644 --- a/backend/exence/src/main/resources/messages_fr.properties +++ b/backend/exence/src/main/resources/messages_fr.properties @@ -310,3 +310,17 @@ achievement.app_streak.silver.name=Discipline mensuelle achievement.app_streak.silver.description=Enregistrez des transactions chaque jour pendant 30 jours consécutifs. achievement.app_streak.gold.name=Inarrêtable achievement.app_streak.gold.description=Enregistrez des transactions chaque jour pendant 90 jours consécutifs. + +# Workspace error messages +error.workspace-not-found.title=Workspace Not Found +error.workspace-not-found=You are not a member of this workspace. +error.workspace-cannot-delete-last.title=Cannot Delete Last Workspace +error.workspace-cannot-delete-last=You cannot delete your only workspace. Create or join another workspace first. +error.workspace-owner-cannot-leave.title=Cannot Leave Workspace +error.workspace-owner-cannot-leave=The workspace owner cannot leave. Transfer ownership first. +error.workspace-owner-cannot-be-removed.title=Cannot Remove Owner +error.workspace-owner-cannot-be-removed=The workspace owner cannot be removed from the workspace. +error.workspace-header-missing.title=Missing Workspace Header +error.workspace-header-missing=Workspace ID header (X-Workspace-ID) is required. +error.workspace-member-already-exists.title=Member Already Exists +error.workspace-member-already-exists=This user is already a member of the workspace. diff --git a/backend/exence/src/main/resources/messages_hu.properties b/backend/exence/src/main/resources/messages_hu.properties index 6e8ffbd3..82d8d06d 100644 --- a/backend/exence/src/main/resources/messages_hu.properties +++ b/backend/exence/src/main/resources/messages_hu.properties @@ -311,3 +311,17 @@ achievement.app_streak.silver.name=Havi fegyelem achievement.app_streak.silver.description=Rögzíts tranzakciókat minden nap 30 egymást követő napon. achievement.app_streak.gold.name=Megállíthatatlan achievement.app_streak.gold.description=Rögzíts tranzakciókat minden nap 90 egymást követő napon. + +# Workspace error messages +error.workspace-not-found.title=Workspace Not Found +error.workspace-not-found=You are not a member of this workspace. +error.workspace-cannot-delete-last.title=Cannot Delete Last Workspace +error.workspace-cannot-delete-last=You cannot delete your only workspace. Create or join another workspace first. +error.workspace-owner-cannot-leave.title=Cannot Leave Workspace +error.workspace-owner-cannot-leave=The workspace owner cannot leave. Transfer ownership first. +error.workspace-owner-cannot-be-removed.title=Cannot Remove Owner +error.workspace-owner-cannot-be-removed=The workspace owner cannot be removed from the workspace. +error.workspace-header-missing.title=Missing Workspace Header +error.workspace-header-missing=Workspace ID header (X-Workspace-ID) is required. +error.workspace-member-already-exists.title=Member Already Exists +error.workspace-member-already-exists=This user is already a member of the workspace. diff --git a/backend/exence/src/main/resources/messages_it.properties b/backend/exence/src/main/resources/messages_it.properties index 92f5e060..66b100f8 100644 --- a/backend/exence/src/main/resources/messages_it.properties +++ b/backend/exence/src/main/resources/messages_it.properties @@ -311,3 +311,17 @@ achievement.app_streak.silver.name=Disciplina mensile achievement.app_streak.silver.description=Registra transazioni ogni giorno per 30 giorni consecutivi. achievement.app_streak.gold.name=Inarrestabile achievement.app_streak.gold.description=Registra transazioni ogni giorno per 90 giorni consecutivi. + +# Workspace error messages +error.workspace-not-found.title=Workspace Not Found +error.workspace-not-found=You are not a member of this workspace. +error.workspace-cannot-delete-last.title=Cannot Delete Last Workspace +error.workspace-cannot-delete-last=You cannot delete your only workspace. Create or join another workspace first. +error.workspace-owner-cannot-leave.title=Cannot Leave Workspace +error.workspace-owner-cannot-leave=The workspace owner cannot leave. Transfer ownership first. +error.workspace-owner-cannot-be-removed.title=Cannot Remove Owner +error.workspace-owner-cannot-be-removed=The workspace owner cannot be removed from the workspace. +error.workspace-header-missing.title=Missing Workspace Header +error.workspace-header-missing=Workspace ID header (X-Workspace-ID) is required. +error.workspace-member-already-exists.title=Member Already Exists +error.workspace-member-already-exists=This user is already a member of the workspace. diff --git a/backend/exence/src/main/resources/messages_pl.properties b/backend/exence/src/main/resources/messages_pl.properties index 08884196..f5601cc1 100644 --- a/backend/exence/src/main/resources/messages_pl.properties +++ b/backend/exence/src/main/resources/messages_pl.properties @@ -310,3 +310,17 @@ achievement.app_streak.silver.name=Miesięczna dyscyplina achievement.app_streak.silver.description=Rejestruj transakcje każdego dnia przez 30 kolejnych dni. achievement.app_streak.gold.name=Niepohamowany achievement.app_streak.gold.description=Rejestruj transakcje każdego dnia przez 90 kolejnych dni. + +# Workspace error messages +error.workspace-not-found.title=Workspace Not Found +error.workspace-not-found=You are not a member of this workspace. +error.workspace-cannot-delete-last.title=Cannot Delete Last Workspace +error.workspace-cannot-delete-last=You cannot delete your only workspace. Create or join another workspace first. +error.workspace-owner-cannot-leave.title=Cannot Leave Workspace +error.workspace-owner-cannot-leave=The workspace owner cannot leave. Transfer ownership first. +error.workspace-owner-cannot-be-removed.title=Cannot Remove Owner +error.workspace-owner-cannot-be-removed=The workspace owner cannot be removed from the workspace. +error.workspace-header-missing.title=Missing Workspace Header +error.workspace-header-missing=Workspace ID header (X-Workspace-ID) is required. +error.workspace-member-already-exists.title=Member Already Exists +error.workspace-member-already-exists=This user is already a member of the workspace. diff --git a/backend/exence/src/main/resources/messages_sk.properties b/backend/exence/src/main/resources/messages_sk.properties index 234dd183..c10beeb3 100644 --- a/backend/exence/src/main/resources/messages_sk.properties +++ b/backend/exence/src/main/resources/messages_sk.properties @@ -310,3 +310,17 @@ achievement.app_streak.silver.name=Mesačná disciplína achievement.app_streak.silver.description=Zaznamenaj transakcie každý deň počas 30 po sebe nasledujúcich dní. achievement.app_streak.gold.name=Nezastaviteľný achievement.app_streak.gold.description=Zaznamenaj transakcie každý deň počas 90 po sebe nasledujúcich dní. + +# Workspace error messages +error.workspace-not-found.title=Workspace Not Found +error.workspace-not-found=You are not a member of this workspace. +error.workspace-cannot-delete-last.title=Cannot Delete Last Workspace +error.workspace-cannot-delete-last=You cannot delete your only workspace. Create or join another workspace first. +error.workspace-owner-cannot-leave.title=Cannot Leave Workspace +error.workspace-owner-cannot-leave=The workspace owner cannot leave. Transfer ownership first. +error.workspace-owner-cannot-be-removed.title=Cannot Remove Owner +error.workspace-owner-cannot-be-removed=The workspace owner cannot be removed from the workspace. +error.workspace-header-missing.title=Missing Workspace Header +error.workspace-header-missing=Workspace ID header (X-Workspace-ID) is required. +error.workspace-member-already-exists.title=Member Already Exists +error.workspace-member-already-exists=This user is already a member of the workspace. diff --git a/backend/exence/src/test/java/com/exence/finance/modules/workspace/service/impl/WorkspaceServiceImplTest.java b/backend/exence/src/test/java/com/exence/finance/modules/workspace/service/impl/WorkspaceServiceImplTest.java new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/backend/exence/src/test/java/com/exence/finance/modules/workspace/service/impl/WorkspaceServiceImplTest.java @@ -0,0 +1 @@ + diff --git a/backend/exence/src/test/java/com/exence/finance/validators/EmailDomainValidatorTest.java b/backend/exence/src/test/java/com/exence/finance/validators/EmailDomainValidatorTest.java index 589a5104..31ed7625 100644 --- a/backend/exence/src/test/java/com/exence/finance/validators/EmailDomainValidatorTest.java +++ b/backend/exence/src/test/java/com/exence/finance/validators/EmailDomainValidatorTest.java @@ -6,7 +6,8 @@ import static org.mockito.Mockito.lenient; import com.exence.finance.common.validators.EmailDomainValidator; -import com.exence.finance.config.properties.EmailBusinessProperties; +import com.exence.finance.modules.systemsettings.entity.SystemSettings; +import com.exence.finance.modules.systemsettings.service.SystemSettingsService; import jakarta.validation.ConstraintValidatorContext; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -25,14 +26,16 @@ public class EmailDomainValidatorTest { private ConstraintValidatorContext.ConstraintViolationBuilder builder; @Mock - private EmailBusinessProperties emailBusinessProperties; + private SystemSettingsService systemSettingsService; @InjectMocks private EmailDomainValidator validator; @BeforeEach void setUp() { - lenient().when(emailBusinessProperties.domainWhitelistOnly()).thenReturn(false); + SystemSettings settings = + SystemSettings.builder().domainWhitelistOnly(false).build(); + lenient().when(systemSettingsService.getSettings()).thenReturn(settings); lenient() .when(context.buildConstraintViolationWithTemplate(anyString()))