fix: check category parents and repair orphan categories (#393) #472
2 changed files with 25 additions and 4 deletions
|
|
@ -172,6 +172,23 @@ describe("useCategories — « Vérifier la hiérarchie » (#393)", () => {
|
||||||
expect(state.isSaving).toBe(false);
|
expect(state.isSaving).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("reloads the tree even when the check after a committed reattachment fails", async () => {
|
||||||
|
vi.mocked(findOrphanCategories)
|
||||||
|
.mockResolvedValueOnce([CYCLE])
|
||||||
|
.mockRejectedValueOnce(new Error("database is locked"));
|
||||||
|
vi.mocked(reattachCategory).mockResolvedValue(2);
|
||||||
|
let api = await mount();
|
||||||
|
await api.checkHierarchy();
|
||||||
|
api = harness.render(useCategories);
|
||||||
|
await api.reattachOrphan(CYCLE, null);
|
||||||
|
expect(reattachCategory).toHaveBeenCalledWith(3, null);
|
||||||
|
expect(logInfo).toHaveBeenCalledTimes(1);
|
||||||
|
expect(getAllCategoriesWithCounts).toHaveBeenCalledTimes(2);
|
||||||
|
const { state } = harness.render(useCategories);
|
||||||
|
expect(state.hierarchyCheck?.error).toEqual({ message: "database is locked" });
|
||||||
|
expect(state.isSaving).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
it("shows a refused reattachment in the window by its translated code, with no Journal line", async () => {
|
it("shows a refused reattachment in the window by its translated code, with no Journal line", async () => {
|
||||||
vi.mocked(findOrphanCategories).mockResolvedValue([CYCLE]);
|
vi.mocked(findOrphanCategories).mockResolvedValue([CYCLE]);
|
||||||
vi.mocked(reattachCategory).mockRejectedValue(new CategoryHierarchyError("parent_has_transactions"));
|
vi.mocked(reattachCategory).mockRejectedValue(new CategoryHierarchyError("parent_has_transactions"));
|
||||||
|
|
|
||||||
|
|
@ -417,7 +417,8 @@ export function useCategories() {
|
||||||
/**
|
/**
|
||||||
* Reattaches an orphan under `parentId`, or to the root with `null` (#393).
|
* Reattaches an orphan under `parentId`, or to the root with `null` (#393).
|
||||||
* On success: one Journal line (counts, no name), then the orphan list and
|
* On success: one Journal line (counts, no name), then the orphan list and
|
||||||
* the tree reload. A refusal shows in the window, by its translated code.
|
* the tree reload; the tree reloads even if the new check fails, since the
|
||||||
|
* write is committed. A refusal shows in the window, by its translated code.
|
||||||
*/
|
*/
|
||||||
const reattachOrphan = useCallback(
|
const reattachOrphan = useCallback(
|
||||||
async (orphan: OrphanCategory, parentId: number | null) => {
|
async (orphan: OrphanCategory, parentId: number | null) => {
|
||||||
|
|
@ -425,9 +426,12 @@ export function useCategories() {
|
||||||
try {
|
try {
|
||||||
const restored = await reattachCategory(orphan.id, parentId);
|
const restored = await reattachCategory(orphan.id, parentId);
|
||||||
logInfo(reattachLogLine(orphan.reason, restored));
|
logInfo(reattachLogLine(orphan.reason, restored));
|
||||||
|
try {
|
||||||
const orphans = await findOrphanCategories();
|
const orphans = await findOrphanCategories();
|
||||||
dispatch({ type: "SET_ORPHANS", payload: orphans });
|
dispatch({ type: "SET_ORPHANS", payload: orphans });
|
||||||
|
} finally {
|
||||||
await loadCategories();
|
await loadCategories();
|
||||||
|
}
|
||||||
dispatch({ type: "SET_SAVING", payload: false });
|
dispatch({ type: "SET_SAVING", payload: false });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dispatch({ type: "SET_HIERARCHY_ERROR", payload: categoriesErrorOf(e) });
|
dispatch({ type: "SET_HIERARCHY_ERROR", payload: categoriesErrorOf(e) });
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue