@accounter/server 0.0.8-alpha-20251105183654-b3147b83bfda6ce62d09073ce81342ceadf5160c → 0.0.8-alpha-20251106080932-aeb05a6f60a5ad38f48a4149e31ae1c5482d7177

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 (46) hide show
  1. package/CHANGELOG.md +5 -25
  2. package/dist/server/src/__generated__/types.d.ts +10 -39
  3. package/dist/server/src/__generated__/types.js.map +1 -1
  4. package/dist/server/src/modules/financial-entities/__generated__/clients.types.d.ts +4 -11
  5. package/dist/server/src/modules/financial-entities/__generated__/types.d.ts +7 -19
  6. package/dist/server/src/modules/financial-entities/__generated__/types.js.map +1 -1
  7. package/dist/server/src/modules/financial-entities/providers/businesses.provider.js +1 -1
  8. package/dist/server/src/modules/financial-entities/providers/clients.provider.js +16 -18
  9. package/dist/server/src/modules/financial-entities/providers/clients.provider.js.map +1 -1
  10. package/dist/server/src/modules/financial-entities/resolvers/clients.resolvers.js +24 -26
  11. package/dist/server/src/modules/financial-entities/resolvers/clients.resolvers.js.map +1 -1
  12. package/dist/server/src/modules/financial-entities/typeDefs/clients.graphql.js +8 -24
  13. package/dist/server/src/modules/financial-entities/typeDefs/clients.graphql.js.map +1 -1
  14. package/dist/server/src/modules/green-invoice/__generated__/types.d.ts +0 -8
  15. package/dist/server/src/modules/green-invoice/__generated__/types.js.map +1 -1
  16. package/dist/server/src/modules/green-invoice/helpers/contract-to-draft.helper.d.ts +1 -3
  17. package/dist/server/src/modules/green-invoice/helpers/contract-to-draft.helper.js +12 -5
  18. package/dist/server/src/modules/green-invoice/helpers/contract-to-draft.helper.js.map +1 -1
  19. package/dist/server/src/modules/green-invoice/helpers/green-invoice-clients.helper.d.ts +2 -1
  20. package/dist/server/src/modules/green-invoice/helpers/green-invoice-clients.helper.js +31 -17
  21. package/dist/server/src/modules/green-invoice/helpers/green-invoice-clients.helper.js.map +1 -1
  22. package/dist/server/src/modules/green-invoice/helpers/green-invoice.helper.d.ts +2 -2
  23. package/dist/server/src/modules/green-invoice/helpers/green-invoice.helper.js +18 -21
  24. package/dist/server/src/modules/green-invoice/helpers/green-invoice.helper.js.map +1 -1
  25. package/dist/server/src/modules/green-invoice/resolvers/green-invoice.resolvers.js +28 -89
  26. package/dist/server/src/modules/green-invoice/resolvers/green-invoice.resolvers.js.map +1 -1
  27. package/dist/server/src/modules/green-invoice/typeDefs/green-invoice.graphql.js +0 -4
  28. package/dist/server/src/modules/green-invoice/typeDefs/green-invoice.graphql.js.map +1 -1
  29. package/package.json +1 -1
  30. package/src/__generated__/types.ts +10 -42
  31. package/src/modules/financial-entities/__generated__/clients.types.ts +4 -10
  32. package/src/modules/financial-entities/__generated__/types.ts +7 -19
  33. package/src/modules/financial-entities/providers/businesses.provider.ts +1 -1
  34. package/src/modules/financial-entities/providers/clients.provider.ts +16 -19
  35. package/src/modules/financial-entities/resolvers/clients.resolvers.ts +27 -30
  36. package/src/modules/financial-entities/typeDefs/clients.graphql.ts +8 -24
  37. package/src/modules/green-invoice/__generated__/types.ts +0 -8
  38. package/src/modules/green-invoice/helpers/contract-to-draft.helper.ts +13 -7
  39. package/src/modules/green-invoice/helpers/green-invoice-clients.helper.ts +40 -19
  40. package/src/modules/green-invoice/helpers/green-invoice.helper.ts +23 -22
  41. package/src/modules/green-invoice/resolvers/green-invoice.resolvers.ts +34 -99
  42. package/src/modules/green-invoice/typeDefs/green-invoice.graphql.ts +0 -4
  43. package/dist/server/src/modules/financial-entities/helpers/clients.helper.d.ts +0 -11
  44. package/dist/server/src/modules/financial-entities/helpers/clients.helper.js +0 -26
  45. package/dist/server/src/modules/financial-entities/helpers/clients.helper.js.map +0 -1
  46. package/src/modules/financial-entities/helpers/clients.helper.ts +0 -28
@@ -3,7 +3,6 @@ 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';
7
6
  import type {
8
7
  IDeleteClientQuery,
9
8
  IGetAllClientsQuery,
@@ -28,14 +27,24 @@ const getClientsByIds = sql<IGetClientsByIdsQuery>`
28
27
  `;
29
28
 
30
29
  const getClientsByGreenInvoiceIds = sql<IGetClientsByGreenInvoiceIdsQuery>`
31
- SELECT *, (integrations->>'greenInvoiceId')::uuid as green_invoice_business_id
30
+ SELECT *
32
31
  FROM accounter_schema.clients
33
- WHERE (integrations->>'greenInvoiceId')::uuid in $$greenInvoiceBusinessIds;
32
+ WHERE green_invoice_id IN $$greenInvoiceBusinessIds;
34
33
  `;
35
34
 
36
35
  const updateClient = sql<IUpdateClientQuery>`
37
36
  UPDATE accounter_schema.clients
38
37
  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
+ ),
39
48
  emails = COALESCE(
40
49
  $emails,
41
50
  emails,
@@ -45,11 +54,6 @@ const updateClient = sql<IUpdateClientQuery>`
45
54
  $newBusinessId,
46
55
  business_id,
47
56
  NULL
48
- ),
49
- integrations = COALESCE(
50
- $integrations,
51
- integrations,
52
- NULL
53
57
  )
54
58
  WHERE
55
59
  business_id = $businessId
@@ -63,8 +67,8 @@ const deleteClient = sql<IDeleteClientQuery>`
63
67
  `;
64
68
 
65
69
  const insertClient = sql<IInsertClientQuery>`
66
- INSERT INTO accounter_schema.clients (business_id, emails, integrations)
67
- VALUES ($businessId, $emails, $integrations)
70
+ INSERT INTO accounter_schema.clients (business_id, green_invoice_id, hive_id, emails)
71
+ VALUES ($businessId, $greenInvoiceId, $hiveId, $emails)
68
72
  RETURNING *;`;
69
73
 
70
74
  @Injectable({
@@ -87,12 +91,7 @@ export class ClientsProvider {
87
91
  this.cache.set('all-clients', data);
88
92
  data.map(client => {
89
93
  this.cache.set(`client-id-${client.business_id}`, client);
90
- try {
91
- const { greenInvoiceId } = validateClientIntegrations(client.integrations ?? {});
92
- this.cache.set(`client-green-invoice-id-${greenInvoiceId}`, client);
93
- } catch {
94
- // swallow errors
95
- }
94
+ this.cache.set(`client-green-invoice-id-${client.green_invoice_id}`, client);
96
95
  });
97
96
  return data;
98
97
  });
@@ -124,9 +123,7 @@ export class ClientsProvider {
124
123
  this.dbProvider,
125
124
  );
126
125
 
127
- return greenInvoiceIds.map(id =>
128
- matches.find(match => match.green_invoice_business_id === id),
129
- );
126
+ return greenInvoiceIds.map(id => matches.find(match => match.green_invoice_id === id));
130
127
  } catch (e) {
131
128
  console.error(e);
132
129
  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';
2
3
  import { BusinessesProvider } from '@modules/financial-entities/providers/businesses.provider.js';
3
4
  import {
4
5
  addGreenInvoiceClient,
5
6
  updateGreenInvoiceClient,
6
7
  } from '@modules/green-invoice/helpers/green-invoice-clients.helper.js';
7
- import { ClientIntegrationsInput, Resolvers } from '@shared/gql-types';
8
- import { validateClientIntegrations } from '../helpers/clients.helper.js';
8
+ import { Resolvers } from '@shared/gql-types';
9
9
  import { ClientsProvider } from '../providers/clients.provider.js';
10
10
  import type {
11
11
  FinancialEntitiesModule,
@@ -45,26 +45,12 @@ 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
- }
63
48
  const adjustedFields: IUpdateClientParams = {
64
49
  businessId,
65
50
  emails: fields.emails ? [...fields.emails] : undefined,
51
+ greenInvoiceId: fields.greenInvoiceId,
52
+ hiveId: fields.hiveId,
66
53
  newBusinessId: fields.newBusinessId,
67
- integrations: updatedIntegrations,
68
54
  };
69
55
  try {
70
56
  const [updatedClient] = await injector
@@ -95,7 +81,8 @@ export const clientsResolvers: FinancialEntitiesModule.Resolvers &
95
81
  const newClient: IInsertClientParams = {
96
82
  businessId: fields.businessId,
97
83
  emails: fields.emails ? [...fields.emails] : [],
98
- integrations: fields.integrations,
84
+ greenInvoiceId: fields.greenInvoiceId,
85
+ hiveId: fields.hiveId,
99
86
  };
100
87
  const [insertClient] = await injector.get(ClientsProvider).insertClient(newClient);
101
88
 
@@ -129,18 +116,28 @@ export const clientsResolvers: FinancialEntitiesModule.Resolvers &
129
116
 
130
117
  return businessMatch;
131
118
  },
119
+ greenInvoiceId: business => business.green_invoice_id,
120
+ hiveId: business => business.hive_id,
132
121
  emails: business => business.emails ?? [],
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,
122
+ greenInvoiceInfo: async (business, _, { injector }) => {
123
+ if (!business.green_invoice_id) {
124
+ return null;
125
+ }
126
+ const client = await injector
127
+ .get(GreenInvoiceClientProvider)
128
+ .clientLoader.load(business.green_invoice_id);
129
+ if (!client) {
130
+ throw new GraphQLError(
131
+ `Green Invoice client with ID "${business.green_invoice_id}" not found`,
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
+ },
144
141
  },
145
142
  LtdFinancialEntity: {
146
143
  clientInfo: async (business, _, { injector }) => {
@@ -16,45 +16,29 @@ export default gql`
16
16
  type Client {
17
17
  id: UUID!
18
18
  originalBusiness: LtdFinancialEntity!
19
+ greenInvoiceId: UUID
20
+ hiveId: String
19
21
  emails: [String!]!
20
22
  generatedDocumentType: DocumentType!
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
23
+ greenInvoiceInfo: GreenInvoiceClient
32
24
  }
33
25
 
34
26
  " fields for inserting a new client "
35
27
  input ClientInsertInput {
36
28
  businessId: UUID!
29
+ greenInvoiceId: UUID
30
+ hiveId: String
37
31
  emails: [String!]
38
32
  generatedDocumentType: DocumentType!
39
- integrations: ClientIntegrationsInput
40
33
  }
41
34
 
42
35
  " fields for updating an existing client "
43
36
  input ClientUpdateInput {
44
- newBusinessId: UUID
45
- emails: [String!]
46
- generatedDocumentType: DocumentType
47
- integrations: ClientIntegrationsInput
48
- }
49
-
50
- " integrations input for client insert/update "
51
- input ClientIntegrationsInput {
52
37
  greenInvoiceId: UUID
53
38
  hiveId: String
54
- linearId: String
55
- slackChannelKey: String
56
- notionId: String
57
- workflowyUrl: String
39
+ emails: [String!]
40
+ generatedDocumentType: DocumentType
41
+ newBusinessId: UUID
58
42
  }
59
43
 
60
44
  " result type for updateClient "
@@ -11,7 +11,6 @@ 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';
15
14
  };
16
15
 
17
16
  interface DefinedEnumValues {
@@ -47,7 +46,6 @@ export namespace GreenInvoiceModule {
47
46
  export type FileScalar = Types.FileScalar;
48
47
  export type Charge = Types.Charge;
49
48
  export type IssuedDocumentInfo = Types.IssuedDocumentInfo;
50
- export type ClientIntegrations = Types.ClientIntegrations;
51
49
  export type DocumentType = Types.DocumentType;
52
50
  export type GreenInvoiceDocumentLang = DefinedEnumValues['GreenInvoiceDocumentLang'];
53
51
  export type Currency = Types.Currency;
@@ -77,7 +75,6 @@ export namespace GreenInvoiceModule {
77
75
  export type GreenInvoiceIncomeResolvers = Pick<Types.GreenInvoiceIncomeResolvers, DefinedFields['GreenInvoiceIncome']>;
78
76
  export type GreenInvoicePaymentResolvers = Pick<Types.GreenInvoicePaymentResolvers, DefinedFields['GreenInvoicePayment']>;
79
77
  export type IssuedDocumentInfoResolvers = Pick<Types.IssuedDocumentInfoResolvers, DefinedFields['IssuedDocumentInfo']>;
80
- export type ClientIntegrationsResolvers = Pick<Types.ClientIntegrationsResolvers, DefinedFields['ClientIntegrations']>;
81
78
 
82
79
  export interface Resolvers {
83
80
  Query?: QueryResolvers;
@@ -89,7 +86,6 @@ export namespace GreenInvoiceModule {
89
86
  GreenInvoiceIncome?: GreenInvoiceIncomeResolvers;
90
87
  GreenInvoicePayment?: GreenInvoicePaymentResolvers;
91
88
  IssuedDocumentInfo?: IssuedDocumentInfoResolvers;
92
- ClientIntegrations?: ClientIntegrationsResolvers;
93
89
  };
94
90
 
95
91
  export interface MiddlewareMap {
@@ -116,10 +112,6 @@ export namespace GreenInvoiceModule {
116
112
  '*'?: gm.Middleware[];
117
113
  originalDocument?: gm.Middleware[];
118
114
  };
119
- ClientIntegrations?: {
120
- '*'?: gm.Middleware[];
121
- greenInvoiceInfo?: gm.Middleware[];
122
- };
123
115
  GenerateMonthlyClientDocumentsResult?: {
124
116
  '*'?: gm.Middleware[];
125
117
  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';
7
6
  import { BusinessesProvider } from '@modules/financial-entities/providers/businesses.provider.js';
8
7
  import { ClientsProvider } from '@modules/financial-entities/providers/clients.provider.js';
9
8
  import { Currency } from '@shared/enums';
10
9
  import { NewDocumentInfo } from '@shared/gql-types';
11
10
  import { dateToTimelessDateString } from '@shared/helpers';
12
11
  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,7 +20,12 @@ 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 [business, client] = await Promise.all([businessPromise, clientPromise]);
23
+ const greenInvoiceClientPromise = getClientFromGreenInvoiceClient(injector, contract.client_id);
24
+ const [business, client, greenInvoiceClient] = await Promise.all([
25
+ businessPromise,
26
+ clientPromise,
27
+ greenInvoiceClientPromise,
28
+ ]);
24
29
 
25
30
  if (!business) {
26
31
  throw new GraphQLError(`Business ID="${contract.client_id}" not found`);
@@ -30,9 +35,7 @@ export const convertContractToDraft = async (
30
35
  throw new GraphQLError(`Client not found for business ID="${contract.client_id}"`);
31
36
  }
32
37
 
33
- const greenInvoiceId = validateClientIntegrations(client.integrations)?.greenInvoiceId;
34
-
35
- if (!greenInvoiceId) {
38
+ if (!greenInvoiceClient) {
36
39
  throw new GraphQLError(`Green invoice match not found for business ID="${contract.client_id}"`);
37
40
  }
38
41
 
@@ -42,7 +45,7 @@ export const convertContractToDraft = async (
42
45
  const year = today.getFullYear() + (today.getMonth() === 0 ? -1 : 0);
43
46
  const month = format(subMonths(today, 1), 'MMMM');
44
47
 
45
- const documentInput: Omit<NewDocumentInfo, 'client'> & { client: string | undefined } = {
48
+ const documentInput: NewDocumentInfo = {
46
49
  remarks: `${contract.purchase_orders[0] ? `PO: ${contract.purchase_orders[0]}${contract.remarks ? ', ' : ''}` : ''}${contract.remarks ?? ''}`,
47
50
  description: `GraphQL Hive Enterprise License - ${month} ${year}`,
48
51
  type: normalizeDocumentType(contract.document_type),
@@ -53,7 +56,10 @@ export const convertContractToDraft = async (
53
56
  vatType: 'EXEMPT',
54
57
  rounding: false,
55
58
  signed: true,
56
- client: greenInvoiceId,
59
+ client: {
60
+ ...greenInvoiceClient,
61
+ emails: [...((client.emails?.filter(Boolean) as string[]) ?? [])],
62
+ },
57
63
  income: [
58
64
  {
59
65
  description: `GraphQL Hive Enterprise License - ${month} ${year}`,
@@ -5,16 +5,51 @@ 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';
9
8
  import { BusinessesProvider } from '@modules/financial-entities/providers/businesses.provider.js';
10
9
  import { ClientsProvider } from '@modules/financial-entities/providers/clients.provider.js';
11
10
  import {
12
11
  IGetBusinessesByIdsResult,
13
12
  IGetClientsByIdsResult,
14
13
  } from '@modules/financial-entities/types.js';
15
- import { ClientUpdateInput, UpdateBusinessInput } from '@shared/gql-types';
14
+ import { ClientUpdateInput, GreenInvoiceClient, UpdateBusinessInput } from '@shared/gql-types';
16
15
  import { countryCodeToGreenInvoiceCountry } from './green-invoice.helper.js';
17
16
 
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
+
18
53
  function convertLocalClientToGreenInvoiceCreateClientInput(
19
54
  localClient: IGetClientsByIdsResult,
20
55
  localBusiness: IGetBusinessesByIdsResult,
@@ -99,15 +134,10 @@ export async function addGreenInvoiceClient(clientId: string, injector: Injector
99
134
  throw new Error('Failed to create Green Invoice client');
100
135
  }
101
136
 
102
- const integrations = validateClientIntegrations(localClient.integrations);
103
-
104
137
  // add green invoice id to local client
105
138
  await injector.get(ClientsProvider).updateClient({
106
139
  businessId: clientId,
107
- integrations: {
108
- ...integrations,
109
- greenInvoiceId: greenInvoiceClient.id,
110
- },
140
+ greenInvoiceId: greenInvoiceClient.id,
111
141
  });
112
142
  } catch (error) {
113
143
  const message = 'Error adding Green Invoice client';
@@ -186,16 +216,7 @@ export async function updateGreenInvoiceClient(
186
216
  localBusinessPromise,
187
217
  localClientPromise,
188
218
  ]);
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) {
219
+ if (!localBusiness?.name || !localClient?.green_invoice_id) {
199
220
  // We cannot update a client in Green Invoice without its ID.
200
221
  console.warn(
201
222
  `Cannot update Green Invoice client: missing local business name or client ID for business${clientId}`,
@@ -212,7 +233,7 @@ export async function updateGreenInvoiceClient(
212
233
  }
213
234
 
214
235
  const greenInvoiceClient = await injector.get(GreenInvoiceClientProvider).updateClient({
215
- id: greenInvoiceId,
236
+ id: localClient.green_invoice_id,
216
237
  input: fieldsToUpdate,
217
238
  });
218
239
 
@@ -25,15 +25,14 @@ 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';
29
28
  import { ClientsProvider } from '@modules/financial-entities/providers/clients.provider.js';
30
29
  import {
31
30
  Currency,
32
31
  DocumentType,
33
32
  GreenInvoiceCountry,
34
33
  GreenInvoicePaymentType,
34
+ NewDocumentInfo,
35
35
  NewDocumentInput,
36
- ResolversTypes,
37
36
  type GreenInvoiceDiscountType,
38
37
  type GreenInvoiceDocumentLang,
39
38
  type GreenInvoiceLinkType,
@@ -1072,11 +1071,11 @@ export async function insertNewDocumentFromGreenInvoice(
1072
1071
  const documentType = normalizeDocumentType(greenInvoiceDoc.type);
1073
1072
  const isOwnerCreditor = greenInvoiceDoc.amount > 0 && documentType !== DocumentType.CreditInvoice;
1074
1073
 
1074
+ const fileUrl = greenInvoiceDoc.url.en ?? greenInvoiceDoc.url.origin;
1075
+
1075
1076
  try {
1076
1077
  // generate preview image via cloudinary
1077
- const imagePromise = injector
1078
- .get(CloudinaryProvider)
1079
- .uploadInvoiceToCloudinary(greenInvoiceDoc.url.origin);
1078
+ const imagePromise = injector.get(CloudinaryProvider).uploadInvoiceToCloudinary(fileUrl);
1080
1079
 
1081
1080
  // Get matching business
1082
1081
  const clientPromise = greenInvoiceDoc.client.id
@@ -1090,10 +1089,10 @@ export async function insertNewDocumentFromGreenInvoice(
1090
1089
  const fileHashPromise = async () => {
1091
1090
  try {
1092
1091
  // Before creating rawDocument
1093
- const fileResponse = await fetch(greenInvoiceDoc.url.origin);
1092
+ const fileResponse = await fetch(fileUrl);
1094
1093
  if (!fileResponse.ok) {
1095
1094
  // Handle error, maybe log and continue with null hash
1096
- throw new Error(`Failed to fetch file from GreenInvoice: ${greenInvoiceDoc.url.origin}`);
1095
+ throw new Error(`Failed to fetch file from GreenInvoice: ${fileUrl}`);
1097
1096
  }
1098
1097
  const fileContent = await fileResponse.text();
1099
1098
  const fileHash = hashStringToInt(fileContent).toString();
@@ -1248,24 +1247,18 @@ export async function convertDocumentInputIntoGreenInvoiceInput(
1248
1247
  if (!clientInfo) {
1249
1248
  throw new GraphQLError(`Client with ID ${initialInput.client.id} not found`);
1250
1249
  }
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) {
1250
+ if (!clientInfo.green_invoice_id) {
1260
1251
  throw new GraphQLError(`Client with ID ${initialInput.client.id} not found in Green Invoice`);
1261
1252
  }
1262
1253
  const greenInvoiceClient = await injector
1263
1254
  .get(GreenInvoiceClientProvider)
1264
- .clientLoader.load(greenInvoiceId);
1255
+ .clientLoader.load(clientInfo.green_invoice_id);
1265
1256
  if (!greenInvoiceClient) {
1266
- throw new GraphQLError(`Green Invoice client with ID ${greenInvoiceId} not found`);
1257
+ throw new GraphQLError(
1258
+ `Green Invoice client with ID ${clientInfo.green_invoice_id} not found`,
1259
+ );
1267
1260
  }
1268
- const emails: (string | null)[] = ['ap@the-guild.dev']; // TODO: remove hardcoded email
1261
+ const emails: (string | null)[] = ['ap@the-guild.dev'];
1269
1262
  const inputEmails = initialInput.client?.emails?.filter(Boolean) ?? [];
1270
1263
  if (inputEmails.length) {
1271
1264
  emails.push(...inputEmails);
@@ -1273,7 +1266,7 @@ export async function convertDocumentInputIntoGreenInvoiceInput(
1273
1266
  emails.push(...(greenInvoiceClient.emails ?? []));
1274
1267
  }
1275
1268
  client = {
1276
- id: greenInvoiceClient.id,
1269
+ id: clientInfo.green_invoice_id,
1277
1270
  country: greenInvoiceClient.country,
1278
1271
  name: greenInvoiceClient.name,
1279
1272
  phone: greenInvoiceClient.phone,
@@ -1330,10 +1323,18 @@ export async function convertDocumentInputIntoGreenInvoiceInput(
1330
1323
 
1331
1324
  export function convertGreenInvoiceDocumentToLocalDocumentInfo(
1332
1325
  greenInvoiceDocument: _DOLLAR_defs_Document,
1333
- ): ResolversTypes['NewDocumentInfo'] {
1326
+ ): NewDocumentInfo {
1334
1327
  return {
1335
1328
  ...greenInvoiceDocument,
1336
- client: greenInvoiceDocument.client?.id,
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,
1337
1338
  currency: greenInvoiceDocument.currency as Currency,
1338
1339
  income: greenInvoiceDocument.income?.filter(Boolean).map(income => ({
1339
1340
  ...income!,