Clear transaction categories on re-apply of categorization rules

This commit is contained in:
Miroslav Vasilev 2023-12-30 18:59:44 +02:00
parent 76a658986b
commit 3653dc5861
6 changed files with 31 additions and 67 deletions

View file

@ -0,0 +1,10 @@
package dev.mvvasilev.finances.controllers;
import org.springframework.web.bind.annotation.RestController;
@RestController("/statistics")
public class StatisticsController {
}

View file

@ -3,8 +3,23 @@ package dev.mvvasilev.finances.persistence;
import dev.mvvasilev.finances.entity.ProcessedTransaction;
import dev.mvvasilev.finances.entity.ProcessedTransactionCategory;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.stream.Stream;
@Repository
public interface ProcessedTransactionCategoryRepository extends JpaRepository<ProcessedTransactionCategory, Long> {
@Query(
value="""
DELETE FROM categories.processed_transaction_category
WHERE processed_transaction_id IN (:transactionIds)
""",
nativeQuery = true
)
@Modifying
void deleteAllForTransactions(@Param("transactionIds") Collection<Long> transactionIds);
}

View file

@ -80,6 +80,8 @@ public class CategoryService {
final var categorizations = categorizationRepository.fetchForUser(userId);
final var transactions = processedTransactionRepository.fetchForUser(userId);
processedTransactionCategoryRepository.deleteAllForTransactions(transactions.stream().map(AbstractEntity::getId).toList());
// Run each category's rules for all transactions in parallel to eachother
final var futures = categorizations.stream()
.collect(Collectors.groupingBy(Categorization::getCategoryId, HashMap::new, Collectors.toList()))

View file

@ -11,14 +11,12 @@ import Grid from "@mui/material/Unstable_Grid2";
import Button from "@mui/material/Button";
import Divider from "@mui/material/Divider";
import {
Chip,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
Modal,
Stack,
TextField
} from "@mui/material";
import Box from "@mui/material/Box";
@ -188,39 +186,6 @@ export default function CategoriesPage() {
}}
showDelete
/>
{/*<Stack*/}
{/* sx={{*/}
{/* overflowY: "scroll"*/}
{/* }}*/}
{/* minHeight={"100px"}*/}
{/* maxHeight={"250px"}*/}
{/* useFlexGap*/}
{/* flexWrap="wrap"*/}
{/* direction={"row"}*/}
{/* spacing={1}*/}
{/*>*/}
{/* {*/}
{/* categories.map(c => {*/}
{/* let variant = (selectedCategory?.id ?? -1) === c.id ? "filled" : "outlined";*/}
{/* return (*/}
{/* <Chip*/}
{/* key={c.id}*/}
{/* onClick={(e) => {*/}
{/* setSelectedCategory({...c});*/}
{/* }}*/}
{/* onDelete={() => {*/}
{/* setSelectedCategory(c);*/}
{/* openConfirmDeleteCategoryModal(true);*/}
{/* }}*/}
{/* label={c.name}*/}
{/* deleteIcon={<Delete/>}*/}
{/* variant={variant}*/}
{/* />*/}
{/* );*/}
{/* })*/}
{/* }*/}
{/*</Stack>*/}
</Grid>
<Grid xs={12} lg={12}>

View file

@ -12,6 +12,8 @@ export default function CategoriesBox({
minHeight: minHeight = "100px",
maxHeight: maxHeight = "250px",
}) {
let areChipsDeletable = onCategoryDelete !== undefined;
return (
<Stack
sx={{
@ -28,12 +30,11 @@ export default function CategoriesBox({
{
categories.map(c => {
let variant = selectable && (selected?.id ?? -1) === c.id ? "filled" : "outlined";
let isDeletable = onCategoryDelete !== undefined;
return (
<>
{
isDeletable &&
areChipsDeletable &&
<Chip
key={c.id}
onClick={(e) => onCategorySelect(e, c)}
@ -44,7 +45,7 @@ export default function CategoriesBox({
/>
}
{
!isDeletable &&
!areChipsDeletable &&
<Chip
key={c.id}
onClick={(e) => onCategorySelect(e, c)}

View file

@ -1,29 +0,0 @@
import {useRef, useEffect, useState} from "react";
import { Network } from "vis-network";
export default function VisNetwork({ nodes: nodes = [], edges: edges = [], backgroundColor: backgroundColor = "#ffffff", options: options = {} }) {
const visJsRef = useRef(null);
const [network, setNetwork] = useState();
useEffect(() => {
const network = visJsRef.current && new Network(visJsRef.current, { nodes, edges }, options);
network.on("beforeDrawing", function(ctx) {
// save current translate/zoom
ctx.save();
// reset transform to identity
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height)
// restore old transform
ctx.restore();
})
}, [visJsRef, backgroundColor, edges, nodes, options]);
return <div ref={visJsRef} />;
}