@sneat/extension-budgetus-contract 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,99 +1,128 @@
1
- function getLiabilitiesByPeriod(liabilitiesMode, recurringHappenings, space) {
2
- const byPeriod = {};
3
- Object.entries(recurringHappenings).forEach((entry) => {
4
- const [id, brief] = entry;
5
- processHappening(liabilitiesMode, space, byPeriod, { id, brief });
6
- });
7
- return byPeriod;
1
+ import { InjectionToken } from '@angular/core';
2
+
3
+ var ListPage;
4
+ (function (ListPage) {
5
+ ListPage["list"] = "list";
6
+ })(ListPage || (ListPage = {}));
7
+
8
+ class ListItemInfoModel {
9
+ static trackBy = (index, item) => !item
10
+ ? index
11
+ : (!!item.id && `id:${item.id}`) ||
12
+ (item.subListId && `subList:${item.subListId}`) ||
13
+ item.title;
14
+ }
15
+ class ListItemModel {
16
+ static equalListItems(...items) {
17
+ const { id, title, subListId, category, subListType } = items[0];
18
+ return !items.some((item) => {
19
+ if (id) {
20
+ return item.id !== id;
21
+ }
22
+ return ((!!title && item.title !== title) ||
23
+ (!!subListId && item.subListId !== subListId) ||
24
+ (!!category && item.category !== category) ||
25
+ (!!subListType && item.subListType !== subListType));
26
+ });
27
+ }
8
28
  }
9
- function processHappening(liabilitiesMode, space, byPeriod, happening) {
10
- // console.log('budget.processHappening()', happening);
11
- Object.entries(happening.brief.slots || {}).forEach(([slotID, slot]) => {
12
- if (slot.repeats === 'weekly' || slot.repeats === 'monthly') {
13
- processSlot(liabilitiesMode, space, byPeriod, happening, slotID, slot);
14
- }
15
- });
29
+ function getListShortUrlId(communeId, shortId, id) {
30
+ if (shortId) {
31
+ return `${communeId}-${shortId}`;
32
+ }
33
+ if (id) {
34
+ return id;
35
+ }
36
+ return undefined;
16
37
  }
17
- function processSlot(liabilitiesMode, space, byPeriod, happening, slotID, slot) {
18
- let liabilities = byPeriod[slot.repeats] || {
19
- happenings: [],
20
- contacts: [],
38
+ function isListInfoMatchesListDto(i, l) {
39
+ return ((!!i.id && i.id === l.id) ||
40
+ (i.type === l.dbo?.type && !!i.shortId && i.shortId === l.dbo?.shortId));
41
+ }
42
+ function createListInfoFromDto(dto, shortId) {
43
+ if (!dto.title) {
44
+ throw new Error('!title');
45
+ }
46
+ const listInfo = {
47
+ type: dto.type,
48
+ title: dto.title,
21
49
  };
22
- const hLiabilityIndex = liabilities.happenings.findIndex((l) => l.happening.id === happening.id);
23
- let hLiability = hLiabilityIndex >= 0
24
- ? liabilities.happenings[hLiabilityIndex]
25
- : {
26
- happening: { ...happening, space },
27
- valuesByCurrency: {},
28
- };
29
- const prices = happening.brief.prices?.filter((p) => (liabilitiesMode === 'expenses'
30
- ? p.amount.value > 0
31
- : liabilitiesMode === 'incomes'
32
- ? p.amount.value < 0
33
- : true) &&
34
- (p.expenseQuantity || p.term)) || [];
35
- if (prices.length) {
36
- for (let priceIdx = 0; priceIdx < (prices.length || 0); priceIdx++) {
37
- const price = prices[priceIdx];
38
- hLiability = { ...hLiability, priceAmount: price.amount };
39
- hLiability = processPrice(hLiability, slot, price, liabilities);
40
- }
41
- if (hLiabilityIndex >= 0) {
42
- liabilities = {
43
- ...liabilities,
44
- happenings: liabilities.happenings.map((h) => h.happening.id == hLiability.happening.id ? hLiability : h),
45
- };
46
- }
47
- else {
48
- liabilities = {
49
- ...liabilities,
50
- happenings: [...liabilities.happenings, hLiability],
51
- };
52
- }
50
+ if (shortId) {
51
+ listInfo.shortId = shortId;
53
52
  }
54
- byPeriod[slot.repeats] = liabilities;
53
+ if (dto.items && dto.items.length) {
54
+ listInfo.itemsCount = dto.items.length;
55
+ }
56
+ if (dto.emoji) {
57
+ listInfo.emoji = dto.emoji;
58
+ }
59
+ if (dto.restrictions) {
60
+ listInfo.restrictions = dto.restrictions;
61
+ }
62
+ if (dto.commune) {
63
+ listInfo.space = dto.commune;
64
+ }
65
+ return listInfo;
55
66
  }
56
- function processPrice(happeningLiability, slot, price, liabilities) {
57
- if (slot.repeats === 'weekly' && slot.weekdays) {
58
- happeningLiability = { ...happeningLiability, times: slot.weekdays.length };
59
- for (let wdIdx = 0; wdIdx < (slot?.weekdays?.length || 0); wdIdx++) {
60
- let amountValue = happeningLiability.valuesByCurrency[price.amount.currency] || 0;
61
- amountValue += price.amount.value;
62
- happeningLiability = {
63
- ...happeningLiability,
64
- valuesByCurrency: {
65
- ...happeningLiability?.valuesByCurrency,
66
- [price.amount.currency]: amountValue,
67
- },
68
- };
69
- const happeningContacts = happeningLiability.happening.brief?.related?.['contactus']?.['contacts'] || {};
70
- Object.keys(happeningContacts).forEach((itemID) => {
71
- let contactLiability = liabilities.contacts.find((c) => c.contact.id == itemID);
72
- if (!contactLiability) {
73
- contactLiability = {
74
- contact: {
75
- id: itemID,
76
- space: happeningLiability.happening.space,
77
- },
78
- valuesByCurrency: {},
79
- };
80
- }
81
- contactLiability.valuesByCurrency[price.amount.currency] =
82
- (contactLiability.valuesByCurrency[price.amount.currency] || 0) +
83
- price.amount.value;
84
- liabilities = {
85
- ...liabilities,
86
- contacts: [...liabilities.contacts, contactLiability],
87
- };
88
- });
89
- }
67
+ // export function createListItemInfoFromListInfo(listInfo: IListInfo): IListItemBrief {
68
+ // return {
69
+ // id: listInfo.id || '',
70
+ // title: listInfo.title || '',
71
+ // subListType: listInfo.type,
72
+ // subListId: listInfo.id || `${listInfo.team && listInfo.team.id}-${listInfo.shortId}`,
73
+ // emoji: listInfo.emoji,
74
+ // img: listInfo.img,
75
+ // };
76
+ // }
77
+ // export function createListItemInfo(listItem: IListItemDto): IListItemBrief {
78
+ // const v: IListItemBrief = {
79
+ // id: listItem.id,
80
+ // title: listItem.title,
81
+ // };
82
+ // if (listItem.emoji) {
83
+ // v.emoji = listItem.emoji;
84
+ // }
85
+ // if (listItem.done) {
86
+ // v.done = true;
87
+ // }
88
+ // return v;
89
+ // }
90
+
91
+ // Budget tab read-model types (see backstage roadmap:
92
+ // docs/roadmaps/budget-tab-mvp.md, Section 3 "Data model").
93
+ //
94
+ // IBudgetLineItem is a COMPUTED projection, not a persisted record: it is
95
+ // derived from Assetus asset renewals + Calendarius happenings and re-derived
96
+ // on every read. Only per-line overrides (targetAmount / isSurprise) are
97
+ // persisted (see IBudgetOverridePatch below + the overrides store in
98
+ // @sneat/extension-budgetus).
99
+ function monthISOOf(dateISO) {
100
+ return dateISO.slice(0, 7);
101
+ }
102
+ // Surprise-hiding (Surpriseless mechanic — budget-tab-mvp.md Section 1 and
103
+ // Open Question 5). A gift line item flagged `isSurprise` must not reveal its
104
+ // real title to the person it is a surprise for.
105
+ //
106
+ // This prototype has no recipient-linking yet (Open Question 1 in the plan is
107
+ // still unresolved — there's no "this gift is for user X" edge to compare
108
+ // against the current viewer), so for now it masks every `isSurprise` line
109
+ // uniformly rather than per-viewer. `reveal: true` is a demo-only escape hatch
110
+ // the Budget page uses so a reviewer/owner can see the underlying data
111
+ // without needing a second signed-in user.
112
+ function maskSurpriseLineItems(items, options) {
113
+ if (options?.reveal) {
114
+ return items;
90
115
  }
91
- return happeningLiability;
116
+ return items.map((item) => item.isSurprise
117
+ ? { ...item, title: '🎁 Hidden surprise', sourceRef: undefined }
118
+ : item);
92
119
  }
93
120
 
121
+ const BUDGETUS_SERVICE = new InjectionToken('BudgetusService');
122
+
94
123
  /**
95
124
  * Generated bundle index. Do not edit.
96
125
  */
97
126
 
98
- export { getLiabilitiesByPeriod };
127
+ export { BUDGETUS_SERVICE, ListItemInfoModel, ListItemModel, ListPage, createListInfoFromDto, getListShortUrlId, isListInfoMatchesListDto, maskSurpriseLineItems, monthISOOf };
99
128
  //# sourceMappingURL=sneat-extension-budgetus-contract.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"sneat-extension-budgetus-contract.mjs","sources":["../../../../../../libs/extensions/budgetus/contract/src/lib/budget-calc-periods.ts","../../../../../../libs/extensions/budgetus/contract/src/sneat-extension-budgetus-contract.ts"],"sourcesContent":["import { IIdAndBrief } from '@sneat/core';\nimport {\n ICalendarHappeningBrief,\n IHappeningPrice,\n IHappeningSlot,\n} from '@sneat/extension-calendarius-contract';\nimport { ISpaceContext } from '@sneat/space-models';\nimport {\n IHappeningLiability,\n LiabilitiesByPeriod,\n IPeriodLiabilities,\n LiabilitiesMode,\n} from './budget-component-types';\n\nexport function getLiabilitiesByPeriod(\n liabilitiesMode: LiabilitiesMode,\n recurringHappenings: Record<string, ICalendarHappeningBrief>,\n space: ISpaceContext,\n): LiabilitiesByPeriod {\n const byPeriod: LiabilitiesByPeriod = {};\n\n Object.entries(recurringHappenings).forEach((entry) => {\n const [id, brief] = entry;\n processHappening(liabilitiesMode, space, byPeriod, { id, brief });\n });\n return byPeriod;\n}\n\nfunction processHappening(\n liabilitiesMode: LiabilitiesMode,\n space: ISpaceContext,\n byPeriod: LiabilitiesByPeriod,\n happening: IIdAndBrief<ICalendarHappeningBrief>,\n): void {\n // console.log('budget.processHappening()', happening);\n Object.entries(happening.brief.slots || {}).forEach(([slotID, slot]) => {\n if (slot.repeats === 'weekly' || slot.repeats === 'monthly') {\n processSlot(liabilitiesMode, space, byPeriod, happening, slotID, slot);\n }\n });\n}\n\nfunction processSlot(\n liabilitiesMode: LiabilitiesMode,\n space: ISpaceContext,\n byPeriod: LiabilitiesByPeriod,\n happening: IIdAndBrief<ICalendarHappeningBrief>,\n slotID: string,\n slot: IHappeningSlot,\n): void {\n let liabilities: IPeriodLiabilities = byPeriod[slot.repeats] || {\n happenings: [],\n contacts: [],\n };\n const hLiabilityIndex = liabilities.happenings.findIndex(\n (l) => l.happening.id === happening.id,\n );\n let hLiability: IHappeningLiability =\n hLiabilityIndex >= 0\n ? liabilities.happenings[hLiabilityIndex]\n : {\n happening: { ...happening, space },\n valuesByCurrency: {},\n };\n\n const prices =\n happening.brief.prices?.filter(\n (p) =>\n (liabilitiesMode === 'expenses'\n ? p.amount.value > 0\n : liabilitiesMode === 'incomes'\n ? p.amount.value < 0\n : true) &&\n (p.expenseQuantity || p.term),\n ) || [];\n\n if (prices.length) {\n for (let priceIdx = 0; priceIdx < (prices.length || 0); priceIdx++) {\n const price = prices[priceIdx];\n hLiability = { ...hLiability, priceAmount: price.amount };\n hLiability = processPrice(hLiability, slot, price, liabilities);\n }\n if (hLiabilityIndex >= 0) {\n liabilities = {\n ...liabilities,\n happenings: liabilities.happenings.map((h) =>\n h.happening.id == hLiability.happening.id ? hLiability : h,\n ),\n };\n } else {\n liabilities = {\n ...liabilities,\n happenings: [...liabilities.happenings, hLiability],\n };\n }\n }\n byPeriod[slot.repeats] = liabilities;\n}\n\nfunction processPrice(\n happeningLiability: IHappeningLiability,\n slot: IHappeningSlot,\n price: IHappeningPrice,\n liabilities: IPeriodLiabilities,\n): IHappeningLiability {\n if (slot.repeats === 'weekly' && slot.weekdays) {\n happeningLiability = { ...happeningLiability, times: slot.weekdays.length };\n for (let wdIdx = 0; wdIdx < (slot?.weekdays?.length || 0); wdIdx++) {\n let amountValue: number =\n happeningLiability.valuesByCurrency[price.amount.currency] || 0;\n amountValue += price.amount.value;\n happeningLiability = {\n ...happeningLiability,\n valuesByCurrency: {\n ...happeningLiability?.valuesByCurrency,\n [price.amount.currency]: amountValue,\n },\n };\n const happeningContacts =\n happeningLiability.happening.brief?.related?.['contactus']?.[\n 'contacts'\n ] || {};\n Object.keys(happeningContacts).forEach((itemID) => {\n let contactLiability = liabilities.contacts.find(\n (c) => c.contact.id == itemID,\n );\n if (!contactLiability) {\n contactLiability = {\n contact: {\n id: itemID,\n space: happeningLiability.happening.space,\n },\n valuesByCurrency: {},\n };\n }\n contactLiability.valuesByCurrency[price.amount.currency] =\n (contactLiability.valuesByCurrency[price.amount.currency] || 0) +\n price.amount.value;\n liabilities = {\n ...liabilities,\n contacts: [...liabilities.contacts, contactLiability],\n };\n });\n }\n }\n return happeningLiability;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sneat-extension-budgetus-contract.mjs","sources":["../../../../../../libs/extensions/budgetus/contract/src/constants.ts","../../../../../../libs/extensions/budgetus/contract/src/dto/list.ts","../../../../../../libs/extensions/budgetus/contract/src/dto/budget.ts","../../../../../../libs/extensions/budgetus/contract/src/services/budgetus-service.ts","../../../../../../libs/extensions/budgetus/contract/src/sneat-extension-budgetus-contract.ts"],"sourcesContent":["import { EnumAsUnionOfKeys } from '@sneat/core';\n\nexport const enum ListPage {\n list = 'list',\n}\n\nexport type ListPages = EnumAsUnionOfKeys<typeof ListPage>;\n","import { IRecord } from '@sneat/data';\nimport {\n IShortSpaceInfo,\n IWithCreated,\n IWithRestrictions,\n IWithSpaceIDs,\n SneatRecordStatus,\n} from '@sneat/dto';\n\nexport type ListStatus = SneatRecordStatus;\n\nexport interface IQuantity {\n value: number;\n unit: string;\n}\n\nexport interface IListItemCommon extends IListCommon {\n subListId?: string;\n subListType?: ListType;\n quantity?: IQuantity;\n category?: string;\n}\n\nexport type IListItemBase = IListItemCommon;\n\nexport type ListItemStatus = 'done' | 'active';\n\nexport interface IListItemBrief extends IListItemBase {\n id: string;\n readonly created?: string; // UTC datetime\n readonly emoji?: string;\n readonly status?: ListItemStatus;\n readonly img?: string;\n}\n\nexport interface ListCounts {\n // TODO: Use some enumerator as IDB library does.\n active?: number;\n completed?: number;\n}\n\nexport type ListType =\n | 'buy'\n | 'watch'\n | 'cook'\n | 'do'\n | 'other'\n | 'recipes'\n | 'rsvp';\n\n// IListCommon is a common base class for a List & ListItem\nexport interface IListCommon {\n // Do not extend from IWithCreated as it is not applicable for ICreateListItemRequest\n title: string;\n img?: string;\n emoji?: string;\n isDone?: boolean;\n}\n\nexport interface IListBase extends IListCommon, IWithSpaceIDs {\n type: ListType;\n shortId?: string;\n status?: ListStatus;\n}\n\nexport interface IListDbo extends IListBase, IWithRestrictions, IWithCreated {\n dtClosed?: number;\n note?: string; // Is used for example for recipe text\n numberOf?: ListCounts;\n items?: IListItemBrief[];\n commune?: IShortSpaceInfo; // Used just for in-memory columns?\n}\n\nexport class ListItemInfoModel {\n static trackBy: (\n index: number,\n item: IListItemBrief,\n ) => string | number | undefined = (index, item) =>\n !item\n ? index\n : (!!item.id && `id:${item.id}`) ||\n (item.subListId && `subList:${item.subListId}`) ||\n item.title;\n}\n\nexport class ListItemModel {\n static equalListItems(...items: IListItemBrief[]): boolean {\n const { id, title, subListId, category, subListType } = items[0];\n return !items.some((item) => {\n if (id) {\n return item.id !== id;\n }\n return (\n (!!title && item.title !== title) ||\n (!!subListId && item.subListId !== subListId) ||\n (!!category && item.category !== category) ||\n (!!subListType && item.subListType !== subListType)\n );\n });\n }\n}\n\nexport interface IListItemDbo extends IListBase, IListItemCommon {\n listId?: string;\n score?: number;\n subListItems?: IListItemBrief[];\n}\n\nexport function getListShortUrlId(\n communeId: string,\n shortId?: string,\n id?: string,\n): string | undefined {\n if (shortId) {\n return `${communeId}-${shortId}`;\n }\n if (id) {\n return id;\n }\n return undefined;\n}\n\nexport interface IListInfo extends IWithRestrictions {\n parentListId?: string;\n parentListType?: ListType;\n type: ListType;\n id?: string;\n shortId?: string;\n title?: string;\n hidden?: boolean;\n space?: IShortSpaceInfo;\n emoji?: string;\n img?: string;\n note?: string;\n itemsCount?: number;\n}\n\nexport interface IListBrief extends IListBase, IWithCreated {\n emoji?: string;\n}\n\nexport function isListInfoMatchesListDto(\n i: IListInfo,\n l: IRecord<IListDbo>,\n): boolean {\n return (\n (!!i.id && i.id === l.id) ||\n (i.type === l.dbo?.type && !!i.shortId && i.shortId === l.dbo?.shortId)\n );\n}\n\nexport function createListInfoFromDto(\n dto: IListDbo,\n shortId?: string,\n): IListInfo {\n if (!dto.title) {\n throw new Error('!title');\n }\n const listInfo: IListInfo = {\n type: dto.type,\n title: dto.title,\n };\n if (shortId) {\n listInfo.shortId = shortId;\n }\n if (dto.items && dto.items.length) {\n listInfo.itemsCount = dto.items.length;\n }\n if (dto.emoji) {\n listInfo.emoji = dto.emoji;\n }\n if (dto.restrictions) {\n listInfo.restrictions = dto.restrictions;\n }\n if (dto.commune) {\n listInfo.space = dto.commune;\n }\n return listInfo;\n}\n\n// export function createListItemInfoFromListInfo(listInfo: IListInfo): IListItemBrief {\n// \treturn {\n// \t\tid: listInfo.id || '',\n// \t\ttitle: listInfo.title || '',\n// \t\tsubListType: listInfo.type,\n// \t\tsubListId: listInfo.id || `${listInfo.team && listInfo.team.id}-${listInfo.shortId}`,\n// \t\temoji: listInfo.emoji,\n// \t\timg: listInfo.img,\n// \t};\n// }\n\n// export function createListItemInfo(listItem: IListItemDto): IListItemBrief {\n// \tconst v: IListItemBrief = {\n// \t\tid: listItem.id,\n// \t\ttitle: listItem.title,\n// \t};\n// \tif (listItem.emoji) {\n// \t\tv.emoji = listItem.emoji;\n// \t}\n// \tif (listItem.done) {\n// \t\tv.done = true;\n// \t}\n// \treturn v;\n// }\n","// Budget tab read-model types (see backstage roadmap:\n// docs/roadmaps/budget-tab-mvp.md, Section 3 \"Data model\").\n//\n// IBudgetLineItem is a COMPUTED projection, not a persisted record: it is\n// derived from Assetus asset renewals + Calendarius happenings and re-derived\n// on every read. Only per-line overrides (targetAmount / isSurprise) are\n// persisted (see IBudgetOverridePatch below + the overrides store in\n// @sneat/extension-budgetus).\n\nexport interface IMoney {\n currency: string;\n value: number;\n}\n\n// Where a budget line item was derived from. 'gift' is a specialisation of\n// 'happening' — a yearly happening (birthday/anniversary) tagged as a gift\n// occasion, which is the flagship Surpriseless scenario.\nexport type BudgetLineSource = 'asset-renewal' | 'happening' | 'gift';\n\nexport interface IBudgetLineItem {\n id: string;\n title: string;\n dateISO: string; // ISO date (yyyy-mm-dd) of the next occurrence/due date\n amount: IMoney;\n source: BudgetLineSource;\n sourceRef?: string; // id of the source asset/happening, for drill-through\n targetAmount?: IMoney; // user-set override (esp. gift lines)\n isSurprise?: boolean; // Surpriseless \"surprise-hiding\" flag (gift lines)\n}\n\nexport interface IBudgetMonthGroup {\n monthISO: string; // 'YYYY-MM'\n total: IMoney;\n items: IBudgetLineItem[];\n}\n\nexport interface IBudgetRollup {\n byMonth: IBudgetMonthGroup[];\n annualTotal: IMoney;\n mostExpensiveMonthISO: string;\n}\n\n// The only fields a budgetus overrides record may patch onto a computed line\n// item. Kept separate from IBudgetLineItem so the wire/storage shape can't\n// accidentally include projection-only computed fields (title, amount, ...).\nexport interface IBudgetOverridePatch {\n targetAmount?: IMoney;\n isSurprise?: boolean;\n}\n\nexport function monthISOOf(dateISO: string): string {\n return dateISO.slice(0, 7);\n}\n\n// Surprise-hiding (Surpriseless mechanic — budget-tab-mvp.md Section 1 and\n// Open Question 5). A gift line item flagged `isSurprise` must not reveal its\n// real title to the person it is a surprise for.\n//\n// This prototype has no recipient-linking yet (Open Question 1 in the plan is\n// still unresolved — there's no \"this gift is for user X\" edge to compare\n// against the current viewer), so for now it masks every `isSurprise` line\n// uniformly rather than per-viewer. `reveal: true` is a demo-only escape hatch\n// the Budget page uses so a reviewer/owner can see the underlying data\n// without needing a second signed-in user.\nexport function maskSurpriseLineItems(\n items: IBudgetLineItem[],\n options?: { reveal?: boolean },\n): IBudgetLineItem[] {\n if (options?.reveal) {\n return items;\n }\n return items.map((item) =>\n item.isSurprise\n ? { ...item, title: '🎁 Hidden surprise', sourceRef: undefined }\n : item,\n );\n}\n","import { InjectionToken } from '@angular/core';\nimport { ISpaceContext } from '@sneat/space-models';\nimport { Observable } from 'rxjs';\nimport { IListContext } from '../contexts';\nimport { IBudgetOverridePatch, IBudgetRollup, ListType } from '../dto';\nimport {\n ICreateListRequest,\n IDeleteListItemsRequest,\n IListItemResult,\n IListItemsCommandParams,\n IReorderListItemsRequest,\n ISetListItemsIsComplete,\n} from './interfaces';\n\n// IBudgetusService is the runtime-light contract Budgetus pages and components\n// depend on. Members mirror the concrete ListService public surface used by the\n// UI; the implementation lives in the private runtime and is provided via the\n// BUDGETUS_SERVICE token below. The UI BaseListPage additionally needs the\n// inherited ModuleSpaceItemService surface, so it types the injected token as\n// an intersection with ModuleSpaceItemService<IListBrief, IListDbo>.\nexport interface IBudgetusService {\n createList(request: ICreateListRequest): Observable<IListContext>;\n deleteList(space: ISpaceContext, listId: string): Observable<void>;\n reorderListItems(request: IReorderListItemsRequest): Observable<void>;\n createListItems(\n params: IListItemsCommandParams,\n ): Observable<IListItemResult>;\n setListItemsIsCompleted(\n request: ISetListItemsIsComplete,\n ): Observable<void>;\n deleteListItems(request: IDeleteListItemsRequest): Observable<void>;\n getListById(\n space: ISpaceContext,\n listType: ListType,\n listID: string,\n ): Observable<IListContext>;\n\n // --- Budget tab (the read-model projection over renewals + happenings; see\n // budget-tab-mvp.md Section 3/4). Recomputed on every read, not a plain CRUD\n // collection — hence Observable rather than a one-shot fetch. ---\n\n /** Watches the derived+overridden budget rollup for a space. */\n watchBudget(spaceID: string): Observable<IBudgetRollup>;\n\n /**\n * Persists a user override (target amount and/or surprise-hide flag) for a\n * single computed budget line item, keyed by its `IBudgetLineItem.id`.\n * Triggers a re-emission on the `watchBudget()` observable.\n */\n setOverride(\n spaceID: string,\n lineItemId: string,\n patch: IBudgetOverridePatch,\n ): Promise<void>;\n}\n\nexport const BUDGETUS_SERVICE = new InjectionToken<IBudgetusService>(\n 'BudgetusService',\n);\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,14 +1,16 @@
1
1
  {
2
2
  "name": "@sneat/extension-budgetus-contract",
3
- "version": "0.0.1",
3
+ "version": "0.1.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
7
  "peerDependencies": {
8
- "@sneat/core": "0.12.1",
9
- "@sneat/space-models": "0.12.1",
10
- "@sneat/extension-contactus-contract": "0.12.1",
11
- "@sneat/extension-calendarius-contract": "0.12.1",
8
+ "@angular/core": "^21.0.0",
9
+ "rxjs": "^7.0.0",
10
+ "@sneat/core": "^0.22.1",
11
+ "@sneat/data": "^0.22.1",
12
+ "@sneat/dto": "^0.22.1",
13
+ "@sneat/space-models": "^0.22.1",
12
14
  "vitest": "^4.0.9"
13
15
  },
14
16
  "sideEffects": false,
@@ -1,29 +1,211 @@
1
- import { IContactContext } from '@sneat/extension-contactus-contract';
2
- import { IAmount, IHappeningContext, RepeatPeriod, ICalendarHappeningBrief } from '@sneat/extension-calendarius-contract';
3
- import { ISpaceContext } from '@sneat/space-models';
1
+ import { EnumAsUnionOfKeys } from '@sneat/core';
2
+ import { ISpaceItemNavContext, ISpaceRequest, ISpaceContext } from '@sneat/space-models';
3
+ import { IRecord } from '@sneat/data';
4
+ import { IWithSpaceIDs, SneatRecordStatus, IWithCreated, IWithRestrictions, IShortSpaceInfo, ICommuneDbo } from '@sneat/dto';
5
+ import { InjectionToken } from '@angular/core';
6
+ import { Observable } from 'rxjs';
4
7
 
5
- type LiabilitiesMode = 'incomes' | 'expenses' | 'balance';
6
- type AmountsByCurrency = {
7
- [id: string]: number;
8
- };
9
- interface ILiabilityBase {
10
- readonly valuesByCurrency: AmountsByCurrency;
8
+ declare const enum ListPage {
9
+ list = "list"
11
10
  }
12
- interface IHappeningLiability extends ILiabilityBase {
13
- priceAmount?: IAmount;
14
- times?: number;
15
- readonly happening: IHappeningContext;
11
+ type ListPages = EnumAsUnionOfKeys<typeof ListPage>;
12
+
13
+ type ListStatus = SneatRecordStatus;
14
+ interface IQuantity {
15
+ value: number;
16
+ unit: string;
17
+ }
18
+ interface IListItemCommon extends IListCommon {
19
+ subListId?: string;
20
+ subListType?: ListType;
21
+ quantity?: IQuantity;
22
+ category?: string;
23
+ }
24
+ type IListItemBase = IListItemCommon;
25
+ type ListItemStatus = 'done' | 'active';
26
+ interface IListItemBrief extends IListItemBase {
27
+ id: string;
28
+ readonly created?: string;
29
+ readonly emoji?: string;
30
+ readonly status?: ListItemStatus;
31
+ readonly img?: string;
32
+ }
33
+ interface ListCounts {
34
+ active?: number;
35
+ completed?: number;
36
+ }
37
+ type ListType = 'buy' | 'watch' | 'cook' | 'do' | 'other' | 'recipes' | 'rsvp';
38
+ interface IListCommon {
39
+ title: string;
40
+ img?: string;
41
+ emoji?: string;
42
+ isDone?: boolean;
43
+ }
44
+ interface IListBase extends IListCommon, IWithSpaceIDs {
45
+ type: ListType;
46
+ shortId?: string;
47
+ status?: ListStatus;
48
+ }
49
+ interface IListDbo extends IListBase, IWithRestrictions, IWithCreated {
50
+ dtClosed?: number;
51
+ note?: string;
52
+ numberOf?: ListCounts;
53
+ items?: IListItemBrief[];
54
+ commune?: IShortSpaceInfo;
55
+ }
56
+ declare class ListItemInfoModel {
57
+ static trackBy: (index: number, item: IListItemBrief) => string | number | undefined;
58
+ }
59
+ declare class ListItemModel {
60
+ static equalListItems(...items: IListItemBrief[]): boolean;
61
+ }
62
+ interface IListItemDbo extends IListBase, IListItemCommon {
63
+ listId?: string;
64
+ score?: number;
65
+ subListItems?: IListItemBrief[];
16
66
  }
17
- interface IPeriodLiabilities {
18
- readonly happenings: readonly IHappeningLiability[];
19
- readonly contacts: readonly IContactLiability[];
67
+ declare function getListShortUrlId(communeId: string, shortId?: string, id?: string): string | undefined;
68
+ interface IListInfo extends IWithRestrictions {
69
+ parentListId?: string;
70
+ parentListType?: ListType;
71
+ type: ListType;
72
+ id?: string;
73
+ shortId?: string;
74
+ title?: string;
75
+ hidden?: boolean;
76
+ space?: IShortSpaceInfo;
77
+ emoji?: string;
78
+ img?: string;
79
+ note?: string;
80
+ itemsCount?: number;
20
81
  }
21
- type LiabilitiesByPeriod = Partial<Record<RepeatPeriod, IPeriodLiabilities>>;
22
- interface IContactLiability extends ILiabilityBase {
23
- readonly contact: IContactContext;
82
+ interface IListBrief extends IListBase, IWithCreated {
83
+ emoji?: string;
24
84
  }
85
+ declare function isListInfoMatchesListDto(i: IListInfo, l: IRecord<IListDbo>): boolean;
86
+ declare function createListInfoFromDto(dto: IListDbo, shortId?: string): IListInfo;
25
87
 
26
- declare function getLiabilitiesByPeriod(liabilitiesMode: LiabilitiesMode, recurringHappenings: Record<string, ICalendarHappeningBrief>, space: ISpaceContext): LiabilitiesByPeriod;
88
+ interface IListGroup {
89
+ id: string;
90
+ title?: string;
91
+ type?: ListType;
92
+ emoji?: string;
93
+ lists?: IListInfo[];
94
+ }
95
+
96
+ interface IBudgetusSpaceDbo {
97
+ listGroups?: IListGroup[];
98
+ }
99
+
100
+ interface IMoney {
101
+ currency: string;
102
+ value: number;
103
+ }
104
+ type BudgetLineSource = 'asset-renewal' | 'happening' | 'gift';
105
+ interface IBudgetLineItem {
106
+ id: string;
107
+ title: string;
108
+ dateISO: string;
109
+ amount: IMoney;
110
+ source: BudgetLineSource;
111
+ sourceRef?: string;
112
+ targetAmount?: IMoney;
113
+ isSurprise?: boolean;
114
+ }
115
+ interface IBudgetMonthGroup {
116
+ monthISO: string;
117
+ total: IMoney;
118
+ items: IBudgetLineItem[];
119
+ }
120
+ interface IBudgetRollup {
121
+ byMonth: IBudgetMonthGroup[];
122
+ annualTotal: IMoney;
123
+ mostExpensiveMonthISO: string;
124
+ }
125
+ interface IBudgetOverridePatch {
126
+ targetAmount?: IMoney;
127
+ isSurprise?: boolean;
128
+ }
129
+ declare function monthISOOf(dateISO: string): string;
130
+ declare function maskSurpriseLineItems(items: IBudgetLineItem[], options?: {
131
+ reveal?: boolean;
132
+ }): IBudgetLineItem[];
133
+
134
+ interface IListKey {
135
+ id: string;
136
+ type: ListType;
137
+ }
138
+ interface IListContext extends ISpaceItemNavContext<IListBrief, IListDbo> {
139
+ type: ListType;
140
+ }
141
+
142
+ interface GetOrCreateCommuneItemIds {
143
+ id?: string;
144
+ shortId?: string;
145
+ communeShortId?: string;
146
+ }
147
+ interface IProgress {
148
+ current: number;
149
+ total: number;
150
+ state?: string;
151
+ }
152
+ interface IListItemResult {
153
+ message?: string;
154
+ changed?: boolean;
155
+ success: boolean;
156
+ listDto: IListDbo;
157
+ communeDto?: ICommuneDbo;
158
+ listItemDto?: IListItemDbo;
159
+ }
160
+ interface IListItemsCommandParams {
161
+ space: ISpaceContext;
162
+ list: IListContext;
163
+ items: IListItemBrief[];
164
+ }
165
+ type ReorderListItemsWorker = (listDto: IListDbo) => void;
166
+ interface ICreateListRequest extends ISpaceRequest, IListBrief {
167
+ }
168
+ interface IListRequest extends ISpaceRequest {
169
+ readonly listID: string;
170
+ }
171
+ interface ICreateListItemRequest extends IListItemBase {
172
+ id: string;
173
+ }
174
+ interface ICreateListItemsRequest extends IListRequest {
175
+ items: ICreateListItemRequest[];
176
+ }
177
+ interface IListItemRequest extends IListRequest {
178
+ itemID: string;
179
+ }
180
+ interface IListItemIDsRequest extends IListRequest {
181
+ readonly itemIDs: string[];
182
+ }
183
+ interface IReorderListItemsRequest extends IListItemIDsRequest {
184
+ toIndex: number;
185
+ }
186
+ type IDeleteListItemsRequest = IListItemIDsRequest;
187
+ interface ISetListItemsIsComplete extends IListItemIDsRequest {
188
+ isDone: boolean;
189
+ }
190
+
191
+ interface IBudgetusService {
192
+ createList(request: ICreateListRequest): Observable<IListContext>;
193
+ deleteList(space: ISpaceContext, listId: string): Observable<void>;
194
+ reorderListItems(request: IReorderListItemsRequest): Observable<void>;
195
+ createListItems(params: IListItemsCommandParams): Observable<IListItemResult>;
196
+ setListItemsIsCompleted(request: ISetListItemsIsComplete): Observable<void>;
197
+ deleteListItems(request: IDeleteListItemsRequest): Observable<void>;
198
+ getListById(space: ISpaceContext, listType: ListType, listID: string): Observable<IListContext>;
199
+ /** Watches the derived+overridden budget rollup for a space. */
200
+ watchBudget(spaceID: string): Observable<IBudgetRollup>;
201
+ /**
202
+ * Persists a user override (target amount and/or surprise-hide flag) for a
203
+ * single computed budget line item, keyed by its `IBudgetLineItem.id`.
204
+ * Triggers a re-emission on the `watchBudget()` observable.
205
+ */
206
+ setOverride(spaceID: string, lineItemId: string, patch: IBudgetOverridePatch): Promise<void>;
207
+ }
208
+ declare const BUDGETUS_SERVICE: InjectionToken<IBudgetusService>;
27
209
 
28
- export { getLiabilitiesByPeriod };
29
- export type { AmountsByCurrency, IContactLiability, IHappeningLiability, ILiabilityBase, IPeriodLiabilities, LiabilitiesByPeriod, LiabilitiesMode };
210
+ export { BUDGETUS_SERVICE, ListItemInfoModel, ListItemModel, ListPage, createListInfoFromDto, getListShortUrlId, isListInfoMatchesListDto, maskSurpriseLineItems, monthISOOf };
211
+ export type { BudgetLineSource, GetOrCreateCommuneItemIds, IBudgetLineItem, IBudgetMonthGroup, IBudgetOverridePatch, IBudgetRollup, IBudgetusService, IBudgetusSpaceDbo, ICreateListItemRequest, ICreateListItemsRequest, ICreateListRequest, IDeleteListItemsRequest, IListBase, IListBrief, IListCommon, IListContext, IListDbo, IListGroup, IListInfo, IListItemBase, IListItemBrief, IListItemCommon, IListItemDbo, IListItemIDsRequest, IListItemRequest, IListItemResult, IListItemsCommandParams, IListKey, IListRequest, IMoney, IProgress, IQuantity, IReorderListItemsRequest, ISetListItemsIsComplete, ListCounts, ListItemStatus, ListPages, ListStatus, ListType, ReorderListItemsWorker };