@powerhousedao/contributor-billing 0.0.13 → 0.0.14

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.
Files changed (164) hide show
  1. package/dist/document-models/billing-statement/gen/actions.d.ts +8 -0
  2. package/dist/document-models/billing-statement/gen/actions.d.ts.map +1 -0
  3. package/dist/document-models/billing-statement/gen/actions.js +3 -0
  4. package/dist/document-models/billing-statement/gen/creators.d.ts +4 -0
  5. package/dist/document-models/billing-statement/gen/creators.d.ts.map +1 -0
  6. package/dist/document-models/billing-statement/gen/creators.js +3 -0
  7. package/dist/document-models/billing-statement/gen/document-model.d.ts +3 -0
  8. package/dist/document-models/billing-statement/gen/document-model.d.ts.map +1 -0
  9. package/dist/document-models/billing-statement/gen/document-model.js +117 -0
  10. package/dist/document-models/billing-statement/gen/general/actions.d.ts +7 -0
  11. package/dist/document-models/billing-statement/gen/general/actions.d.ts.map +1 -0
  12. package/dist/document-models/billing-statement/gen/general/actions.js +1 -0
  13. package/dist/document-models/billing-statement/gen/general/creators.d.ts +6 -0
  14. package/dist/document-models/billing-statement/gen/general/creators.d.ts.map +1 -0
  15. package/dist/document-models/billing-statement/gen/general/creators.js +5 -0
  16. package/dist/document-models/billing-statement/gen/general/error.d.ts +2 -0
  17. package/dist/document-models/billing-statement/gen/general/error.d.ts.map +1 -0
  18. package/dist/document-models/billing-statement/gen/general/error.js +1 -0
  19. package/dist/document-models/billing-statement/gen/general/object.d.ts +9 -0
  20. package/dist/document-models/billing-statement/gen/general/object.d.ts.map +1 -0
  21. package/dist/document-models/billing-statement/gen/general/object.js +13 -0
  22. package/dist/document-models/billing-statement/gen/general/operations.d.ts +9 -0
  23. package/dist/document-models/billing-statement/gen/general/operations.d.ts.map +1 -0
  24. package/dist/document-models/billing-statement/gen/general/operations.js +1 -0
  25. package/dist/document-models/billing-statement/gen/index.d.ts +6 -0
  26. package/dist/document-models/billing-statement/gen/index.d.ts.map +1 -0
  27. package/dist/document-models/billing-statement/gen/index.js +5 -0
  28. package/dist/document-models/billing-statement/gen/line-items/actions.d.ts +6 -0
  29. package/dist/document-models/billing-statement/gen/line-items/actions.d.ts.map +1 -0
  30. package/dist/document-models/billing-statement/gen/line-items/actions.js +1 -0
  31. package/dist/document-models/billing-statement/gen/line-items/creators.d.ts +5 -0
  32. package/dist/document-models/billing-statement/gen/line-items/creators.d.ts.map +1 -0
  33. package/dist/document-models/billing-statement/gen/line-items/creators.js +4 -0
  34. package/dist/document-models/billing-statement/gen/line-items/error.d.ts +2 -0
  35. package/dist/document-models/billing-statement/gen/line-items/error.d.ts.map +1 -0
  36. package/dist/document-models/billing-statement/gen/line-items/error.js +1 -0
  37. package/dist/document-models/billing-statement/gen/line-items/object.d.ts +8 -0
  38. package/dist/document-models/billing-statement/gen/line-items/object.d.ts.map +1 -0
  39. package/dist/document-models/billing-statement/gen/line-items/object.js +10 -0
  40. package/dist/document-models/billing-statement/gen/line-items/operations.d.ts +8 -0
  41. package/dist/document-models/billing-statement/gen/line-items/operations.d.ts.map +1 -0
  42. package/dist/document-models/billing-statement/gen/line-items/operations.js +1 -0
  43. package/dist/document-models/billing-statement/gen/object.d.ts +20 -0
  44. package/dist/document-models/billing-statement/gen/object.d.ts.map +1 -0
  45. package/dist/document-models/billing-statement/gen/object.js +33 -0
  46. package/dist/document-models/billing-statement/gen/reducer.d.ts +3 -0
  47. package/dist/document-models/billing-statement/gen/reducer.d.ts.map +1 -0
  48. package/dist/document-models/billing-statement/gen/reducer.js +39 -0
  49. package/dist/document-models/billing-statement/gen/schema/index.d.ts +3 -0
  50. package/dist/document-models/billing-statement/gen/schema/index.d.ts.map +1 -0
  51. package/dist/document-models/billing-statement/gen/schema/index.js +2 -0
  52. package/dist/document-models/billing-statement/gen/schema/types.d.ts +202 -0
  53. package/dist/document-models/billing-statement/gen/schema/types.d.ts.map +1 -0
  54. package/dist/document-models/billing-statement/gen/schema/types.js +1 -0
  55. package/dist/document-models/billing-statement/gen/schema/zod.d.ts +23 -0
  56. package/dist/document-models/billing-statement/gen/schema/zod.d.ts.map +1 -0
  57. package/dist/document-models/billing-statement/gen/schema/zod.js +117 -0
  58. package/dist/document-models/billing-statement/gen/tags/actions.d.ts +5 -0
  59. package/dist/document-models/billing-statement/gen/tags/actions.d.ts.map +1 -0
  60. package/dist/document-models/billing-statement/gen/tags/actions.js +1 -0
  61. package/dist/document-models/billing-statement/gen/tags/creators.d.ts +4 -0
  62. package/dist/document-models/billing-statement/gen/tags/creators.d.ts.map +1 -0
  63. package/dist/document-models/billing-statement/gen/tags/creators.js +3 -0
  64. package/dist/document-models/billing-statement/gen/tags/error.d.ts +2 -0
  65. package/dist/document-models/billing-statement/gen/tags/error.d.ts.map +1 -0
  66. package/dist/document-models/billing-statement/gen/tags/error.js +1 -0
  67. package/dist/document-models/billing-statement/gen/tags/object.d.ts +7 -0
  68. package/dist/document-models/billing-statement/gen/tags/object.d.ts.map +1 -0
  69. package/dist/document-models/billing-statement/gen/tags/object.js +7 -0
  70. package/dist/document-models/billing-statement/gen/tags/operations.d.ts +7 -0
  71. package/dist/document-models/billing-statement/gen/tags/operations.d.ts.map +1 -0
  72. package/dist/document-models/billing-statement/gen/tags/operations.js +1 -0
  73. package/dist/document-models/billing-statement/gen/types.d.ts +10 -0
  74. package/dist/document-models/billing-statement/gen/types.d.ts.map +1 -0
  75. package/dist/document-models/billing-statement/gen/types.js +1 -0
  76. package/dist/document-models/billing-statement/gen/utils.d.ts +7 -0
  77. package/dist/document-models/billing-statement/gen/utils.d.ts.map +1 -0
  78. package/dist/document-models/billing-statement/gen/utils.js +42 -0
  79. package/dist/document-models/billing-statement/index.d.ts +31 -0
  80. package/dist/document-models/billing-statement/index.d.ts.map +1 -0
  81. package/dist/document-models/billing-statement/index.js +21 -0
  82. package/dist/document-models/billing-statement/src/reducers/general.d.ts +8 -0
  83. package/dist/document-models/billing-statement/src/reducers/general.d.ts.map +1 -0
  84. package/dist/document-models/billing-statement/src/reducers/general.js +41 -0
  85. package/dist/document-models/billing-statement/src/reducers/line-items.d.ts +8 -0
  86. package/dist/document-models/billing-statement/src/reducers/line-items.d.ts.map +1 -0
  87. package/dist/document-models/billing-statement/src/reducers/line-items.js +49 -0
  88. package/dist/document-models/billing-statement/src/reducers/tags.d.ts +8 -0
  89. package/dist/document-models/billing-statement/src/reducers/tags.d.ts.map +1 -0
  90. package/dist/document-models/billing-statement/src/reducers/tags.js +36 -0
  91. package/dist/document-models/billing-statement/src/tests/document-model.test.d.ts +6 -0
  92. package/dist/document-models/billing-statement/src/tests/document-model.test.d.ts.map +1 -0
  93. package/dist/document-models/billing-statement/src/tests/document-model.test.js +17 -0
  94. package/dist/document-models/billing-statement/src/tests/general.test.d.ts +5 -0
  95. package/dist/document-models/billing-statement/src/tests/general.test.d.ts.map +1 -0
  96. package/dist/document-models/billing-statement/src/tests/general.test.js +93 -0
  97. package/dist/document-models/billing-statement/src/tests/line-items.test.d.ts +6 -0
  98. package/dist/document-models/billing-statement/src/tests/line-items.test.d.ts.map +1 -0
  99. package/dist/document-models/billing-statement/src/tests/line-items.test.js +131 -0
  100. package/dist/document-models/billing-statement/src/tests/tags.test.d.ts +6 -0
  101. package/dist/document-models/billing-statement/src/tests/tags.test.d.ts.map +1 -0
  102. package/dist/document-models/billing-statement/src/tests/tags.test.js +52 -0
  103. package/dist/document-models/billing-statement/src/utils.d.ts +2 -0
  104. package/dist/document-models/billing-statement/src/utils.d.ts.map +1 -0
  105. package/dist/document-models/billing-statement/src/utils.js +1 -0
  106. package/dist/document-models/index.d.ts +1 -0
  107. package/dist/document-models/index.d.ts.map +1 -1
  108. package/dist/document-models/index.js +1 -0
  109. package/dist/editors/billing-statement/components/lineItems.d.ts +3 -0
  110. package/dist/editors/billing-statement/components/lineItems.d.ts.map +1 -0
  111. package/dist/editors/billing-statement/components/lineItems.js +24 -0
  112. package/dist/editors/billing-statement/components/lineItemsTable.d.ts +6 -0
  113. package/dist/editors/billing-statement/components/lineItemsTable.d.ts.map +1 -0
  114. package/dist/editors/billing-statement/components/lineItemsTable.js +116 -0
  115. package/dist/editors/billing-statement/components/objectSetTable.d.ts +6 -0
  116. package/dist/editors/billing-statement/components/objectSetTable.d.ts.map +1 -0
  117. package/dist/editors/billing-statement/components/objectSetTable.js +96 -0
  118. package/dist/editors/billing-statement/editor.d.ts +5 -0
  119. package/dist/editors/billing-statement/editor.d.ts.map +1 -0
  120. package/dist/editors/billing-statement/editor.js +23 -0
  121. package/dist/editors/billing-statement/index.d.ts +5 -0
  122. package/dist/editors/billing-statement/index.d.ts.map +1 -0
  123. package/dist/editors/billing-statement/index.js +12 -0
  124. package/dist/editors/billing-statement/lineItemTags/lineItemTags.d.ts +16 -0
  125. package/dist/editors/billing-statement/lineItemTags/lineItemTags.d.ts.map +1 -0
  126. package/dist/editors/billing-statement/lineItemTags/lineItemTags.js +58 -0
  127. package/dist/editors/billing-statement/lineItemTags/tagMapping.d.ts +4 -0
  128. package/dist/editors/billing-statement/lineItemTags/tagMapping.d.ts.map +1 -0
  129. package/dist/editors/billing-statement/lineItemTags/tagMapping.js +44 -0
  130. package/dist/editors/contributor-billing/editor.js +1 -1
  131. package/dist/editors/index.d.ts +1 -0
  132. package/dist/editors/index.d.ts.map +1 -1
  133. package/dist/editors/index.js +1 -0
  134. package/dist/editors/invoice/components/currencyForm.d.ts.map +1 -1
  135. package/dist/editors/invoice/components/currencyForm.js +2 -4
  136. package/dist/editors/invoice/components/datePicker.d.ts.map +1 -1
  137. package/dist/editors/invoice/components/datePicker.js +2 -2
  138. package/dist/editors/invoice/components/inputField.d.ts.map +1 -1
  139. package/dist/editors/invoice/components/inputField.js +1 -3
  140. package/dist/editors/invoice/components/numberForm.d.ts +2 -1
  141. package/dist/editors/invoice/components/numberForm.d.ts.map +1 -1
  142. package/dist/editors/invoice/components/numberForm.js +2 -2
  143. package/dist/editors/invoice/editor.d.ts.map +1 -1
  144. package/dist/editors/invoice/editor.js +38 -33
  145. package/dist/editors/invoice/lineItems.d.ts +1 -1
  146. package/dist/editors/invoice/lineItems.d.ts.map +1 -1
  147. package/dist/editors/invoice/lineItems.js +21 -12
  148. package/dist/index.d.ts +2 -2
  149. package/dist/index.d.ts.map +1 -1
  150. package/dist/powerhouse.manifest.json +10 -1
  151. package/dist/style.css +102 -2
  152. package/dist/subgraphs/billing-statement/index.d.ts +10 -0
  153. package/dist/subgraphs/billing-statement/index.d.ts.map +1 -0
  154. package/dist/subgraphs/billing-statement/index.js +11 -0
  155. package/dist/subgraphs/billing-statement/resolvers.d.ts +3 -0
  156. package/dist/subgraphs/billing-statement/resolvers.d.ts.map +1 -0
  157. package/dist/subgraphs/billing-statement/resolvers.js +110 -0
  158. package/dist/subgraphs/billing-statement/schema.d.ts +3 -0
  159. package/dist/subgraphs/billing-statement/schema.d.ts.map +1 -0
  160. package/dist/subgraphs/billing-statement/schema.js +165 -0
  161. package/dist/subgraphs/index.d.ts +1 -0
  162. package/dist/subgraphs/index.d.ts.map +1 -1
  163. package/dist/subgraphs/index.js +1 -0
  164. package/package.json +4 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-items.d.ts","sourceRoot":"","sources":["../../../../../document-models/billing-statement/src/reducers/line-items.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,oCAAoC,CAAC;AAG9F,eAAO,MAAM,OAAO,EAAE,mCAuCrB,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * This is a scaffold file meant for customization:
3
+ * - modify it by implementing the reducer functions
4
+ * - delete the file and run the code generator again to have it reset
5
+ */
6
+ export const reducer = {
7
+ addLineItemOperation(state, action, dispatch) {
8
+ try {
9
+ const newLineItem = {
10
+ ...action.input,
11
+ lineItemTag: [],
12
+ };
13
+ // Check for duplicate ID
14
+ if (state.lineItems.find((x) => x.id === newLineItem.id)) {
15
+ throw new Error("Duplicate line item ID");
16
+ }
17
+ state.lineItems.push(newLineItem);
18
+ updateTotals(state);
19
+ }
20
+ catch (error) {
21
+ console.error("Failed to add line item:", error);
22
+ }
23
+ },
24
+ editLineItemOperation(state, action, dispatch) {
25
+ try {
26
+ const stateItem = state.lineItems.find((x) => x.id === action.input.id);
27
+ if (!stateItem)
28
+ throw new Error("Item matching input.id not found");
29
+ const sanitizedInput = Object.fromEntries(Object.entries(action.input).filter(([, value]) => value !== null));
30
+ const nextItem = {
31
+ ...stateItem,
32
+ ...sanitizedInput,
33
+ };
34
+ Object.assign(stateItem, nextItem);
35
+ updateTotals(state);
36
+ }
37
+ catch (error) {
38
+ console.error("Failed to edit line item:", error);
39
+ }
40
+ },
41
+ };
42
+ const updateTotals = (state) => {
43
+ state.totalCash = state.lineItems.reduce((total, lineItem) => {
44
+ return total + lineItem.quantity * lineItem.unitPriceCash;
45
+ }, 0.0);
46
+ state.totalPowt = state.lineItems.reduce((total, lineItem) => {
47
+ return total + lineItem.quantity * lineItem.unitPricePwt;
48
+ }, 0.0);
49
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * This is a scaffold file meant for customization:
3
+ * - modify it by implementing the reducer functions
4
+ * - delete the file and run the code generator again to have it reset
5
+ */
6
+ import type { BillingStatementTagsOperations } from "../../gen/tags/operations.js";
7
+ export declare const reducer: BillingStatementTagsOperations;
8
+ //# sourceMappingURL=tags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../../../../document-models/billing-statement/src/reducers/tags.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAEnF,eAAO,MAAM,OAAO,EAAE,8BA8BrB,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * This is a scaffold file meant for customization:
3
+ * - modify it by implementing the reducer functions
4
+ * - delete the file and run the code generator again to have it reset
5
+ */
6
+ export const reducer = {
7
+ editLineItemTagOperation(state, action, dispatch) {
8
+ try {
9
+ const stateItem = state.lineItems.find((x) => x.id === action.input.lineItemId);
10
+ if (!stateItem)
11
+ throw new Error("Item matching input.lineItemId not found");
12
+ // if tag already exists with the same dimension, update the value and label
13
+ const existingTag = stateItem.lineItemTag?.find((tag) => tag.dimension === action.input.dimension);
14
+ if (existingTag) {
15
+ existingTag.value = action.input.value;
16
+ existingTag.label = action.input.label || null;
17
+ }
18
+ else {
19
+ // if tag does not exist, add it
20
+ const newTag = {
21
+ dimension: action.input.dimension,
22
+ value: action.input.value,
23
+ label: action.input.label || null,
24
+ };
25
+ if (!stateItem.lineItemTag) {
26
+ stateItem.lineItemTag = [];
27
+ }
28
+ // Add the new tag
29
+ stateItem.lineItemTag?.push(newTag);
30
+ }
31
+ }
32
+ catch (error) {
33
+ console.error("Failed to edit line item tag:", error);
34
+ }
35
+ },
36
+ };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * This is a scaffold file meant for customization:
3
+ * - change it by adding new tests or modifying the existing ones
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=document-model.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-model.test.d.ts","sourceRoot":"","sources":["../../../../../document-models/billing-statement/src/tests/document-model.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * This is a scaffold file meant for customization:
3
+ * - change it by adding new tests or modifying the existing ones
4
+ */
5
+ import utils, { initialGlobalState, initialLocalState, } from "../../gen/utils.js";
6
+ describe("Billing Statement Document Model", () => {
7
+ it("should create a new Billing Statement document", () => {
8
+ const document = utils.createDocument();
9
+ expect(document).toBeDefined();
10
+ expect(document.documentType).toBe("powerhouse/billing-statement");
11
+ });
12
+ it("should create a new Billing Statement document with a valid initial state", () => {
13
+ const document = utils.createDocument();
14
+ expect(document.state.global).toStrictEqual(initialGlobalState);
15
+ expect(document.state.local).toStrictEqual(initialLocalState);
16
+ });
17
+ });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for Billing Statement operations
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=general.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"general.test.d.ts","sourceRoot":"","sources":["../../../../../document-models/billing-statement/src/tests/general.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Tests for Billing Statement operations
3
+ */
4
+ import utils from "../../gen/utils.js";
5
+ import { reducer } from "../../gen/reducer.js";
6
+ import * as creators from "../../gen/general/creators.js";
7
+ describe("Billing Statement Operations", () => {
8
+ let document;
9
+ beforeEach(() => {
10
+ document = utils.createDocument();
11
+ });
12
+ describe("editBillingStatement", () => {
13
+ it("should update billing statement with all fields", () => {
14
+ const input = {
15
+ dateIssued: "2024-03-20T10:00:00Z",
16
+ dateDue: "2024-04-20T10:00:00Z",
17
+ currency: "USD",
18
+ notes: "Test billing statement notes"
19
+ };
20
+ const updatedDocument = reducer(document, creators.editBillingStatement(input));
21
+ // Verify operation was recorded
22
+ expect(updatedDocument.operations.global).toHaveLength(1);
23
+ expect(updatedDocument.operations.global[0].type).toBe("EDIT_BILLING_STATEMENT");
24
+ expect(updatedDocument.operations.global[0].input).toStrictEqual(input);
25
+ expect(updatedDocument.operations.global[0].index).toEqual(0);
26
+ // Verify state was updated
27
+ expect(updatedDocument.state.global.dateIssued).toBe(input.dateIssued);
28
+ expect(updatedDocument.state.global.dateDue).toBe(input.dateDue);
29
+ expect(updatedDocument.state.global.currency).toBe(input.currency);
30
+ expect(updatedDocument.state.global.notes).toBe(input.notes);
31
+ });
32
+ it("should update billing statement with partial fields", () => {
33
+ const input = {
34
+ dateIssued: "2024-03-20T10:00:00Z",
35
+ currency: "EUR"
36
+ };
37
+ const updatedDocument = reducer(document, creators.editBillingStatement(input));
38
+ // Verify operation was recorded
39
+ expect(updatedDocument.operations.global).toHaveLength(1);
40
+ expect(updatedDocument.operations.global[0].type).toBe("EDIT_BILLING_STATEMENT");
41
+ expect(updatedDocument.operations.global[0].input).toStrictEqual(input);
42
+ // Verify only specified fields were updated
43
+ expect(updatedDocument.state.global.dateIssued).toBe(input.dateIssued);
44
+ expect(updatedDocument.state.global.currency).toBe(input.currency);
45
+ // Other fields should remain unchanged
46
+ expect(updatedDocument.state.global.dateDue).toBe(document.state.global.dateDue);
47
+ expect(updatedDocument.state.global.notes).toBe(document.state.global.notes);
48
+ });
49
+ });
50
+ describe("editContributor", () => {
51
+ it("should update contributor ID", () => {
52
+ const input = {
53
+ contributor: "PHID-USER-123456789"
54
+ };
55
+ const updatedDocument = reducer(document, creators.editContributor(input));
56
+ // Verify operation was recorded
57
+ expect(updatedDocument.operations.global).toHaveLength(1);
58
+ expect(updatedDocument.operations.global[0].type).toBe("EDIT_CONTRIBUTOR");
59
+ expect(updatedDocument.operations.global[0].input).toStrictEqual(input);
60
+ // Verify state was updated
61
+ expect(updatedDocument.state.global.contributor).toBe(input.contributor);
62
+ });
63
+ });
64
+ describe("editStatus", () => {
65
+ it("should update billing statement status", () => {
66
+ const input = {
67
+ status: "ISSUED"
68
+ };
69
+ const updatedDocument = reducer(document, creators.editStatus(input));
70
+ // Verify operation was recorded
71
+ expect(updatedDocument.operations.global).toHaveLength(1);
72
+ expect(updatedDocument.operations.global[0].type).toBe("EDIT_STATUS");
73
+ expect(updatedDocument.operations.global[0].input).toStrictEqual(input);
74
+ // Verify state was updated
75
+ expect(updatedDocument.state.global.status).toBe(input.status);
76
+ });
77
+ it("should handle all possible status transitions", () => {
78
+ const statuses = [
79
+ "DRAFT",
80
+ "ISSUED",
81
+ "ACCEPTED",
82
+ "REJECTED",
83
+ "PAID"
84
+ ];
85
+ let currentDocument = document;
86
+ for (const status of statuses) {
87
+ const input = { status };
88
+ currentDocument = reducer(currentDocument, creators.editStatus(input));
89
+ expect(currentDocument.state.global.status).toBe(status);
90
+ }
91
+ });
92
+ });
93
+ });
@@ -0,0 +1,6 @@
1
+ /**
2
+ * This is a scaffold file meant for customization:
3
+ * - change it by adding new tests or modifying the existing ones
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=line-items.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-items.test.d.ts","sourceRoot":"","sources":["../../../../../document-models/billing-statement/src/tests/line-items.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * This is a scaffold file meant for customization:
3
+ * - change it by adding new tests or modifying the existing ones
4
+ */
5
+ import utils from "../../gen/utils.js";
6
+ import { reducer } from "../../gen/reducer.js";
7
+ import * as creators from "../../gen/line-items/creators.js";
8
+ import { generateId } from "document-model";
9
+ describe("Billing Statement Line Items Operations", () => {
10
+ let document;
11
+ beforeEach(() => {
12
+ document = utils.createDocument();
13
+ });
14
+ describe("addLineItem", () => {
15
+ it("should add a new line item and update totals", () => {
16
+ const input = {
17
+ id: generateId(),
18
+ description: "Test Line Item",
19
+ quantity: 2,
20
+ unit: "HOUR",
21
+ unitPricePwt: 10,
22
+ unitPriceCash: 20,
23
+ totalPricePwt: 20,
24
+ totalPriceCash: 40,
25
+ };
26
+ const updatedDocument = reducer(document, creators.addLineItem(input));
27
+ // Verify operation was recorded
28
+ expect(updatedDocument.operations.global).toHaveLength(1);
29
+ expect(updatedDocument.operations.global[0].type).toBe("ADD_LINE_ITEM");
30
+ expect(updatedDocument.operations.global[0].input).toStrictEqual(input);
31
+ // Verify state was updated
32
+ expect(updatedDocument.state.global.lineItems).toHaveLength(1);
33
+ const addedItem = updatedDocument.state.global.lineItems[0];
34
+ expect(addedItem.description).toBe(input.description);
35
+ expect(addedItem.quantity).toBe(input.quantity);
36
+ expect(addedItem.unitPricePwt).toBe(input.unitPricePwt);
37
+ expect(addedItem.unitPriceCash).toBe(input.unitPriceCash);
38
+ expect(addedItem.totalPricePwt).toBe(input.totalPricePwt);
39
+ expect(addedItem.totalPriceCash).toBe(input.totalPriceCash);
40
+ expect(addedItem.lineItemTag).toEqual([]);
41
+ // Verify totals were updated
42
+ expect(updatedDocument.state.global.totalCash).toBe(input.totalPriceCash);
43
+ expect(updatedDocument.state.global.totalPowt).toBe(input.totalPricePwt);
44
+ });
45
+ });
46
+ describe("editLineItem", () => {
47
+ it("should edit an existing line item and update totals", () => {
48
+ // First, add a line item
49
+ const addInput = {
50
+ id: generateId(),
51
+ description: "Original Line Item",
52
+ quantity: 1,
53
+ unit: "HOUR",
54
+ unitPricePwt: 10,
55
+ unitPriceCash: 20,
56
+ totalPricePwt: 10,
57
+ totalPriceCash: 20,
58
+ };
59
+ let updatedDocument = reducer(document, creators.addLineItem(addInput));
60
+ const lineItemId = updatedDocument.state.global.lineItems[0].id;
61
+ // Now edit the line item
62
+ const editInput = {
63
+ id: lineItemId,
64
+ description: "Updated Line Item",
65
+ quantity: 3,
66
+ unit: "HOUR",
67
+ unitPricePwt: 15,
68
+ unitPriceCash: 25,
69
+ totalPricePwt: 45,
70
+ totalPriceCash: 75,
71
+ };
72
+ updatedDocument = reducer(updatedDocument, creators.editLineItem(editInput));
73
+ // Verify operation was recorded
74
+ expect(updatedDocument.operations.global).toHaveLength(2);
75
+ expect(updatedDocument.operations.global[1].type).toBe("EDIT_LINE_ITEM");
76
+ expect(updatedDocument.operations.global[1].input).toStrictEqual(editInput);
77
+ // Verify state was updated
78
+ expect(updatedDocument.state.global.lineItems).toHaveLength(1);
79
+ const editedItem = updatedDocument.state.global.lineItems[0];
80
+ expect(editedItem.description).toBe(editInput.description);
81
+ expect(editedItem.quantity).toBe(editInput.quantity);
82
+ expect(editedItem.unitPricePwt).toBe(editInput.unitPricePwt);
83
+ expect(editedItem.unitPriceCash).toBe(editInput.unitPriceCash);
84
+ expect(editedItem.totalPricePwt).toBe(editInput.totalPricePwt);
85
+ expect(editedItem.totalPriceCash).toBe(editInput.totalPriceCash);
86
+ // Verify totals were updated
87
+ expect(updatedDocument.state.global.totalCash).toBe(editInput.totalPriceCash);
88
+ expect(updatedDocument.state.global.totalPowt).toBe(editInput.totalPricePwt);
89
+ });
90
+ it("should handle partial updates to a line item", () => {
91
+ // First, add a line item
92
+ const addInput = {
93
+ id: generateId(),
94
+ description: "Original Line Item",
95
+ quantity: 1,
96
+ unit: "HOUR",
97
+ unitPricePwt: 10,
98
+ unitPriceCash: 20,
99
+ totalPricePwt: 10,
100
+ totalPriceCash: 20,
101
+ };
102
+ let updatedDocument = reducer(document, creators.addLineItem(addInput));
103
+ const lineItemId = updatedDocument.state.global.lineItems[0].id;
104
+ // Now edit the line item with partial fields
105
+ const editInput = {
106
+ id: lineItemId,
107
+ description: "Updated Description",
108
+ quantity: 2,
109
+ unit: "UNIT",
110
+ };
111
+ updatedDocument = reducer(updatedDocument, creators.editLineItem(editInput));
112
+ // Verify operation was recorded
113
+ expect(updatedDocument.operations.global).toHaveLength(2);
114
+ expect(updatedDocument.operations.global[1].type).toBe("EDIT_LINE_ITEM");
115
+ expect(updatedDocument.operations.global[1].input).toStrictEqual(editInput);
116
+ // Verify state was updated
117
+ expect(updatedDocument.state.global.lineItems).toHaveLength(1);
118
+ const editedItem = updatedDocument.state.global.lineItems[0];
119
+ expect(editedItem.description).toBe(editInput.description);
120
+ expect(editedItem.quantity).toBe(editInput.quantity);
121
+ // Other fields should remain unchanged
122
+ expect(editedItem.unitPricePwt).toBe(addInput.unitPricePwt);
123
+ expect(editedItem.unitPriceCash).toBe(addInput.unitPriceCash);
124
+ // Verify totals were updated based on new quantity
125
+ expect(editInput.quantity).not.toBeNull();
126
+ expect(editInput.quantity).not.toBeUndefined();
127
+ expect(updatedDocument.state.global.totalCash).toBe(editInput.quantity * addInput.unitPriceCash);
128
+ expect(updatedDocument.state.global.totalPowt).toBe(editInput.quantity * addInput.unitPricePwt);
129
+ });
130
+ });
131
+ });
@@ -0,0 +1,6 @@
1
+ /**
2
+ * This is a scaffold file meant for customization:
3
+ * - change it by adding new tests or modifying the existing ones
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=tags.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tags.test.d.ts","sourceRoot":"","sources":["../../../../../document-models/billing-statement/src/tests/tags.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * This is a scaffold file meant for customization:
3
+ * - change it by adding new tests or modifying the existing ones
4
+ */
5
+ import utils from "../../gen/utils.js";
6
+ import { reducer } from "../../gen/reducer.js";
7
+ import * as creators from "../../gen/tags/creators.js";
8
+ import * as lineItemCreators from "../../gen/line-items/creators.js";
9
+ import { generateId } from "document-model";
10
+ describe("Billing Statement Tags Operations", () => {
11
+ let document;
12
+ beforeEach(() => {
13
+ document = utils.createDocument();
14
+ });
15
+ describe("editLineItemTag", () => {
16
+ it("should edit a line item tag", () => {
17
+ // First, add a line item
18
+ const addInput = {
19
+ id: generateId(),
20
+ description: "Test Line Item",
21
+ quantity: 1,
22
+ unit: "HOUR",
23
+ unitPricePwt: 10,
24
+ unitPriceCash: 20,
25
+ totalPricePwt: 10,
26
+ totalPriceCash: 20,
27
+ };
28
+ let updatedDocument = reducer(document, lineItemCreators.addLineItem(addInput));
29
+ const lineItemId = updatedDocument.state.global.lineItems[0].id;
30
+ // Now edit the line item tag
31
+ const input = {
32
+ lineItemId: lineItemId,
33
+ dimension: "category",
34
+ value: "expense",
35
+ label: "Office Supplies",
36
+ };
37
+ updatedDocument = reducer(updatedDocument, creators.editLineItemTag(input));
38
+ // Verify operation was recorded
39
+ expect(updatedDocument.operations.global).toHaveLength(2);
40
+ expect(updatedDocument.operations.global[1].type).toBe("EDIT_LINE_ITEM_TAG");
41
+ expect(updatedDocument.operations.global[1].input).toStrictEqual(input);
42
+ // Verify state was updated
43
+ const lineItem = updatedDocument.state.global.lineItems.find(item => item.id === input.lineItemId);
44
+ expect(lineItem).toBeDefined();
45
+ expect(lineItem?.lineItemTag).toContainEqual({
46
+ dimension: input.dimension,
47
+ value: input.value,
48
+ label: input.label,
49
+ });
50
+ });
51
+ });
52
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../document-models/billing-statement/src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export { module as Invoice } from "./invoice/index.js";
2
+ export { module as BillingStatement } from "./billing-statement/index.js";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../document-models/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../document-models/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,MAAM,IAAI,gBAAgB,EAAE,MAAM,8BAA8B,CAAC"}
@@ -1 +1,2 @@
1
1
  export { module as Invoice } from "./invoice/index.js";
2
+ export { module as BillingStatement } from "./billing-statement/index.js";
@@ -0,0 +1,3 @@
1
+ declare const LineItems: () => import("react/jsx-runtime").JSX.Element;
2
+ export default LineItems;
3
+ //# sourceMappingURL=lineItems.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lineItems.d.ts","sourceRoot":"","sources":["../../../../editors/billing-statement/components/lineItems.tsx"],"names":[],"mappings":"AAOA,QAAA,MAAM,SAAS,+CA2Cd,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Tag } from "lucide-react";
3
+ // import { ObjectSetTable } from "@powerhousedao/document-engineering";
4
+ import { useMemo } from "react";
5
+ // table columns
6
+ const LineItems = () => {
7
+ const columns = useMemo(() => [
8
+ { field: 'description', title: "Description" },
9
+ { field: 'unit', title: "Unit" },
10
+ { field: 'quantity', title: "Quantity" },
11
+ { field: 'unitPriceCash', title: "Fiat/Unit" },
12
+ { field: 'unitPricePwt', title: "POWT/Unit" },
13
+ { field: 'totalPriceCash', title: "Total Fiat" },
14
+ { field: 'totalPricePwt', title: "Total POWT" },
15
+ ], []);
16
+ return (_jsxs("div", { className: "mt-6", children: [_jsxs("div", { className: "flex justify-between", children: [_jsx("div", { className: "flex items-center", children: _jsx("h1", { className: "text-1xl font-bold px-2", children: "Line Items" }) }), _jsx("div", { className: "flex items-center", children: _jsx(Tag, { onClick: () => { }, style: {
17
+ cursor: "pointer",
18
+ width: 28,
19
+ height: 28,
20
+ color: "white",
21
+ fill: "#475264",
22
+ } }) })] }), _jsx("div", { className: "mt-4" })] }));
23
+ };
24
+ export default LineItems;
@@ -0,0 +1,6 @@
1
+ declare const LineItemsTable: (props: {
2
+ state: any;
3
+ dispatch: any;
4
+ }) => import("react/jsx-runtime").JSX.Element;
5
+ export default LineItemsTable;
6
+ //# sourceMappingURL=lineItemsTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lineItemsTable.d.ts","sourceRoot":"","sources":["../../../../editors/billing-statement/components/lineItemsTable.tsx"],"names":[],"mappings":"AAoBA,QAAA,MAAM,cAAc,GAAI,OAAO;IAAE,KAAK,EAAE,GAAG,CAAC;IAAC,QAAQ,EAAE,GAAG,CAAA;CAAE,4CA8N3D,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -0,0 +1,116 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Tag } from "lucide-react";
3
+ import { Select } from "@powerhousedao/document-engineering";
4
+ import { InputField } from "../../invoice/components/inputField.js";
5
+ import { NumberForm } from "../../invoice/components/numberForm.js";
6
+ import { actions, } from "../../../document-models/billing-statement/index.js";
7
+ import { useState, useRef, useEffect } from "react";
8
+ import { formatNumber } from "../../invoice/lineItems.js";
9
+ import { LineItemTagsTable } from "../lineItemTags/lineItemTags.js";
10
+ const initialLineItem = {
11
+ description: "",
12
+ unit: "Hour",
13
+ quantity: "",
14
+ unitPriceCash: "",
15
+ unitPricePwt: "",
16
+ };
17
+ const LineItemsTable = (props) => {
18
+ const { state, dispatch } = props;
19
+ const [editingRow, setEditingRow] = useState(null);
20
+ const [localLineItem, setLocalLineItem] = useState(initialLineItem);
21
+ const [showTagTable, setShowTagTable] = useState(false);
22
+ const tableRef = useRef(null);
23
+ useEffect(() => {
24
+ function handleClickOutside(event) {
25
+ // Check if the click is on a select menu or its dropdown
26
+ const target = event.target;
27
+ const isSelectMenu = target.closest('[role="listbox"]') || target.closest('[role="option"]');
28
+ if (tableRef.current &&
29
+ !tableRef.current.contains(event.target) &&
30
+ !isSelectMenu) {
31
+ // Save changes before clearing the editing state
32
+ if (editingRow !== null) {
33
+ handleSave();
34
+ }
35
+ }
36
+ }
37
+ document.addEventListener("mousedown", handleClickOutside);
38
+ return () => {
39
+ document.removeEventListener("mousedown", handleClickOutside);
40
+ };
41
+ }, [editingRow, localLineItem]);
42
+ const units = [
43
+ { label: "Minute", value: "MINUTE" },
44
+ { label: "Hour", value: "HOUR" },
45
+ { label: "Day", value: "DAY" },
46
+ { label: "Unit", value: "UNIT" },
47
+ ];
48
+ const handleEdit = (rowIdx, item) => {
49
+ setEditingRow(rowIdx);
50
+ setLocalLineItem({ ...item });
51
+ };
52
+ const handleInputChange = (field, value) => {
53
+ if (field === "unitPriceCash" || field === "unitPricePwt") {
54
+ // Allow negative numbers with optional minus sign at start
55
+ const regex = new RegExp(`^-?\\d*\\.?\\d{0,6}$`);
56
+ if (regex.test(value) || value === "-") {
57
+ setLocalLineItem((prev) => ({ ...prev, [field]: value }));
58
+ }
59
+ }
60
+ setLocalLineItem((prev) => ({ ...prev, [field]: value }));
61
+ };
62
+ const handleSave = () => {
63
+ const { description, unit, quantity, unitPriceCash, unitPricePwt } = localLineItem;
64
+ if (description &&
65
+ unit &&
66
+ quantity !== "" &&
67
+ unitPriceCash !== "" &&
68
+ unitPricePwt !== "") {
69
+ // Parse as number, allowing negative values
70
+ const qty = Number(quantity);
71
+ const fiat = Number(unitPriceCash);
72
+ const powt = Number(unitPricePwt);
73
+ // Get the original line item
74
+ const originalItem = state.lineItems.find((item) => item.id === localLineItem.id);
75
+ // Check if any values have actually changed
76
+ const hasChanges = !originalItem ||
77
+ originalItem.description !== description ||
78
+ originalItem.unit !== unit ||
79
+ originalItem.quantity !== qty ||
80
+ originalItem.unitPriceCash !== fiat ||
81
+ originalItem.unitPricePwt !== powt;
82
+ if (hasChanges) {
83
+ dispatch(actions.editLineItem({
84
+ id: localLineItem.id,
85
+ description,
86
+ unit,
87
+ quantity: qty,
88
+ unitPriceCash: fiat,
89
+ unitPricePwt: powt,
90
+ totalPriceCash: qty * fiat,
91
+ totalPricePwt: qty * powt,
92
+ }));
93
+ }
94
+ setEditingRow(null);
95
+ setLocalLineItem(initialLineItem);
96
+ }
97
+ };
98
+ if (showTagTable) {
99
+ return (_jsx(LineItemTagsTable, { lineItems: state.lineItems, onClose: () => setShowTagTable(false), dispatch: dispatch }));
100
+ }
101
+ return (_jsxs("div", { className: "mt-2 overflow-x-auto", ref: tableRef, children: [_jsxs("div", { className: "flex justify-between mt-6", children: [_jsx("div", { className: "flex items-center", children: _jsx("h1", { className: "text-1xl font-bold", children: "Line Items" }) }), _jsx("div", { className: "flex items-center", children: _jsx(Tag, { style: {
102
+ cursor: "pointer",
103
+ width: 28,
104
+ height: 28,
105
+ color: "white",
106
+ fill: "#475264",
107
+ }, onClick: () => setShowTagTable(!showTagTable) }) })] }), _jsx("div", { className: "mt-4 min-w-[900px]", children: _jsxs("table", { className: "w-full border border-gray-300 text-sm", children: [_jsx("thead", { children: _jsxs("tr", { className: "bg-gray-100", children: [_jsx("th", { className: "border px-2 py-1", children: "#" }), _jsx("th", { className: "border px-2 py-1", children: "Desc" }), _jsx("th", { className: "border px-2 py-1 w-40", children: "Unit" }), _jsx("th", { className: "border px-2 py-1 w-16", children: "Qty" }), _jsx("th", { className: "border px-2 py-1 w-16", children: "FIAT/Uni" }), _jsx("th", { className: "border px-2 py-1 w-16", children: "POWT/Uni" }), _jsx("th", { className: "border px-2 py-1 w-16", children: "Total Fiat" }), _jsx("th", { className: "border px-2 py-1 w-16", children: "Total POW" })] }) }), _jsx("tbody", { children: state.lineItems.map((item, idx) => (editingRow === idx ? (_jsxs("tr", { className: "bg-yellow-50", children: [_jsx("td", { className: "border px-2 py-1 text-center", children: idx + 1 }), _jsx("td", { className: "border px-2 py-1 w-40", children: _jsx(InputField, { input: localLineItem.description, value: localLineItem.description, onBlur: () => { }, handleInputChange: (e) => handleInputChange("description", e.target.value), className: "w-full px-1 py-1 border rounded" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(Select, { options: units, value: localLineItem.unit, onChange: (value) => handleInputChange("unit", value), className: "w-32 px-1 py-1 border rounded" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(NumberForm, { number: localLineItem.quantity, handleInputChange: (e) => handleInputChange("quantity", e.target.value), className: "w-32 px-4 py-1 border rounded text-center" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(NumberForm, { number: localLineItem.unitPriceCash, handleInputChange: (e) => handleInputChange("unitPriceCash", String(e.target.value)), className: "w-32 px-4 py-1 border rounded text-center" }) }), _jsx("td", { className: "border px-2 py-1 w-16", children: _jsx(NumberForm, { number: localLineItem.unitPricePwt, handleInputChange: (e) => handleInputChange("unitPricePwt", e.target.value), className: "w-32 px-4 py-1 border rounded text-center" }) }), _jsx("td", { className: "border px-2 py-1 text-center", children: localLineItem.quantity && localLineItem.unitPriceCash
108
+ ? Number(localLineItem.quantity) * Number(localLineItem.unitPriceCash)
109
+ : "" }), _jsx("td", { className: "border px-2 py-1 text-center", children: localLineItem.quantity && localLineItem.unitPricePwt
110
+ ? Number(localLineItem.quantity) * Number(localLineItem.unitPricePwt)
111
+ : "" })] }, item.id)) : (_jsxs("tr", { className: "hover:bg-gray-50 cursor-pointer", onDoubleClick: () => {
112
+ setEditingRow(idx);
113
+ setLocalLineItem({ ...item });
114
+ }, children: [_jsx("td", { className: "border px-2 py-2 text-center", children: idx + 1 }), _jsx("td", { className: "border px-2 py-2", children: item.description }), _jsx("td", { className: "border px-2 py-2 w-40 text-center", children: item.unit }), _jsx("td", { className: "border px-2 py-2 w-16 text-center", children: item.quantity }), _jsx("td", { className: "border px-2 py-2 w-10 text-center", children: formatNumber(item.unitPriceCash) }), _jsx("td", { className: "border px-2 py-2 w-10 text-center", children: formatNumber(item.unitPricePwt) }), _jsx("td", { className: "border px-2 py-2 text-center", children: formatNumber(item.totalPriceCash) }), _jsx("td", { className: "border px-2 py-2 text-center", children: formatNumber(item.totalPricePwt) })] }, item.id)))) })] }) })] }));
115
+ };
116
+ export default LineItemsTable;