@powerhousedao/contributor-billing 0.0.99 → 0.1.1
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.
- package/dist/document-models/billing-statement/src/reducers/general.d.ts.map +1 -1
- package/dist/document-models/billing-statement/src/reducers/general.js +8 -26
- package/dist/document-models/billing-statement/src/reducers/line-items.d.ts.map +1 -1
- package/dist/document-models/billing-statement/src/reducers/line-items.js +19 -29
- package/dist/document-models/billing-statement/src/reducers/tags.d.ts.map +1 -1
- package/dist/document-models/billing-statement/src/reducers/tags.js +20 -25
- package/dist/document-models/integrations/src/reducers/integrations.d.ts.map +1 -1
- package/dist/document-models/integrations/src/reducers/integrations.js +29 -44
- package/dist/document-models/invoice/src/reducers/general.d.ts.map +1 -1
- package/dist/document-models/invoice/src/reducers/general.js +31 -56
- package/dist/document-models/invoice/src/reducers/items.d.ts.map +1 -1
- package/dist/document-models/invoice/src/reducers/items.js +63 -88
- package/dist/document-models/invoice/src/reducers/parties.d.ts.map +1 -1
- package/dist/document-models/invoice/src/reducers/parties.js +199 -229
- package/dist/editors/billing-statement/components/lineItemsTable.d.ts +3 -2
- package/dist/editors/billing-statement/components/lineItemsTable.d.ts.map +1 -1
- package/dist/editors/billing-statement/components/lineItemsTable.js +12 -8
- package/dist/editors/billing-statement/components/objectSetTable.d.ts +3 -2
- package/dist/editors/billing-statement/components/objectSetTable.d.ts.map +1 -1
- package/dist/editors/billing-statement/editor.d.ts +3 -1
- package/dist/editors/billing-statement/editor.d.ts.map +1 -1
- package/dist/editors/billing-statement/editor.js +2 -2
- package/dist/editors/billing-statement/lineItemTags/lineItemTags.d.ts +2 -2
- package/dist/editors/billing-statement/lineItemTags/lineItemTags.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/DriveExplorer.d.ts +8 -1
- package/dist/editors/contributor-billing/components/DriveExplorer.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/DriveExplorer.js +18 -64
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts +2 -8
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.js +21 -7
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts +8 -10
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.js +27 -24
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableRow.d.ts +6 -8
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableRow.d.ts.map +1 -1
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableRow.js +8 -17
- package/dist/editors/contributor-billing/editor.d.ts +1 -10
- package/dist/editors/contributor-billing/editor.d.ts.map +1 -1
- package/dist/editors/contributor-billing/editor.js +2 -23
- package/dist/editors/contributor-billing/hooks/useTransformedNodes.d.ts +2 -1
- package/dist/editors/contributor-billing/hooks/useTransformedNodes.d.ts.map +1 -1
- package/dist/editors/contributor-billing/index.js +1 -1
- package/dist/editors/hooks/useBillingStatementDocument.d.ts +4 -0
- package/dist/editors/hooks/useBillingStatementDocument.d.ts.map +1 -0
- package/dist/editors/hooks/useBillingStatementDocument.js +8 -0
- package/dist/editors/hooks/useIntegrationsDocument.d.ts +4 -0
- package/dist/editors/hooks/useIntegrationsDocument.d.ts.map +1 -0
- package/dist/editors/hooks/useIntegrationsDocument.js +8 -0
- package/dist/editors/hooks/useInvoiceDocument.d.ts +4 -0
- package/dist/editors/hooks/useInvoiceDocument.d.ts.map +1 -0
- package/dist/editors/hooks/useInvoiceDocument.js +8 -0
- package/dist/editors/integrations/editor.d.ts +4 -1
- package/dist/editors/integrations/editor.d.ts.map +1 -1
- package/dist/editors/integrations/editor.js +7 -12
- package/dist/editors/invoice/editor.d.ts +4 -1
- package/dist/editors/invoice/editor.d.ts.map +1 -1
- package/dist/editors/invoice/editor.js +5 -4
- package/dist/editors/invoice/ingestPDF.d.ts.map +1 -1
- package/dist/editors/invoice/ingestPDF.js +3 -3
- package/dist/editors/invoice/invoiceToGnosis.d.ts +3 -2
- package/dist/editors/invoice/invoiceToGnosis.d.ts.map +1 -1
- package/dist/editors/invoice/invoiceToGnosis.js +11 -11
- package/dist/editors/invoice/legalEntity/bankSection.d.ts +1 -0
- package/dist/editors/invoice/legalEntity/bankSection.d.ts.map +1 -1
- package/dist/editors/invoice/legalEntity/bankSection.js +36 -12
- package/dist/editors/invoice/legalEntity/legalEntity.d.ts +2 -1
- package/dist/editors/invoice/legalEntity/legalEntity.d.ts.map +1 -1
- package/dist/editors/invoice/legalEntity/legalEntity.js +2 -2
- package/dist/editors/invoice/lineItemTags/lineItemTags.d.ts.map +1 -1
- package/dist/editors/invoice/lineItems.d.ts.map +1 -1
- package/dist/editors/invoice/lineItems.js +8 -6
- package/dist/editors/invoice/requestFinance.js +2 -2
- package/dist/editors/invoice/uploadPdfChunked.js +1 -1
- package/dist/editors/invoice/validation/validationHandler.d.ts +1 -1
- package/dist/editors/invoice/validation/validationHandler.d.ts.map +1 -1
- package/dist/editors/invoice/validation/validationHandler.js +25 -9
- package/dist/editors/invoice/validation/validationManager.d.ts.map +1 -1
- package/dist/editors/invoice/validation/validationManager.js +3 -2
- package/dist/editors/invoice/validation/validationRules.d.ts +2 -0
- package/dist/editors/invoice/validation/validationRules.d.ts.map +1 -1
- package/dist/editors/invoice/validation/validationRules.js +37 -7
- package/dist/scripts/contributor-billing/createExpenseReportCsv.d.ts +5 -0
- package/dist/scripts/contributor-billing/createExpenseReportCsv.d.ts.map +1 -0
- package/dist/scripts/contributor-billing/createExpenseReportCsv.js +122 -0
- package/dist/style.css +9 -6
- package/package.json +12 -12
- package/dist/reducers/general.d.ts +0 -8
- package/dist/reducers/general.d.ts.map +0 -1
- package/dist/reducers/general.js +0 -73
- package/dist/reducers/items.d.ts +0 -8
- package/dist/reducers/items.d.ts.map +0 -1
- package/dist/reducers/items.js +0 -195
- package/dist/reducers/parties.d.ts +0 -8
- package/dist/reducers/parties.d.ts.map +0 -1
- package/dist/reducers/parties.js +0 -266
- package/dist/reducers/transitions.d.ts +0 -8
- package/dist/reducers/transitions.d.ts.map +0 -1
- package/dist/reducers/transitions.js +0 -162
|
@@ -3,8 +3,8 @@ import { useState } from "react";
|
|
|
3
3
|
import { actions } from "../../document-models/invoice/index.js";
|
|
4
4
|
import { generateId } from "document-model";
|
|
5
5
|
let GRAPHQL_URL = "http://localhost:4001/graphql/invoice";
|
|
6
|
-
if (!window.document.baseURI.includes(
|
|
7
|
-
GRAPHQL_URL =
|
|
6
|
+
if (!window.document.baseURI.includes("localhost")) {
|
|
7
|
+
GRAPHQL_URL = "https://switchboard-staging.powerhouse.xyz/graphql/invoice";
|
|
8
8
|
}
|
|
9
9
|
const RequestFinance = ({ docState, dispatch, }) => {
|
|
10
10
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
let GRAPHQL_URL = 'http://localhost:4001/graphql/invoice';
|
|
9
9
|
if (!window.document.baseURI.includes('localhost')) {
|
|
10
|
-
GRAPHQL_URL = 'https://switchboard-
|
|
10
|
+
GRAPHQL_URL = 'https://switchboard-staging.powerhouse.xyz/graphql/invoice';
|
|
11
11
|
}
|
|
12
12
|
export async function uploadPdfChunked(pdfData, endpoint = GRAPHQL_URL, chunkSize = 500 * 1024, // 500KB chunks
|
|
13
13
|
onProgress) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { ValidationResult } from "./validationManager.js";
|
|
2
|
-
declare const validateStatusBeforeContinue: (newStatus: string, state: any, setInvoiceValidation: (validation: ValidationResult) => void, setWalletValidation: (validation: ValidationResult) => void, setCurrencyValidation: (validation: ValidationResult) => void, setMainCountryValidation: (validation: ValidationResult) => void, setBankCountryValidation: (validation: ValidationResult) => void, setIbanValidation: (validation: ValidationResult) => void, setBicValidation: (validation: ValidationResult) => void, setBankNameValidation: (validation: ValidationResult) => void, setStreetAddressValidation: (validation: ValidationResult) => void, setCityValidation: (validation: ValidationResult) => void, setPostalCodeValidation: (validation: ValidationResult) => void, setPayerEmailValidation: (validation: ValidationResult) => void, setLineItemValidation: (validation: ValidationResult) => void, setRoutingNumberValidation: (validation: ValidationResult) => void, isFiatCurrency: (currency: string) => boolean) => boolean | undefined;
|
|
2
|
+
declare const validateStatusBeforeContinue: (newStatus: string, state: any, setInvoiceValidation: (validation: ValidationResult) => void, setWalletValidation: (validation: ValidationResult) => void, setCurrencyValidation: (validation: ValidationResult) => void, setMainCountryValidation: (validation: ValidationResult) => void, setBankCountryValidation: (validation: ValidationResult) => void, setIbanValidation: (validation: ValidationResult) => void, setBicValidation: (validation: ValidationResult) => void, setAccountNumberValidation: (validation: ValidationResult) => void, setBankNameValidation: (validation: ValidationResult) => void, setStreetAddressValidation: (validation: ValidationResult) => void, setCityValidation: (validation: ValidationResult) => void, setPostalCodeValidation: (validation: ValidationResult) => void, setPayerEmailValidation: (validation: ValidationResult) => void, setLineItemValidation: (validation: ValidationResult) => void, setRoutingNumberValidation: (validation: ValidationResult) => void, isFiatCurrency: (currency: string) => boolean) => boolean | undefined;
|
|
3
3
|
export default validateStatusBeforeContinue;
|
|
4
4
|
//# sourceMappingURL=validationHandler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validationHandler.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/validation/validationHandler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validationHandler.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/validation/validationHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAoC,MAAM,wBAAwB,CAAC;AAI5F,QAAA,MAAM,4BAA4B,GAC9B,WAAW,MAAM,EACjB,OAAO,GAAG,EACV,sBAAsB,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EAC5D,qBAAqB,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EAC3D,uBAAuB,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EAC7D,0BAA0B,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EAChE,0BAA0B,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EAChE,mBAAmB,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EACzD,kBAAkB,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EACxD,4BAA4B,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EAClE,uBAAuB,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EAC7D,4BAA4B,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EAClE,mBAAmB,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EACzD,yBAAyB,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EAC/D,yBAAyB,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EAC/D,uBAAuB,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EAC7D,4BAA4B,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EAClE,gBAAgB,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,wBAqNhD,CAAA;AAED,eAAe,4BAA4B,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { validateField } from "./validationManager.js";
|
|
2
2
|
import { toast } from "@powerhousedao/design-system";
|
|
3
|
-
|
|
3
|
+
import { isValidIBAN } from "./validationRules.js";
|
|
4
|
+
const validateStatusBeforeContinue = (newStatus, state, setInvoiceValidation, setWalletValidation, setCurrencyValidation, setMainCountryValidation, setBankCountryValidation, setIbanValidation, setBicValidation, setAccountNumberValidation, setBankNameValidation, setStreetAddressValidation, setCityValidation, setPostalCodeValidation, setPayerEmailValidation, setLineItemValidation, setRoutingNumberValidation, isFiatCurrency) => {
|
|
4
5
|
if (newStatus === "PAYMENTSCHEDULED" || newStatus === "ISSUED") {
|
|
5
6
|
const context = {
|
|
6
7
|
currency: state.currency,
|
|
@@ -43,11 +44,25 @@ const validateStatusBeforeContinue = (newStatus, state, setInvoiceValidation, se
|
|
|
43
44
|
if (bankCountryValidation && !bankCountryValidation.isValid) {
|
|
44
45
|
validationErrors.push(bankCountryValidation);
|
|
45
46
|
}
|
|
46
|
-
// Validate
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
// Validate account number or IBAN depending on currency to avoid duplicate validation of the same field
|
|
48
|
+
const IBAN_CURRENCIES = ["EUR", "GBP", "DKK"];
|
|
49
|
+
if (IBAN_CURRENCIES.includes(state.currency)) {
|
|
50
|
+
// Only IBAN applies
|
|
51
|
+
const ibanValidation = validateField("accountNum", state.issuer.paymentRouting?.bank?.accountNum, context);
|
|
52
|
+
setIbanValidation(ibanValidation);
|
|
53
|
+
setAccountNumberValidation(null);
|
|
54
|
+
if (ibanValidation && !ibanValidation.isValid) {
|
|
55
|
+
validationErrors.push(ibanValidation);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// Generic account number applies
|
|
60
|
+
const accountNumberValidation = validateField("accountNum", state.issuer.paymentRouting?.bank?.accountNum, context);
|
|
61
|
+
setAccountNumberValidation(accountNumberValidation);
|
|
62
|
+
setIbanValidation(null);
|
|
63
|
+
if (accountNumberValidation && !accountNumberValidation.isValid) {
|
|
64
|
+
validationErrors.push(accountNumberValidation);
|
|
65
|
+
}
|
|
51
66
|
}
|
|
52
67
|
// Validate BIC/SWIFT number
|
|
53
68
|
const bicValidation = validateField("bicNumber", state.issuer.paymentRouting?.bank?.BIC || state.issuer.paymentRouting?.bank?.SWIFT, context);
|
|
@@ -57,9 +72,10 @@ const validateStatusBeforeContinue = (newStatus, state, setInvoiceValidation, se
|
|
|
57
72
|
}
|
|
58
73
|
// Validate routing number
|
|
59
74
|
const routingNumberValidation = validateField("routingNumber", state.issuer.paymentRouting?.bank?.ABA, context);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
75
|
+
const usdIbanPayment = isValidIBAN(state.issuer.paymentRouting?.bank?.accountNum ?? "") && state.currency === "USD";
|
|
76
|
+
setRoutingNumberValidation(usdIbanPayment ? null : routingNumberValidation);
|
|
77
|
+
if (usdIbanPayment ? null : routingNumberValidation && !routingNumberValidation.isValid) {
|
|
78
|
+
validationErrors.push(usdIbanPayment ? { isValid: true, message: '', severity: 'none' } : routingNumberValidation);
|
|
63
79
|
}
|
|
64
80
|
// Validate bank name
|
|
65
81
|
const bankNameValidation = validateField("bankName", state.issuer.paymentRouting?.bank?.name, context);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validationManager.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/validation/validationManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"validationManager.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/validation/validationManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAoBnE,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAE9D,MAAM,MAAM,gBAAgB,GAAG;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,kBAAkB,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,gBAAgB,CAAC;IAC1D,SAAS,EAAE;QACP,UAAU,EAAE,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC;QAClC,iBAAiB,EAAE;YACf,IAAI,EAAE,MAAM,EAAE,CAAC;YACf,EAAE,EAAE,MAAM,EAAE,CAAC;SAChB,CAAC;KACL,CAAC;CACL,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACxB,CAAC;AAiCF,wBAAgB,aAAa,CACzB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,GAAG,EACV,OAAO,EAAE,iBAAiB,GAC3B,gBAAgB,GAAG,IAAI,CAqBzB;AAGD,wBAAgB,wBAAwB,CACpC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,OAAO,EAAE,iBAAiB,GAC3B,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAalC;AAGD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAE5D;AAGD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAKxD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { accountIbanRule, bicNumberRule, bankNameRule, currencyRule, ethereumAddressRule, invoiceNumberRule, issuerPostalCodeRule, issuerStreetAddressRule, issuerCityRule, payerEmailRule, lineItemRule, mainCountryRule, bankCountryRule, routingNumberRule, accountNumberRule } from "./validationRules.js";
|
|
2
2
|
// Validation rules registry
|
|
3
3
|
const validationRules = [];
|
|
4
4
|
// Register rules
|
|
@@ -7,7 +7,7 @@ validationRules.push(ethereumAddressRule);
|
|
|
7
7
|
validationRules.push(currencyRule);
|
|
8
8
|
validationRules.push(mainCountryRule);
|
|
9
9
|
validationRules.push(bankCountryRule);
|
|
10
|
-
validationRules.push(
|
|
10
|
+
validationRules.push(accountIbanRule);
|
|
11
11
|
validationRules.push(bicNumberRule);
|
|
12
12
|
validationRules.push(bankNameRule);
|
|
13
13
|
validationRules.push(issuerStreetAddressRule);
|
|
@@ -16,6 +16,7 @@ validationRules.push(issuerPostalCodeRule);
|
|
|
16
16
|
validationRules.push(payerEmailRule);
|
|
17
17
|
validationRules.push(lineItemRule);
|
|
18
18
|
validationRules.push(routingNumberRule);
|
|
19
|
+
validationRules.push(accountNumberRule);
|
|
19
20
|
// Helper to check if a rule applies to the current context
|
|
20
21
|
function ruleAppliesToContext(rule, context) {
|
|
21
22
|
const { currencies, statusTransitions } = rule.appliesTo;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { ValidationRule } from "./validationManager.js";
|
|
2
|
+
export declare function isValidIBAN(iban: string): boolean;
|
|
2
3
|
export declare const invoiceNumberRule: ValidationRule;
|
|
3
4
|
export declare const ethereumAddressRule: ValidationRule;
|
|
4
5
|
export declare const currencyRule: ValidationRule;
|
|
5
6
|
export declare const mainCountryRule: ValidationRule;
|
|
6
7
|
export declare const bankCountryRule: ValidationRule;
|
|
8
|
+
export declare const accountIbanRule: ValidationRule;
|
|
7
9
|
export declare const accountNumberRule: ValidationRule;
|
|
8
10
|
export declare const bicNumberRule: ValidationRule;
|
|
9
11
|
export declare const bankNameRule: ValidationRule;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validationRules.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/validation/validationRules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"validationRules.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/validation/validationRules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAQxD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAYjD;AAQD,eAAO,MAAM,iBAAiB,EAAE,cAuB/B,CAAC;AAGF,eAAO,MAAM,mBAAmB,EAAE,cA8BjC,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,cAuB1B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,cAuB7B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,cAuB7B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,cA8B7B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,cA+B/B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,cAkC3B,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,cAuB1B,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,cAuBrC,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,cAuB5B,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,cAuBlC,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,cA8B5B,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,cAuB1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,cAqC/B,CAAC"}
|
|
@@ -3,17 +3,15 @@ function isValidEthereumAddress(address) {
|
|
|
3
3
|
const ethereumAddressRegex = /^0x[a-fA-F0-9]{40}$/;
|
|
4
4
|
return ethereumAddressRegex.test(address);
|
|
5
5
|
}
|
|
6
|
-
function isValidIBAN(iban) {
|
|
7
|
-
const ibanRegex = /^([A-Z]{2}[0-9]{2})(?=(?:[A-Z0-9]){9,30}$)((?:[A-Z0-9]{3,5}){2,7})([A-Z0-9]{1,3})?$/;
|
|
8
|
-
const hasNumbers = /\d/.test(iban);
|
|
6
|
+
export function isValidIBAN(iban) {
|
|
7
|
+
const ibanRegex = /^([A-Z]{2}[-]?[0-9]{2})(?=(?:[ -]?[A-Z0-9]){9,30}$)((?:[ -]?[A-Z0-9]{3,5}){2,7})([-]?[A-Z0-9]{1,3})?$/;
|
|
9
8
|
// Extract country code from IBAN (first 2 letters)
|
|
10
9
|
const countryCode = iban.substring(0, 2).toUpperCase();
|
|
11
10
|
// If IBAN starts with a valid country code (2 letters), validate full IBAN format
|
|
12
11
|
if (/^[A-Z]{2}$/.test(countryCode)) {
|
|
13
12
|
return ibanRegex.test(iban);
|
|
14
13
|
}
|
|
15
|
-
|
|
16
|
-
return iban.trim() !== '' && hasNumbers;
|
|
14
|
+
return false;
|
|
17
15
|
}
|
|
18
16
|
function isValidEmail(email) {
|
|
19
17
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
@@ -148,7 +146,7 @@ export const bankCountryRule = {
|
|
|
148
146
|
}
|
|
149
147
|
}
|
|
150
148
|
};
|
|
151
|
-
export const
|
|
149
|
+
export const accountIbanRule = {
|
|
152
150
|
field: 'accountNum',
|
|
153
151
|
validate: (value, document) => {
|
|
154
152
|
if (!value || value.trim() === '') {
|
|
@@ -172,7 +170,39 @@ export const accountNumberRule = {
|
|
|
172
170
|
};
|
|
173
171
|
},
|
|
174
172
|
appliesTo: {
|
|
175
|
-
currencies: ['EUR', 'GBP'],
|
|
173
|
+
currencies: ['EUR', 'GBP', 'DKK'],
|
|
174
|
+
statusTransitions: {
|
|
175
|
+
from: ['DRAFT'],
|
|
176
|
+
to: ['ISSUED']
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
export const accountNumberRule = {
|
|
181
|
+
field: 'accountNum',
|
|
182
|
+
validate: (value) => {
|
|
183
|
+
if (!value || value.trim() === '') {
|
|
184
|
+
return {
|
|
185
|
+
isValid: false,
|
|
186
|
+
message: 'Account number is required',
|
|
187
|
+
severity: 'warning'
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
// Valid account numbers are 6-25 alphanumeric characters. If it DOES NOT match, it's invalid.
|
|
191
|
+
if (!/^[\da-zA-Z]{6,25}$/.test(value)) {
|
|
192
|
+
return {
|
|
193
|
+
isValid: false,
|
|
194
|
+
message: 'Invalid account number format - For account number, ensure it is 6-25 characters long',
|
|
195
|
+
severity: 'warning'
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
isValid: true,
|
|
200
|
+
message: '',
|
|
201
|
+
severity: 'none'
|
|
202
|
+
};
|
|
203
|
+
},
|
|
204
|
+
appliesTo: {
|
|
205
|
+
currencies: ['USD', 'JPY', 'CNY', 'CHF'],
|
|
176
206
|
statusTransitions: {
|
|
177
207
|
from: ['DRAFT'],
|
|
178
208
|
to: ['ISSUED']
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createExpenseReportCsv.d.ts","sourceRoot":"","sources":["../../../scripts/contributor-billing/createExpenseReportCsv.ts"],"names":[],"mappings":"AA+CA;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,aAAa,EAAE,GAAG,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgGtG"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Simple in-memory cache for exchange rates
|
|
2
|
+
const exchangeRateCache = {};
|
|
3
|
+
/**
|
|
4
|
+
* Fetches the exchange rate from `from` currency to `to` currency for a given date using Frankfurter API.
|
|
5
|
+
* Returns 1 for unsupported currencies or errors.
|
|
6
|
+
*/
|
|
7
|
+
async function getExchangeRate(date, from, to) {
|
|
8
|
+
if (!date || !from || !to || from === to)
|
|
9
|
+
return 1;
|
|
10
|
+
// Convert crypto currencies to USD for API compatibility
|
|
11
|
+
let effectiveFrom = from;
|
|
12
|
+
if (from === 'DAI' || from === 'USDS') {
|
|
13
|
+
effectiveFrom = 'USD';
|
|
14
|
+
}
|
|
15
|
+
let effectiveTo = to;
|
|
16
|
+
if (to === 'DAI' || to === 'USDS') {
|
|
17
|
+
effectiveTo = 'USD';
|
|
18
|
+
}
|
|
19
|
+
const formattedDate = date.split('T')[0];
|
|
20
|
+
const cacheKey = `${formattedDate}|${effectiveFrom}|${effectiveTo}`;
|
|
21
|
+
if (exchangeRateCache[cacheKey] !== undefined) {
|
|
22
|
+
return exchangeRateCache[cacheKey];
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const url = `https://api.frankfurter.dev/v1/${formattedDate}?base=${effectiveFrom}&symbols=${effectiveTo}`;
|
|
26
|
+
console.log('Fetching from Frankfurter URL:', url);
|
|
27
|
+
const res = await fetch(url);
|
|
28
|
+
if (!res.ok) {
|
|
29
|
+
throw new Error(`Failed to fetch Frankfurter exchange rate: ${res.status} ${res.statusText}`);
|
|
30
|
+
}
|
|
31
|
+
const data = await res.json();
|
|
32
|
+
const rate = data?.rates?.[effectiveTo];
|
|
33
|
+
if (typeof rate !== 'number') {
|
|
34
|
+
throw new Error(`Frankfurter exchange rate for ${effectiveFrom} to ${effectiveTo} on ${formattedDate} not found in response`);
|
|
35
|
+
}
|
|
36
|
+
exchangeRateCache[cacheKey] = rate;
|
|
37
|
+
return rate;
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
console.error('Frankfurter ForEx API error:', err);
|
|
41
|
+
return 1; // Fallback to 1:1 on error
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Creates an expense report CSV that categorizes line items by their tags
|
|
46
|
+
*/
|
|
47
|
+
export async function exportExpenseReportCSV(invoiceStates, baseCurrency) {
|
|
48
|
+
// Track invoices missing tags
|
|
49
|
+
const missingTagInvoices = [];
|
|
50
|
+
// Data structure to aggregate expenses by tag label
|
|
51
|
+
const expensesByTag = {};
|
|
52
|
+
// Process each selected invoice
|
|
53
|
+
for (const invoiceState of invoiceStates) {
|
|
54
|
+
const state = invoiceState.state.global;
|
|
55
|
+
const invoiceId = invoiceState.header.id;
|
|
56
|
+
const invoiceName = state.name || invoiceId;
|
|
57
|
+
const items = state.lineItems || [];
|
|
58
|
+
const dateIssued = state.dateIssued;
|
|
59
|
+
const currency = state.currency || 'USD';
|
|
60
|
+
// Check if any line item is missing tags
|
|
61
|
+
const hasMissingTags = items.some((item) => {
|
|
62
|
+
return !item.lineItemTag || item.lineItemTag.length === 0;
|
|
63
|
+
});
|
|
64
|
+
if (hasMissingTags) {
|
|
65
|
+
missingTagInvoices.push(invoiceName);
|
|
66
|
+
continue; // Skip this invoice
|
|
67
|
+
}
|
|
68
|
+
// Get exchange rate for this invoice
|
|
69
|
+
let effectiveCurrency = currency;
|
|
70
|
+
if (currency === 'DAI' || currency === 'USDS') {
|
|
71
|
+
effectiveCurrency = 'USD';
|
|
72
|
+
}
|
|
73
|
+
const exchangeRate = await getExchangeRate(dateIssued, effectiveCurrency, baseCurrency);
|
|
74
|
+
// Aggregate line items by tag
|
|
75
|
+
items.forEach((item) => {
|
|
76
|
+
const lineItemTags = item.lineItemTag || [];
|
|
77
|
+
const lineItemTotal = item.totalPriceTaxIncl || 0;
|
|
78
|
+
const convertedAmount = lineItemTotal * exchangeRate;
|
|
79
|
+
lineItemTags.forEach((tag) => {
|
|
80
|
+
const dimension = tag.dimension || '';
|
|
81
|
+
const label = tag.label || tag.value || 'Unknown';
|
|
82
|
+
// Skip accounting-period dimension
|
|
83
|
+
if (dimension === 'accounting-period') {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// Aggregate by tag label in base currency
|
|
87
|
+
if (!expensesByTag[label]) {
|
|
88
|
+
expensesByTag[label] = 0;
|
|
89
|
+
}
|
|
90
|
+
expensesByTag[label] += convertedAmount;
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
// If any invoices are missing tags, throw an error
|
|
95
|
+
if (missingTagInvoices.length > 0) {
|
|
96
|
+
throw {
|
|
97
|
+
message: `The following invoices have line items missing tags: ${[...new Set(missingTagInvoices)].join(', ')}`,
|
|
98
|
+
missingTagInvoices: missingTagInvoices
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// Create CSV headers
|
|
102
|
+
const headers = ['Tag Label', 'Currency', 'Total Amount'];
|
|
103
|
+
// Convert aggregated data to rows
|
|
104
|
+
const expenseRows = Object.entries(expensesByTag)
|
|
105
|
+
.sort(([labelA], [labelB]) => labelA.localeCompare(labelB))
|
|
106
|
+
.map(([label, total]) => [label, baseCurrency, total.toFixed(2)]);
|
|
107
|
+
// Combine headers and data rows
|
|
108
|
+
const allRows = [headers, ...expenseRows];
|
|
109
|
+
// Convert to CSV format
|
|
110
|
+
const csvLines = allRows.map((row) => row.map((value) => `"${value}"`).join(','));
|
|
111
|
+
const csvData = csvLines.join('\n');
|
|
112
|
+
// Download CSV file (browser)
|
|
113
|
+
const blob = new Blob([csvData], { type: 'text/csv;charset=utf-8;' });
|
|
114
|
+
const link = document.createElement('a');
|
|
115
|
+
const url = URL.createObjectURL(blob);
|
|
116
|
+
link.setAttribute('href', url);
|
|
117
|
+
link.setAttribute('download', `expense-report-by-tag-${new Date().toISOString().split('T')[0]}.csv`);
|
|
118
|
+
link.style.visibility = 'hidden';
|
|
119
|
+
document.body.appendChild(link);
|
|
120
|
+
link.click();
|
|
121
|
+
document.body.removeChild(link);
|
|
122
|
+
}
|
package/dist/style.css
CHANGED
|
@@ -315,9 +315,6 @@
|
|
|
315
315
|
.z-10 {
|
|
316
316
|
z-index: 10;
|
|
317
317
|
}
|
|
318
|
-
.z-40 {
|
|
319
|
-
z-index: 40;
|
|
320
|
-
}
|
|
321
318
|
.z-50 {
|
|
322
319
|
z-index: 50;
|
|
323
320
|
}
|
|
@@ -408,9 +405,6 @@
|
|
|
408
405
|
.inline {
|
|
409
406
|
display: inline;
|
|
410
407
|
}
|
|
411
|
-
.inline-block {
|
|
412
|
-
display: inline-block;
|
|
413
|
-
}
|
|
414
408
|
.inline-flex {
|
|
415
409
|
display: inline-flex;
|
|
416
410
|
}
|
|
@@ -454,6 +448,9 @@
|
|
|
454
448
|
.h-32 {
|
|
455
449
|
height: calc(var(--spacing) * 32);
|
|
456
450
|
}
|
|
451
|
+
.h-\[29px\] {
|
|
452
|
+
height: 29px;
|
|
453
|
+
}
|
|
457
454
|
.h-full {
|
|
458
455
|
height: 100%;
|
|
459
456
|
}
|
|
@@ -487,6 +484,9 @@
|
|
|
487
484
|
.w-16 {
|
|
488
485
|
width: calc(var(--spacing) * 16);
|
|
489
486
|
}
|
|
487
|
+
.w-20 {
|
|
488
|
+
width: calc(var(--spacing) * 20);
|
|
489
|
+
}
|
|
490
490
|
.w-32 {
|
|
491
491
|
width: calc(var(--spacing) * 32);
|
|
492
492
|
}
|
|
@@ -499,6 +499,9 @@
|
|
|
499
499
|
.w-50 {
|
|
500
500
|
width: calc(var(--spacing) * 50);
|
|
501
501
|
}
|
|
502
|
+
.w-54 {
|
|
503
|
+
width: calc(var(--spacing) * 54);
|
|
504
|
+
}
|
|
502
505
|
.w-64 {
|
|
503
506
|
width: calc(var(--spacing) * 64);
|
|
504
507
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powerhousedao/contributor-billing",
|
|
3
3
|
"description": "Document models that help contributors of open organisations get paid anonymously for their work on a monthly basis.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.1.1",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
@@ -57,9 +57,9 @@
|
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"@google-cloud/documentai": "^8.12.0",
|
|
60
|
-
"@powerhousedao/builder-tools": "^5.0.0-staging.
|
|
61
|
-
"@powerhousedao/common": "^5.0.0-staging.
|
|
62
|
-
"@powerhousedao/design-system": "^5.0.0-staging.
|
|
60
|
+
"@powerhousedao/builder-tools": "^5.0.0-staging.25",
|
|
61
|
+
"@powerhousedao/common": "^5.0.0-staging.25",
|
|
62
|
+
"@powerhousedao/design-system": "^5.0.0-staging.25",
|
|
63
63
|
"@powerhousedao/document-engineering": "^1.38.0",
|
|
64
64
|
"@react-pdf/renderer": "^4.3.0",
|
|
65
65
|
"@safe-global/api-kit": "^3.0.1",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"@types/cors": "^2.8.17",
|
|
70
70
|
"axios": "^1.9.0",
|
|
71
71
|
"cors": "^2.8.5",
|
|
72
|
-
"document-model": "^5.0.0-staging.
|
|
72
|
+
"document-model": "^5.0.0-staging.25",
|
|
73
73
|
"dotenv": "^16.5.0",
|
|
74
74
|
"error": "^10.4.0",
|
|
75
75
|
"ethers": "^6.14.0",
|
|
@@ -86,19 +86,19 @@
|
|
|
86
86
|
"@eslint/js": "^9.25.0",
|
|
87
87
|
"@playwright/test": "^1.56.0",
|
|
88
88
|
"@powerhousedao/analytics-engine-core": "^0.5.0",
|
|
89
|
-
"@powerhousedao/codegen": "^5.0.0-staging.
|
|
90
|
-
"@powerhousedao/ph-cli": "^5.0.0-staging.
|
|
91
|
-
"@powerhousedao/reactor-api": "^5.0.0-staging.
|
|
92
|
-
"@powerhousedao/reactor-browser": "^5.0.0-staging.
|
|
93
|
-
"@powerhousedao/reactor-local": "^5.0.0-staging.
|
|
89
|
+
"@powerhousedao/codegen": "^5.0.0-staging.25",
|
|
90
|
+
"@powerhousedao/ph-cli": "^5.0.0-staging.25",
|
|
91
|
+
"@powerhousedao/reactor-api": "^5.0.0-staging.25",
|
|
92
|
+
"@powerhousedao/reactor-browser": "^5.0.0-staging.25",
|
|
93
|
+
"@powerhousedao/reactor-local": "^5.0.0-staging.25",
|
|
94
94
|
"@powerhousedao/scalars": "^1.33.1-staging.5",
|
|
95
|
-
"@powerhousedao/switchboard": "^5.0.0-staging.
|
|
95
|
+
"@powerhousedao/switchboard": "^5.0.0-staging.25",
|
|
96
96
|
"@tailwindcss/cli": "^4.1.4",
|
|
97
97
|
"@testing-library/react": "^16.3.0",
|
|
98
98
|
"@types/node": "^22.14.1",
|
|
99
99
|
"@types/react": "^18.3.20",
|
|
100
100
|
"@vitejs/plugin-react": "^4.4.1",
|
|
101
|
-
"document-drive": "^5.0.0-staging.
|
|
101
|
+
"document-drive": "^5.0.0-staging.25",
|
|
102
102
|
"eslint": "^9.25.0",
|
|
103
103
|
"eslint-plugin-react": "^7.37.5",
|
|
104
104
|
"eslint-plugin-react-hooks": "^5.2.0",
|
|
@@ -1,8 +0,0 @@
|
|
|
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 { InvoiceGeneralOperations } from "../../gen/general/operations.js";
|
|
7
|
-
export declare const reducer: InvoiceGeneralOperations;
|
|
8
|
-
//# sourceMappingURL=general.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"general.d.ts","sourceRoot":"","sources":["../../reducers/general.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAEhF,eAAO,MAAM,OAAO,EAAE,wBAkErB,CAAC"}
|
package/dist/reducers/general.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
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
|
-
editInvoiceOperation(state, action, dispatch) {
|
|
8
|
-
try {
|
|
9
|
-
const newState = { ...state };
|
|
10
|
-
newState.currency = action.input.currency ?? state.currency;
|
|
11
|
-
newState.dateDue = action.input.dateDue ?? state.dateDue;
|
|
12
|
-
newState.dateIssued = action.input.dateIssued ?? state.dateIssued;
|
|
13
|
-
newState.invoiceNo = action.input.invoiceNo ?? state.invoiceNo;
|
|
14
|
-
newState.notes = action.input.notes ?? state.notes;
|
|
15
|
-
state = Object.assign(state, newState);
|
|
16
|
-
}
|
|
17
|
-
catch (e) {
|
|
18
|
-
console.error(e);
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
editStatusOperation(state, action, dispatch) {
|
|
22
|
-
try {
|
|
23
|
-
state.status = action.input.status;
|
|
24
|
-
}
|
|
25
|
-
catch (e) {
|
|
26
|
-
console.error(e);
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
editPaymentDataOperation(state, action, dispatch) {
|
|
30
|
-
try {
|
|
31
|
-
const payment = state.payments.find((payment) => payment.id === action.input.id);
|
|
32
|
-
if (payment) {
|
|
33
|
-
payment.processorRef = action.input.processorRef ?? payment.processorRef;
|
|
34
|
-
payment.paymentDate = action.input.paymentDate ?? payment.paymentDate;
|
|
35
|
-
payment.txnRef = action.input.txnRef ?? payment.txnRef;
|
|
36
|
-
payment.confirmed = action.input.confirmed ?? payment.confirmed;
|
|
37
|
-
payment.issue = action.input.issue ?? payment.issue;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
catch (e) {
|
|
41
|
-
console.error(e);
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
addPaymentOperation(state, action, dispatch) {
|
|
45
|
-
try {
|
|
46
|
-
const payment = {
|
|
47
|
-
id: action.input.id,
|
|
48
|
-
processorRef: action.input.processorRef ?? "",
|
|
49
|
-
paymentDate: action.input.paymentDate ?? "",
|
|
50
|
-
txnRef: action.input.txnRef ?? "",
|
|
51
|
-
confirmed: action.input.confirmed ?? false,
|
|
52
|
-
issue: action.input.issue ?? "",
|
|
53
|
-
amount: 0,
|
|
54
|
-
};
|
|
55
|
-
state.payments.push(payment);
|
|
56
|
-
}
|
|
57
|
-
catch (e) {
|
|
58
|
-
console.error(e);
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
setExportedDataOperation(state, action, dispatch) {
|
|
62
|
-
try {
|
|
63
|
-
const exportedData = {
|
|
64
|
-
timestamp: action.input.timestamp,
|
|
65
|
-
exportedLineItems: action.input.exportedLineItems,
|
|
66
|
-
};
|
|
67
|
-
state.exported = exportedData;
|
|
68
|
-
}
|
|
69
|
-
catch (e) {
|
|
70
|
-
console.error(e);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
};
|
package/dist/reducers/items.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
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 { InvoiceItemsOperations } from "../../gen/items/operations.js";
|
|
7
|
-
export declare const reducer: InvoiceItemsOperations;
|
|
8
|
-
//# sourceMappingURL=items.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"items.d.ts","sourceRoot":"","sources":["../../reducers/items.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAG5E,eAAO,MAAM,OAAO,EAAE,sBA6GrB,CAAC"}
|