feat(domain): allocation rules become a dated series
Post.standingRule becomes Post.rules: RuleVersion[], resolved by ruleAt() as the last version effective at or before a month. Per-month overrides still win outright; a post with no applicable version allocates zero rather than applying its earliest rule backwards. allocationFor keeps its signature, so the fold, the views and the ODS export are untouched. Settings gets a read-only rule summary for now; the history editor follows.
This commit is contained in:
1 parent
c74a66aea9
commit
68712e72a3
11 files changed
+252
-151
No files matched your search
@@ -77,34 +77,16 @@ describe("months", () => {
|
||||
describe("posts", () => {
|
||||
test("addPost appends with the next order value", () => {
|
||||
const data = draft();
|
||||
const post = actions.addPost(data, "Travel", "EUR", {
|
||||
kind: "percentOfIncome",
|
||||
percent: 5,
|
||||
});
|
||||
const post = actions.addPost(data, "Travel", "EUR");
|
||||
expect(post.order).toBe(3);
|
||||
expect(post.archived).toBe(false);
|
||||
expect(data.posts).toHaveLength(4);
|
||||
});
|
||||
|
||||
test("addPost rounds a fixed standing rule's amount and a percent's percent", () => {
|
||||
test("addPost starts the post unbudgeted", () => {
|
||||
const data = draft();
|
||||
const fixedPost = actions.addPost(data, "Rent", "DKK", {
|
||||
kind: "fixed",
|
||||
amount: { amount: 12.345, currency: "DKK" },
|
||||
});
|
||||
expect(fixedPost.standingRule).toEqual({
|
||||
kind: "fixed",
|
||||
amount: { amount: 12.35, currency: "DKK" },
|
||||
});
|
||||
|
||||
const percentPost = actions.addPost(data, "Travel", "EUR", {
|
||||
kind: "percentOfIncome",
|
||||
percent: 12.3456,
|
||||
});
|
||||
expect(percentPost.standingRule).toEqual({
|
||||
kind: "percentOfIncome",
|
||||
percent: 12.35,
|
||||
});
|
||||
const post = actions.addPost(data, "Travel", "EUR");
|
||||
expect(post.rules).toEqual([]);
|
||||
});
|
||||
|
||||
test("setPostArchived toggles without deleting", () => {
|
||||
@@ -140,26 +122,6 @@ describe("posts", () => {
|
||||
expect(post.currency).toBe("DKK");
|
||||
});
|
||||
|
||||
test("updatePost rounds a fixed standing rule's amount and a percent's percent", () => {
|
||||
const data = draft();
|
||||
const postId = data.posts[0]!.id;
|
||||
actions.updatePost(data, postId, {
|
||||
standingRule: { kind: "fixed", amount: { amount: 12.345, currency: "DKK" } },
|
||||
});
|
||||
expect(data.posts.find((p) => p.id === postId)!.standingRule).toEqual({
|
||||
kind: "fixed",
|
||||
amount: { amount: 12.35, currency: "DKK" },
|
||||
});
|
||||
|
||||
actions.updatePost(data, postId, {
|
||||
standingRule: { kind: "percentOfIncome", percent: 12.3456 },
|
||||
});
|
||||
expect(data.posts.find((p) => p.id === postId)!.standingRule).toEqual({
|
||||
kind: "percentOfIncome",
|
||||
percent: 12.35,
|
||||
});
|
||||
});
|
||||
|
||||
test("an unknown post id throws", () => {
|
||||
expect(() => actions.updatePost(draft(), "ghost", { name: "x" })).toThrow(/ghost/);
|
||||
});
|
||||
|
||||
+2
-10
@@ -102,19 +102,14 @@ export function setRuleOverride(
|
||||
month.ruleOverrides[postId] = roundRule(rule);
|
||||
}
|
||||
|
||||
export function addPost(
|
||||
draft: Dataset,
|
||||
name: string,
|
||||
currency: Currency,
|
||||
standingRule: Rule,
|
||||
): Post {
|
||||
export function addPost(draft: Dataset, name: string, currency: Currency): Post {
|
||||
const post: Post = {
|
||||
id: newId(),
|
||||
name,
|
||||
order: draft.posts.length,
|
||||
archived: false,
|
||||
currency,
|
||||
standingRule: roundRule(standingRule),
|
||||
rules: [],
|
||||
};
|
||||
draft.posts.push(post);
|
||||
return post;
|
||||
@@ -127,9 +122,6 @@ export function updatePost(
|
||||
): void {
|
||||
const post = requirePost(draft, postId);
|
||||
const resolved: Partial<Omit<Post, "id">> = { ...changes };
|
||||
if (changes.standingRule) {
|
||||
resolved.standingRule = roundRule(changes.standingRule);
|
||||
}
|
||||
Object.assign(post, resolved);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user