@accounter/server 0.0.8-alpha-20251105181339-4ce756e457f7145a4035565e526bc02285ab2675 → 0.0.8-alpha-20251105183654-b3147b83bfda6ce62d09073ce81342ceadf5160c
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/CHANGELOG.md +25 -5
- package/dist/server/src/__generated__/types.d.ts +39 -10
- package/dist/server/src/__generated__/types.js.map +1 -1
- package/dist/server/src/modules/financial-entities/__generated__/clients.types.d.ts +11 -4
- package/dist/server/src/modules/financial-entities/__generated__/types.d.ts +19 -7
- package/dist/server/src/modules/financial-entities/__generated__/types.js.map +1 -1
- package/dist/server/src/modules/financial-entities/helpers/clients.helper.d.ts +11 -0
- package/dist/server/src/modules/financial-entities/helpers/clients.helper.js +26 -0
- package/dist/server/src/modules/financial-entities/helpers/clients.helper.js.map +1 -0
- package/dist/server/src/modules/financial-entities/providers/businesses.provider.js +1 -1
- package/dist/server/src/modules/financial-entities/providers/clients.provider.js +18 -16
- package/dist/server/src/modules/financial-entities/providers/clients.provider.js.map +1 -1
- package/dist/server/src/modules/financial-entities/resolvers/clients.resolvers.js +26 -24
- package/dist/server/src/modules/financial-entities/resolvers/clients.resolvers.js.map +1 -1
- package/dist/server/src/modules/financial-entities/typeDefs/clients.graphql.js +24 -8
- package/dist/server/src/modules/financial-entities/typeDefs/clients.graphql.js.map +1 -1
- package/dist/server/src/modules/green-invoice/__generated__/types.d.ts +8 -0
- package/dist/server/src/modules/green-invoice/__generated__/types.js.map +1 -1
- package/dist/server/src/modules/green-invoice/helpers/contract-to-draft.helper.d.ts +3 -1
- package/dist/server/src/modules/green-invoice/helpers/contract-to-draft.helper.js +5 -12
- package/dist/server/src/modules/green-invoice/helpers/contract-to-draft.helper.js.map +1 -1
- package/dist/server/src/modules/green-invoice/helpers/green-invoice-clients.helper.d.ts +1 -2
- package/dist/server/src/modules/green-invoice/helpers/green-invoice-clients.helper.js +17 -31
- package/dist/server/src/modules/green-invoice/helpers/green-invoice-clients.helper.js.map +1 -1
- package/dist/server/src/modules/green-invoice/helpers/green-invoice.helper.d.ts +2 -2
- package/dist/server/src/modules/green-invoice/helpers/green-invoice.helper.js +16 -14
- package/dist/server/src/modules/green-invoice/helpers/green-invoice.helper.js.map +1 -1
- package/dist/server/src/modules/green-invoice/resolvers/green-invoice.resolvers.js +91 -29
- package/dist/server/src/modules/green-invoice/resolvers/green-invoice.resolvers.js.map +1 -1
- package/dist/server/src/modules/green-invoice/typeDefs/green-invoice.graphql.js +4 -0
- package/dist/server/src/modules/green-invoice/typeDefs/green-invoice.graphql.js.map +1 -1
- package/package.json +3 -4
- package/src/__generated__/types.ts +42 -10
- package/src/modules/financial-entities/__generated__/clients.types.ts +10 -4
- package/src/modules/financial-entities/__generated__/types.ts +19 -7
- package/src/modules/financial-entities/helpers/clients.helper.ts +28 -0
- package/src/modules/financial-entities/providers/businesses.provider.ts +1 -1
- package/src/modules/financial-entities/providers/clients.provider.ts +19 -16
- package/src/modules/financial-entities/resolvers/clients.resolvers.ts +30 -27
- package/src/modules/financial-entities/typeDefs/clients.graphql.ts +24 -8
- package/src/modules/green-invoice/__generated__/types.ts +8 -0
- package/src/modules/green-invoice/helpers/contract-to-draft.helper.ts +7 -13
- package/src/modules/green-invoice/helpers/green-invoice-clients.helper.ts +19 -40
- package/src/modules/green-invoice/helpers/green-invoice.helper.ts +17 -18
- package/src/modules/green-invoice/resolvers/green-invoice.resolvers.ts +101 -35
- package/src/modules/green-invoice/typeDefs/green-invoice.graphql.ts +4 -0
|
@@ -281,7 +281,7 @@ const replaceBusinesses = sql<IReplaceBusinessesQuery>`
|
|
|
281
281
|
UPDATE accounter_schema.clients
|
|
282
282
|
SET business_id = $targetBusinessId
|
|
283
283
|
WHERE business_id = $businessIdToReplace
|
|
284
|
-
RETURNING
|
|
284
|
+
RETURNING (integrations->>'greenInvoiceId')::uuid
|
|
285
285
|
)
|
|
286
286
|
UPDATE accounter_schema.transactions
|
|
287
287
|
SET business_id = $targetBusinessId
|
|
@@ -3,6 +3,7 @@ import { Injectable, Scope } from 'graphql-modules';
|
|
|
3
3
|
import { DBProvider } from '@modules/app-providers/db.provider.js';
|
|
4
4
|
import { sql } from '@pgtyped/runtime';
|
|
5
5
|
import { getCacheInstance } from '@shared/helpers';
|
|
6
|
+
import { validateClientIntegrations } from '../helpers/clients.helper.js';
|
|
6
7
|
import type {
|
|
7
8
|
IDeleteClientQuery,
|
|
8
9
|
IGetAllClientsQuery,
|
|
@@ -27,24 +28,14 @@ const getClientsByIds = sql<IGetClientsByIdsQuery>`
|
|
|
27
28
|
`;
|
|
28
29
|
|
|
29
30
|
const getClientsByGreenInvoiceIds = sql<IGetClientsByGreenInvoiceIdsQuery>`
|
|
30
|
-
SELECT
|
|
31
|
+
SELECT *, (integrations->>'greenInvoiceId')::uuid as green_invoice_business_id
|
|
31
32
|
FROM accounter_schema.clients
|
|
32
|
-
WHERE
|
|
33
|
+
WHERE (integrations->>'greenInvoiceId')::uuid in $$greenInvoiceBusinessIds;
|
|
33
34
|
`;
|
|
34
35
|
|
|
35
36
|
const updateClient = sql<IUpdateClientQuery>`
|
|
36
37
|
UPDATE accounter_schema.clients
|
|
37
38
|
SET
|
|
38
|
-
green_invoice_id = COALESCE(
|
|
39
|
-
$greenInvoiceId,
|
|
40
|
-
green_invoice_id,
|
|
41
|
-
NULL
|
|
42
|
-
),
|
|
43
|
-
hive_id = COALESCE(
|
|
44
|
-
$hiveId,
|
|
45
|
-
hive_id,
|
|
46
|
-
NULL
|
|
47
|
-
),
|
|
48
39
|
emails = COALESCE(
|
|
49
40
|
$emails,
|
|
50
41
|
emails,
|
|
@@ -54,6 +45,11 @@ const updateClient = sql<IUpdateClientQuery>`
|
|
|
54
45
|
$newBusinessId,
|
|
55
46
|
business_id,
|
|
56
47
|
NULL
|
|
48
|
+
),
|
|
49
|
+
integrations = COALESCE(
|
|
50
|
+
$integrations,
|
|
51
|
+
integrations,
|
|
52
|
+
NULL
|
|
57
53
|
)
|
|
58
54
|
WHERE
|
|
59
55
|
business_id = $businessId
|
|
@@ -67,8 +63,8 @@ const deleteClient = sql<IDeleteClientQuery>`
|
|
|
67
63
|
`;
|
|
68
64
|
|
|
69
65
|
const insertClient = sql<IInsertClientQuery>`
|
|
70
|
-
INSERT INTO accounter_schema.clients (business_id,
|
|
71
|
-
VALUES ($businessId, $
|
|
66
|
+
INSERT INTO accounter_schema.clients (business_id, emails, integrations)
|
|
67
|
+
VALUES ($businessId, $emails, $integrations)
|
|
72
68
|
RETURNING *;`;
|
|
73
69
|
|
|
74
70
|
@Injectable({
|
|
@@ -91,7 +87,12 @@ export class ClientsProvider {
|
|
|
91
87
|
this.cache.set('all-clients', data);
|
|
92
88
|
data.map(client => {
|
|
93
89
|
this.cache.set(`client-id-${client.business_id}`, client);
|
|
94
|
-
|
|
90
|
+
try {
|
|
91
|
+
const { greenInvoiceId } = validateClientIntegrations(client.integrations ?? {});
|
|
92
|
+
this.cache.set(`client-green-invoice-id-${greenInvoiceId}`, client);
|
|
93
|
+
} catch {
|
|
94
|
+
// swallow errors
|
|
95
|
+
}
|
|
95
96
|
});
|
|
96
97
|
return data;
|
|
97
98
|
});
|
|
@@ -123,7 +124,9 @@ export class ClientsProvider {
|
|
|
123
124
|
this.dbProvider,
|
|
124
125
|
);
|
|
125
126
|
|
|
126
|
-
return greenInvoiceIds.map(id =>
|
|
127
|
+
return greenInvoiceIds.map(id =>
|
|
128
|
+
matches.find(match => match.green_invoice_business_id === id),
|
|
129
|
+
);
|
|
127
130
|
} catch (e) {
|
|
128
131
|
console.error(e);
|
|
129
132
|
return greenInvoiceIds.map(() => undefined);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { GraphQLError } from 'graphql';
|
|
2
|
-
import { GreenInvoiceClientProvider } from '@modules/app-providers/green-invoice-client.js';
|
|
3
2
|
import { BusinessesProvider } from '@modules/financial-entities/providers/businesses.provider.js';
|
|
4
3
|
import {
|
|
5
4
|
addGreenInvoiceClient,
|
|
6
5
|
updateGreenInvoiceClient,
|
|
7
6
|
} from '@modules/green-invoice/helpers/green-invoice-clients.helper.js';
|
|
8
|
-
import { Resolvers } from '@shared/gql-types';
|
|
7
|
+
import { ClientIntegrationsInput, Resolvers } from '@shared/gql-types';
|
|
8
|
+
import { validateClientIntegrations } from '../helpers/clients.helper.js';
|
|
9
9
|
import { ClientsProvider } from '../providers/clients.provider.js';
|
|
10
10
|
import type {
|
|
11
11
|
FinancialEntitiesModule,
|
|
@@ -45,12 +45,26 @@ export const clientsResolvers: FinancialEntitiesModule.Resolvers &
|
|
|
45
45
|
},
|
|
46
46
|
Mutation: {
|
|
47
47
|
updateClient: async (_, { businessId, fields }, { injector }) => {
|
|
48
|
+
let updatedIntegrations: ClientIntegrationsInput | undefined =
|
|
49
|
+
fields.integrations ?? undefined;
|
|
50
|
+
if (updatedIntegrations) {
|
|
51
|
+
const currentClient = await injector
|
|
52
|
+
.get(ClientsProvider)
|
|
53
|
+
.getClientByIdLoader.load(businessId);
|
|
54
|
+
if (!currentClient) {
|
|
55
|
+
throw new GraphQLError(`Client with ID="${businessId}" not found`);
|
|
56
|
+
}
|
|
57
|
+
const currentIntegrations = validateClientIntegrations(currentClient.integrations);
|
|
58
|
+
updatedIntegrations = {
|
|
59
|
+
...currentIntegrations,
|
|
60
|
+
...updatedIntegrations,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
48
63
|
const adjustedFields: IUpdateClientParams = {
|
|
49
64
|
businessId,
|
|
50
65
|
emails: fields.emails ? [...fields.emails] : undefined,
|
|
51
|
-
greenInvoiceId: fields.greenInvoiceId,
|
|
52
|
-
hiveId: fields.hiveId,
|
|
53
66
|
newBusinessId: fields.newBusinessId,
|
|
67
|
+
integrations: updatedIntegrations,
|
|
54
68
|
};
|
|
55
69
|
try {
|
|
56
70
|
const [updatedClient] = await injector
|
|
@@ -81,8 +95,7 @@ export const clientsResolvers: FinancialEntitiesModule.Resolvers &
|
|
|
81
95
|
const newClient: IInsertClientParams = {
|
|
82
96
|
businessId: fields.businessId,
|
|
83
97
|
emails: fields.emails ? [...fields.emails] : [],
|
|
84
|
-
|
|
85
|
-
hiveId: fields.hiveId,
|
|
98
|
+
integrations: fields.integrations,
|
|
86
99
|
};
|
|
87
100
|
const [insertClient] = await injector.get(ClientsProvider).insertClient(newClient);
|
|
88
101
|
|
|
@@ -116,28 +129,18 @@ export const clientsResolvers: FinancialEntitiesModule.Resolvers &
|
|
|
116
129
|
|
|
117
130
|
return businessMatch;
|
|
118
131
|
},
|
|
119
|
-
greenInvoiceId: business => business.green_invoice_id,
|
|
120
|
-
hiveId: business => business.hive_id,
|
|
121
132
|
emails: business => business.emails ?? [],
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
const emails = client.emails ? (client.emails.filter(Boolean) as string[]) : [];
|
|
135
|
-
return {
|
|
136
|
-
...client,
|
|
137
|
-
emails,
|
|
138
|
-
id: business.green_invoice_id,
|
|
139
|
-
};
|
|
140
|
-
},
|
|
133
|
+
integrations: business => business,
|
|
134
|
+
},
|
|
135
|
+
ClientIntegrations: {
|
|
136
|
+
id: business => `${business.business_id}-integrations`,
|
|
137
|
+
hiveId: business => validateClientIntegrations(business.integrations).hiveId ?? null,
|
|
138
|
+
linearId: business => validateClientIntegrations(business.integrations).linearId ?? null,
|
|
139
|
+
slackChannelKey: business =>
|
|
140
|
+
validateClientIntegrations(business.integrations).slackChannelKey ?? null,
|
|
141
|
+
notionId: business => validateClientIntegrations(business.integrations).notionId ?? null,
|
|
142
|
+
workflowyUrl: business =>
|
|
143
|
+
validateClientIntegrations(business.integrations).workflowyUrl ?? null,
|
|
141
144
|
},
|
|
142
145
|
LtdFinancialEntity: {
|
|
143
146
|
clientInfo: async (business, _, { injector }) => {
|
|
@@ -16,29 +16,45 @@ export default gql`
|
|
|
16
16
|
type Client {
|
|
17
17
|
id: UUID!
|
|
18
18
|
originalBusiness: LtdFinancialEntity!
|
|
19
|
-
greenInvoiceId: UUID
|
|
20
|
-
hiveId: String
|
|
21
19
|
emails: [String!]!
|
|
22
20
|
generatedDocumentType: DocumentType!
|
|
23
|
-
|
|
21
|
+
integrations: ClientIntegrations!
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
" integrations associated with a client "
|
|
25
|
+
type ClientIntegrations {
|
|
26
|
+
id: ID!
|
|
27
|
+
hiveId: String
|
|
28
|
+
linearId: String
|
|
29
|
+
slackChannelKey: String
|
|
30
|
+
notionId: String
|
|
31
|
+
workflowyUrl: String
|
|
24
32
|
}
|
|
25
33
|
|
|
26
34
|
" fields for inserting a new client "
|
|
27
35
|
input ClientInsertInput {
|
|
28
36
|
businessId: UUID!
|
|
29
|
-
greenInvoiceId: UUID
|
|
30
|
-
hiveId: String
|
|
31
37
|
emails: [String!]
|
|
32
38
|
generatedDocumentType: DocumentType!
|
|
39
|
+
integrations: ClientIntegrationsInput
|
|
33
40
|
}
|
|
34
41
|
|
|
35
42
|
" fields for updating an existing client "
|
|
36
43
|
input ClientUpdateInput {
|
|
37
|
-
|
|
38
|
-
hiveId: String
|
|
44
|
+
newBusinessId: UUID
|
|
39
45
|
emails: [String!]
|
|
40
46
|
generatedDocumentType: DocumentType
|
|
41
|
-
|
|
47
|
+
integrations: ClientIntegrationsInput
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
" integrations input for client insert/update "
|
|
51
|
+
input ClientIntegrationsInput {
|
|
52
|
+
greenInvoiceId: UUID
|
|
53
|
+
hiveId: String
|
|
54
|
+
linearId: String
|
|
55
|
+
slackChannelKey: String
|
|
56
|
+
notionId: String
|
|
57
|
+
workflowyUrl: String
|
|
42
58
|
}
|
|
43
59
|
|
|
44
60
|
" result type for updateClient "
|
|
@@ -11,6 +11,7 @@ export namespace GreenInvoiceModule {
|
|
|
11
11
|
GreenInvoiceIncome: 'currency' | 'currencyRate' | 'description' | 'itemId' | 'price' | 'quantity' | 'vatRate' | 'vatType';
|
|
12
12
|
GreenInvoicePayment: 'currency' | 'currencyRate' | 'date' | 'price' | 'type' | 'subType' | 'bankName' | 'bankBranch' | 'bankAccount' | 'chequeNum' | 'accountId' | 'transactionId' | 'appType' | 'cardType' | 'cardNum' | 'dealType' | 'numPayments' | 'firstPayment';
|
|
13
13
|
IssuedDocumentInfo: 'originalDocument';
|
|
14
|
+
ClientIntegrations: 'greenInvoiceInfo';
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
interface DefinedEnumValues {
|
|
@@ -46,6 +47,7 @@ export namespace GreenInvoiceModule {
|
|
|
46
47
|
export type FileScalar = Types.FileScalar;
|
|
47
48
|
export type Charge = Types.Charge;
|
|
48
49
|
export type IssuedDocumentInfo = Types.IssuedDocumentInfo;
|
|
50
|
+
export type ClientIntegrations = Types.ClientIntegrations;
|
|
49
51
|
export type DocumentType = Types.DocumentType;
|
|
50
52
|
export type GreenInvoiceDocumentLang = DefinedEnumValues['GreenInvoiceDocumentLang'];
|
|
51
53
|
export type Currency = Types.Currency;
|
|
@@ -75,6 +77,7 @@ export namespace GreenInvoiceModule {
|
|
|
75
77
|
export type GreenInvoiceIncomeResolvers = Pick<Types.GreenInvoiceIncomeResolvers, DefinedFields['GreenInvoiceIncome']>;
|
|
76
78
|
export type GreenInvoicePaymentResolvers = Pick<Types.GreenInvoicePaymentResolvers, DefinedFields['GreenInvoicePayment']>;
|
|
77
79
|
export type IssuedDocumentInfoResolvers = Pick<Types.IssuedDocumentInfoResolvers, DefinedFields['IssuedDocumentInfo']>;
|
|
80
|
+
export type ClientIntegrationsResolvers = Pick<Types.ClientIntegrationsResolvers, DefinedFields['ClientIntegrations']>;
|
|
78
81
|
|
|
79
82
|
export interface Resolvers {
|
|
80
83
|
Query?: QueryResolvers;
|
|
@@ -86,6 +89,7 @@ export namespace GreenInvoiceModule {
|
|
|
86
89
|
GreenInvoiceIncome?: GreenInvoiceIncomeResolvers;
|
|
87
90
|
GreenInvoicePayment?: GreenInvoicePaymentResolvers;
|
|
88
91
|
IssuedDocumentInfo?: IssuedDocumentInfoResolvers;
|
|
92
|
+
ClientIntegrations?: ClientIntegrationsResolvers;
|
|
89
93
|
};
|
|
90
94
|
|
|
91
95
|
export interface MiddlewareMap {
|
|
@@ -112,6 +116,10 @@ export namespace GreenInvoiceModule {
|
|
|
112
116
|
'*'?: gm.Middleware[];
|
|
113
117
|
originalDocument?: gm.Middleware[];
|
|
114
118
|
};
|
|
119
|
+
ClientIntegrations?: {
|
|
120
|
+
'*'?: gm.Middleware[];
|
|
121
|
+
greenInvoiceInfo?: gm.Middleware[];
|
|
122
|
+
};
|
|
115
123
|
GenerateMonthlyClientDocumentsResult?: {
|
|
116
124
|
'*'?: gm.Middleware[];
|
|
117
125
|
success?: gm.Middleware[];
|
|
@@ -3,13 +3,13 @@ import { GraphQLError } from 'graphql';
|
|
|
3
3
|
import { Injector } from 'graphql-modules';
|
|
4
4
|
import type { IGetContractsByIdsResult } from '@modules/contracts/types.js';
|
|
5
5
|
import { normalizeDocumentType } from '@modules/documents/resolvers/common.js';
|
|
6
|
+
import { validateClientIntegrations } from '@modules/financial-entities/helpers/clients.helper.js';
|
|
6
7
|
import { BusinessesProvider } from '@modules/financial-entities/providers/businesses.provider.js';
|
|
7
8
|
import { ClientsProvider } from '@modules/financial-entities/providers/clients.provider.js';
|
|
8
9
|
import { Currency } from '@shared/enums';
|
|
9
10
|
import { NewDocumentInfo } from '@shared/gql-types';
|
|
10
11
|
import { dateToTimelessDateString } from '@shared/helpers';
|
|
11
12
|
import { TimelessDateString } from '@shared/types';
|
|
12
|
-
import { getClientFromGreenInvoiceClient } from './green-invoice-clients.helper.js';
|
|
13
13
|
|
|
14
14
|
export const convertContractToDraft = async (
|
|
15
15
|
contract: IGetContractsByIdsResult,
|
|
@@ -20,12 +20,7 @@ export const convertContractToDraft = async (
|
|
|
20
20
|
.get(BusinessesProvider)
|
|
21
21
|
.getBusinessByIdLoader.load(contract.client_id);
|
|
22
22
|
const clientPromise = injector.get(ClientsProvider).getClientByIdLoader.load(contract.client_id);
|
|
23
|
-
const
|
|
24
|
-
const [business, client, greenInvoiceClient] = await Promise.all([
|
|
25
|
-
businessPromise,
|
|
26
|
-
clientPromise,
|
|
27
|
-
greenInvoiceClientPromise,
|
|
28
|
-
]);
|
|
23
|
+
const [business, client] = await Promise.all([businessPromise, clientPromise]);
|
|
29
24
|
|
|
30
25
|
if (!business) {
|
|
31
26
|
throw new GraphQLError(`Business ID="${contract.client_id}" not found`);
|
|
@@ -35,7 +30,9 @@ export const convertContractToDraft = async (
|
|
|
35
30
|
throw new GraphQLError(`Client not found for business ID="${contract.client_id}"`);
|
|
36
31
|
}
|
|
37
32
|
|
|
38
|
-
|
|
33
|
+
const greenInvoiceId = validateClientIntegrations(client.integrations)?.greenInvoiceId;
|
|
34
|
+
|
|
35
|
+
if (!greenInvoiceId) {
|
|
39
36
|
throw new GraphQLError(`Green invoice match not found for business ID="${contract.client_id}"`);
|
|
40
37
|
}
|
|
41
38
|
|
|
@@ -45,7 +42,7 @@ export const convertContractToDraft = async (
|
|
|
45
42
|
const year = today.getFullYear() + (today.getMonth() === 0 ? -1 : 0);
|
|
46
43
|
const month = format(subMonths(today, 1), 'MMMM');
|
|
47
44
|
|
|
48
|
-
const documentInput: NewDocumentInfo = {
|
|
45
|
+
const documentInput: Omit<NewDocumentInfo, 'client'> & { client: string | undefined } = {
|
|
49
46
|
remarks: `${contract.purchase_orders[0] ? `PO: ${contract.purchase_orders[0]}${contract.remarks ? ', ' : ''}` : ''}${contract.remarks ?? ''}`,
|
|
50
47
|
description: `GraphQL Hive Enterprise License - ${month} ${year}`,
|
|
51
48
|
type: normalizeDocumentType(contract.document_type),
|
|
@@ -56,10 +53,7 @@ export const convertContractToDraft = async (
|
|
|
56
53
|
vatType: 'EXEMPT',
|
|
57
54
|
rounding: false,
|
|
58
55
|
signed: true,
|
|
59
|
-
client:
|
|
60
|
-
...greenInvoiceClient,
|
|
61
|
-
emails: [...((client.emails?.filter(Boolean) as string[]) ?? [])],
|
|
62
|
-
},
|
|
56
|
+
client: greenInvoiceId,
|
|
63
57
|
income: [
|
|
64
58
|
{
|
|
65
59
|
description: `GraphQL Hive Enterprise License - ${month} ${year}`,
|
|
@@ -5,51 +5,16 @@ import {
|
|
|
5
5
|
} from '@accounter/green-invoice-graphql';
|
|
6
6
|
import { GreenInvoiceClientProvider } from '@modules/app-providers/green-invoice-client.js';
|
|
7
7
|
import { CountryCode } from '@modules/countries/types.js';
|
|
8
|
+
import { validateClientIntegrations } from '@modules/financial-entities/helpers/clients.helper.js';
|
|
8
9
|
import { BusinessesProvider } from '@modules/financial-entities/providers/businesses.provider.js';
|
|
9
10
|
import { ClientsProvider } from '@modules/financial-entities/providers/clients.provider.js';
|
|
10
11
|
import {
|
|
11
12
|
IGetBusinessesByIdsResult,
|
|
12
13
|
IGetClientsByIdsResult,
|
|
13
14
|
} from '@modules/financial-entities/types.js';
|
|
14
|
-
import { ClientUpdateInput,
|
|
15
|
+
import { ClientUpdateInput, UpdateBusinessInput } from '@shared/gql-types';
|
|
15
16
|
import { countryCodeToGreenInvoiceCountry } from './green-invoice.helper.js';
|
|
16
17
|
|
|
17
|
-
export async function getClientFromGreenInvoiceClient(
|
|
18
|
-
injector: Injector,
|
|
19
|
-
businessId: string,
|
|
20
|
-
useGreenInvoiceId = false,
|
|
21
|
-
): Promise<GreenInvoiceClient | undefined> {
|
|
22
|
-
const client = await injector.get(ClientsProvider).getClientByIdLoader.load(businessId);
|
|
23
|
-
if (!client?.green_invoice_id) {
|
|
24
|
-
return useGreenInvoiceId ? undefined : { id: businessId };
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const greenInvoiceClient = await injector
|
|
28
|
-
.get(GreenInvoiceClientProvider)
|
|
29
|
-
.clientLoader.load(client.green_invoice_id);
|
|
30
|
-
|
|
31
|
-
if (!greenInvoiceClient) {
|
|
32
|
-
return useGreenInvoiceId ? undefined : { id: businessId };
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
id: useGreenInvoiceId && greenInvoiceClient.id ? greenInvoiceClient.id : businessId,
|
|
37
|
-
country: greenInvoiceClient.country,
|
|
38
|
-
emails: [
|
|
39
|
-
...((greenInvoiceClient.emails?.filter(Boolean) as string[]) ?? []),
|
|
40
|
-
'ap@the-guild.dev',
|
|
41
|
-
],
|
|
42
|
-
name: greenInvoiceClient.name,
|
|
43
|
-
phone: greenInvoiceClient.phone,
|
|
44
|
-
taxId: greenInvoiceClient.taxId,
|
|
45
|
-
address: greenInvoiceClient.address,
|
|
46
|
-
city: greenInvoiceClient.city,
|
|
47
|
-
zip: greenInvoiceClient.zip,
|
|
48
|
-
fax: greenInvoiceClient.fax,
|
|
49
|
-
mobile: greenInvoiceClient.mobile,
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
18
|
function convertLocalClientToGreenInvoiceCreateClientInput(
|
|
54
19
|
localClient: IGetClientsByIdsResult,
|
|
55
20
|
localBusiness: IGetBusinessesByIdsResult,
|
|
@@ -134,10 +99,15 @@ export async function addGreenInvoiceClient(clientId: string, injector: Injector
|
|
|
134
99
|
throw new Error('Failed to create Green Invoice client');
|
|
135
100
|
}
|
|
136
101
|
|
|
102
|
+
const integrations = validateClientIntegrations(localClient.integrations);
|
|
103
|
+
|
|
137
104
|
// add green invoice id to local client
|
|
138
105
|
await injector.get(ClientsProvider).updateClient({
|
|
139
106
|
businessId: clientId,
|
|
140
|
-
|
|
107
|
+
integrations: {
|
|
108
|
+
...integrations,
|
|
109
|
+
greenInvoiceId: greenInvoiceClient.id,
|
|
110
|
+
},
|
|
141
111
|
});
|
|
142
112
|
} catch (error) {
|
|
143
113
|
const message = 'Error adding Green Invoice client';
|
|
@@ -216,7 +186,16 @@ export async function updateGreenInvoiceClient(
|
|
|
216
186
|
localBusinessPromise,
|
|
217
187
|
localClientPromise,
|
|
218
188
|
]);
|
|
219
|
-
|
|
189
|
+
|
|
190
|
+
let greenInvoiceId: string | undefined = undefined;
|
|
191
|
+
try {
|
|
192
|
+
greenInvoiceId =
|
|
193
|
+
validateClientIntegrations(localClient?.integrations ?? {}).greenInvoiceId ?? undefined;
|
|
194
|
+
} catch {
|
|
195
|
+
// swallow errors
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (!localBusiness?.name || !greenInvoiceId) {
|
|
220
199
|
// We cannot update a client in Green Invoice without its ID.
|
|
221
200
|
console.warn(
|
|
222
201
|
`Cannot update Green Invoice client: missing local business name or client ID for business${clientId}`,
|
|
@@ -233,7 +212,7 @@ export async function updateGreenInvoiceClient(
|
|
|
233
212
|
}
|
|
234
213
|
|
|
235
214
|
const greenInvoiceClient = await injector.get(GreenInvoiceClientProvider).updateClient({
|
|
236
|
-
id:
|
|
215
|
+
id: greenInvoiceId,
|
|
237
216
|
input: fieldsToUpdate,
|
|
238
217
|
});
|
|
239
218
|
|
|
@@ -25,14 +25,15 @@ import { CountryCode } from '@modules/countries/types.js';
|
|
|
25
25
|
import { DocumentsProvider } from '@modules/documents/providers/documents.provider.js';
|
|
26
26
|
import { IssuedDocumentsProvider } from '@modules/documents/providers/issued-documents.provider.js';
|
|
27
27
|
import type { document_status, IInsertDocumentsParams } from '@modules/documents/types';
|
|
28
|
+
import { validateClientIntegrations } from '@modules/financial-entities/helpers/clients.helper.js';
|
|
28
29
|
import { ClientsProvider } from '@modules/financial-entities/providers/clients.provider.js';
|
|
29
30
|
import {
|
|
30
31
|
Currency,
|
|
31
32
|
DocumentType,
|
|
32
33
|
GreenInvoiceCountry,
|
|
33
34
|
GreenInvoicePaymentType,
|
|
34
|
-
NewDocumentInfo,
|
|
35
35
|
NewDocumentInput,
|
|
36
|
+
ResolversTypes,
|
|
36
37
|
type GreenInvoiceDiscountType,
|
|
37
38
|
type GreenInvoiceDocumentLang,
|
|
38
39
|
type GreenInvoiceLinkType,
|
|
@@ -1247,18 +1248,24 @@ export async function convertDocumentInputIntoGreenInvoiceInput(
|
|
|
1247
1248
|
if (!clientInfo) {
|
|
1248
1249
|
throw new GraphQLError(`Client with ID ${initialInput.client.id} not found`);
|
|
1249
1250
|
}
|
|
1250
|
-
|
|
1251
|
+
let greenInvoiceId: string | null = null;
|
|
1252
|
+
try {
|
|
1253
|
+
greenInvoiceId =
|
|
1254
|
+
validateClientIntegrations(clientInfo.integrations ?? {}).greenInvoiceId ?? null;
|
|
1255
|
+
} catch (error) {
|
|
1256
|
+
console.error('Failed to validate client integrations', error);
|
|
1257
|
+
throw new GraphQLError(`Client with ID ${initialInput.client.id} has invalid integrations`);
|
|
1258
|
+
}
|
|
1259
|
+
if (!greenInvoiceId) {
|
|
1251
1260
|
throw new GraphQLError(`Client with ID ${initialInput.client.id} not found in Green Invoice`);
|
|
1252
1261
|
}
|
|
1253
1262
|
const greenInvoiceClient = await injector
|
|
1254
1263
|
.get(GreenInvoiceClientProvider)
|
|
1255
|
-
.clientLoader.load(
|
|
1264
|
+
.clientLoader.load(greenInvoiceId);
|
|
1256
1265
|
if (!greenInvoiceClient) {
|
|
1257
|
-
throw new GraphQLError(
|
|
1258
|
-
`Green Invoice client with ID ${clientInfo.green_invoice_id} not found`,
|
|
1259
|
-
);
|
|
1266
|
+
throw new GraphQLError(`Green Invoice client with ID ${greenInvoiceId} not found`);
|
|
1260
1267
|
}
|
|
1261
|
-
const emails: (string | null)[] = ['ap@the-guild.dev'];
|
|
1268
|
+
const emails: (string | null)[] = ['ap@the-guild.dev']; // TODO: remove hardcoded email
|
|
1262
1269
|
const inputEmails = initialInput.client?.emails?.filter(Boolean) ?? [];
|
|
1263
1270
|
if (inputEmails.length) {
|
|
1264
1271
|
emails.push(...inputEmails);
|
|
@@ -1266,7 +1273,7 @@ export async function convertDocumentInputIntoGreenInvoiceInput(
|
|
|
1266
1273
|
emails.push(...(greenInvoiceClient.emails ?? []));
|
|
1267
1274
|
}
|
|
1268
1275
|
client = {
|
|
1269
|
-
id:
|
|
1276
|
+
id: greenInvoiceClient.id,
|
|
1270
1277
|
country: greenInvoiceClient.country,
|
|
1271
1278
|
name: greenInvoiceClient.name,
|
|
1272
1279
|
phone: greenInvoiceClient.phone,
|
|
@@ -1323,18 +1330,10 @@ export async function convertDocumentInputIntoGreenInvoiceInput(
|
|
|
1323
1330
|
|
|
1324
1331
|
export function convertGreenInvoiceDocumentToLocalDocumentInfo(
|
|
1325
1332
|
greenInvoiceDocument: _DOLLAR_defs_Document,
|
|
1326
|
-
): NewDocumentInfo {
|
|
1333
|
+
): ResolversTypes['NewDocumentInfo'] {
|
|
1327
1334
|
return {
|
|
1328
1335
|
...greenInvoiceDocument,
|
|
1329
|
-
client: greenInvoiceDocument.client?.id
|
|
1330
|
-
? {
|
|
1331
|
-
...greenInvoiceDocument.client,
|
|
1332
|
-
id: greenInvoiceDocument.client.id,
|
|
1333
|
-
emails: greenInvoiceDocument.client.emails
|
|
1334
|
-
? (greenInvoiceDocument.client.emails.filter(Boolean) as string[])
|
|
1335
|
-
: [],
|
|
1336
|
-
}
|
|
1337
|
-
: undefined,
|
|
1336
|
+
client: greenInvoiceDocument.client?.id,
|
|
1338
1337
|
currency: greenInvoiceDocument.currency as Currency,
|
|
1339
1338
|
income: greenInvoiceDocument.income?.filter(Boolean).map(income => ({
|
|
1340
1339
|
...income!,
|