@accounter/server 0.0.8-alpha-20251105180132-1c81096625a160ce926416f8206cb74fcf4f769f → 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 -15
- package/dist/green-invoice-graphql/src/mesh-artifacts/index.js +2 -2
- package/dist/green-invoice-graphql/src/mesh-artifacts/index.js.map +1 -1
- 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 +89 -28
- 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 +6 -6
- 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 +99 -34
- package/src/modules/green-invoice/typeDefs/green-invoice.graphql.ts +4 -0
|
@@ -942,10 +942,8 @@ export type Client = {
|
|
|
942
942
|
readonly __typename?: 'Client';
|
|
943
943
|
readonly emails: ReadonlyArray<Scalars['String']['output']>;
|
|
944
944
|
readonly generatedDocumentType: DocumentType;
|
|
945
|
-
readonly greenInvoiceId?: Maybe<Scalars['UUID']['output']>;
|
|
946
|
-
readonly greenInvoiceInfo?: Maybe<GreenInvoiceClient>;
|
|
947
|
-
readonly hiveId?: Maybe<Scalars['String']['output']>;
|
|
948
945
|
readonly id: Scalars['UUID']['output'];
|
|
946
|
+
readonly integrations: ClientIntegrations;
|
|
949
947
|
readonly originalBusiness: LtdFinancialEntity;
|
|
950
948
|
};
|
|
951
949
|
|
|
@@ -954,16 +952,36 @@ export type ClientInsertInput = {
|
|
|
954
952
|
readonly businessId: Scalars['UUID']['input'];
|
|
955
953
|
readonly emails?: InputMaybe<ReadonlyArray<Scalars['String']['input']>>;
|
|
956
954
|
readonly generatedDocumentType: DocumentType;
|
|
955
|
+
readonly integrations?: InputMaybe<ClientIntegrationsInput>;
|
|
956
|
+
};
|
|
957
|
+
|
|
958
|
+
/** integrations associated with a client */
|
|
959
|
+
export type ClientIntegrations = {
|
|
960
|
+
readonly __typename?: 'ClientIntegrations';
|
|
961
|
+
readonly greenInvoiceInfo?: Maybe<GreenInvoiceClient>;
|
|
962
|
+
readonly hiveId?: Maybe<Scalars['String']['output']>;
|
|
963
|
+
readonly id: Scalars['ID']['output'];
|
|
964
|
+
readonly linearId?: Maybe<Scalars['String']['output']>;
|
|
965
|
+
readonly notionId?: Maybe<Scalars['String']['output']>;
|
|
966
|
+
readonly slackChannelKey?: Maybe<Scalars['String']['output']>;
|
|
967
|
+
readonly workflowyUrl?: Maybe<Scalars['String']['output']>;
|
|
968
|
+
};
|
|
969
|
+
|
|
970
|
+
/** integrations input for client insert/update */
|
|
971
|
+
export type ClientIntegrationsInput = {
|
|
957
972
|
readonly greenInvoiceId?: InputMaybe<Scalars['UUID']['input']>;
|
|
958
973
|
readonly hiveId?: InputMaybe<Scalars['String']['input']>;
|
|
974
|
+
readonly linearId?: InputMaybe<Scalars['String']['input']>;
|
|
975
|
+
readonly notionId?: InputMaybe<Scalars['String']['input']>;
|
|
976
|
+
readonly slackChannelKey?: InputMaybe<Scalars['String']['input']>;
|
|
977
|
+
readonly workflowyUrl?: InputMaybe<Scalars['String']['input']>;
|
|
959
978
|
};
|
|
960
979
|
|
|
961
980
|
/** fields for updating an existing client */
|
|
962
981
|
export type ClientUpdateInput = {
|
|
963
982
|
readonly emails?: InputMaybe<ReadonlyArray<Scalars['String']['input']>>;
|
|
964
983
|
readonly generatedDocumentType?: InputMaybe<DocumentType>;
|
|
965
|
-
readonly
|
|
966
|
-
readonly hiveId?: InputMaybe<Scalars['String']['input']>;
|
|
984
|
+
readonly integrations?: InputMaybe<ClientIntegrationsInput>;
|
|
967
985
|
readonly newBusinessId?: InputMaybe<Scalars['UUID']['input']>;
|
|
968
986
|
};
|
|
969
987
|
|
|
@@ -5162,6 +5180,8 @@ export type ResolversTypes = {
|
|
|
5162
5180
|
ChargesWithLedgerChangesResult: ResolverTypeWrapper<Omit<ChargesWithLedgerChangesResult, 'charge'> & { charge?: Maybe<ResolversTypes['Charge']> }>;
|
|
5163
5181
|
Client: ResolverTypeWrapper<IGetAllClientsResult>;
|
|
5164
5182
|
ClientInsertInput: ClientInsertInput;
|
|
5183
|
+
ClientIntegrations: ResolverTypeWrapper<IGetAllClientsResult>;
|
|
5184
|
+
ClientIntegrationsInput: ClientIntegrationsInput;
|
|
5165
5185
|
ClientUpdateInput: ClientUpdateInput;
|
|
5166
5186
|
CommonCharge: ResolverTypeWrapper<IGetChargesByIdsResult>;
|
|
5167
5187
|
CommonError: ResolverTypeWrapper<CommonError>;
|
|
@@ -5228,7 +5248,7 @@ export type ResolversTypes = {
|
|
|
5228
5248
|
Fund: ResolverTypeWrapper<ResolversInterfaceTypes<ResolversTypes>['Fund']>;
|
|
5229
5249
|
GenerateMonthlyClientDocumentsResult: ResolverTypeWrapper<GenerateMonthlyClientDocumentsResult>;
|
|
5230
5250
|
GeneratedLedgerRecords: ResolverTypeWrapper<ResolversUnionTypes<ResolversTypes>['GeneratedLedgerRecords']>;
|
|
5231
|
-
GreenInvoiceClient: ResolverTypeWrapper<
|
|
5251
|
+
GreenInvoiceClient: ResolverTypeWrapper<string>;
|
|
5232
5252
|
GreenInvoiceClientInput: GreenInvoiceClientInput;
|
|
5233
5253
|
GreenInvoiceCountry: GreenInvoiceCountry;
|
|
5234
5254
|
GreenInvoiceDiscount: ResolverTypeWrapper<GreenInvoiceDiscount>;
|
|
@@ -5451,6 +5471,8 @@ export type ResolversParentTypes = {
|
|
|
5451
5471
|
ChargesWithLedgerChangesResult: Omit<ChargesWithLedgerChangesResult, 'charge'> & { charge?: Maybe<ResolversParentTypes['Charge']> };
|
|
5452
5472
|
Client: IGetAllClientsResult;
|
|
5453
5473
|
ClientInsertInput: ClientInsertInput;
|
|
5474
|
+
ClientIntegrations: IGetAllClientsResult;
|
|
5475
|
+
ClientIntegrationsInput: ClientIntegrationsInput;
|
|
5454
5476
|
ClientUpdateInput: ClientUpdateInput;
|
|
5455
5477
|
CommonCharge: IGetChargesByIdsResult;
|
|
5456
5478
|
CommonError: CommonError;
|
|
@@ -5508,7 +5530,7 @@ export type ResolversParentTypes = {
|
|
|
5508
5530
|
Fund: ResolversInterfaceTypes<ResolversParentTypes>['Fund'];
|
|
5509
5531
|
GenerateMonthlyClientDocumentsResult: GenerateMonthlyClientDocumentsResult;
|
|
5510
5532
|
GeneratedLedgerRecords: ResolversUnionTypes<ResolversParentTypes>['GeneratedLedgerRecords'];
|
|
5511
|
-
GreenInvoiceClient:
|
|
5533
|
+
GreenInvoiceClient: string;
|
|
5512
5534
|
GreenInvoiceClientInput: GreenInvoiceClientInput;
|
|
5513
5535
|
GreenInvoiceDiscount: GreenInvoiceDiscount;
|
|
5514
5536
|
GreenInvoiceDiscountInput: GreenInvoiceDiscountInput;
|
|
@@ -6165,14 +6187,23 @@ export type ChargesWithLedgerChangesResultResolvers<ContextType = GraphQLModules
|
|
|
6165
6187
|
export type ClientResolvers<ContextType = GraphQLModules.Context, ParentType extends ResolversParentTypes['Client'] = ResolversParentTypes['Client']> = {
|
|
6166
6188
|
emails?: Resolver<ReadonlyArray<ResolversTypes['String']>, ParentType, ContextType>;
|
|
6167
6189
|
generatedDocumentType?: Resolver<ResolversTypes['DocumentType'], ParentType, ContextType>;
|
|
6168
|
-
greenInvoiceId?: Resolver<Maybe<ResolversTypes['UUID']>, ParentType, ContextType>;
|
|
6169
|
-
greenInvoiceInfo?: Resolver<Maybe<ResolversTypes['GreenInvoiceClient']>, ParentType, ContextType>;
|
|
6170
|
-
hiveId?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
|
6171
6190
|
id?: Resolver<ResolversTypes['UUID'], ParentType, ContextType>;
|
|
6191
|
+
integrations?: Resolver<ResolversTypes['ClientIntegrations'], ParentType, ContextType>;
|
|
6172
6192
|
originalBusiness?: Resolver<ResolversTypes['LtdFinancialEntity'], ParentType, ContextType>;
|
|
6173
6193
|
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
|
6174
6194
|
};
|
|
6175
6195
|
|
|
6196
|
+
export type ClientIntegrationsResolvers<ContextType = GraphQLModules.Context, ParentType extends ResolversParentTypes['ClientIntegrations'] = ResolversParentTypes['ClientIntegrations']> = {
|
|
6197
|
+
greenInvoiceInfo?: Resolver<Maybe<ResolversTypes['GreenInvoiceClient']>, ParentType, ContextType>;
|
|
6198
|
+
hiveId?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
|
6199
|
+
id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
|
|
6200
|
+
linearId?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
|
6201
|
+
notionId?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
|
6202
|
+
slackChannelKey?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
|
6203
|
+
workflowyUrl?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
|
6204
|
+
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
|
6205
|
+
};
|
|
6206
|
+
|
|
6176
6207
|
export type CommonChargeResolvers<ContextType = GraphQLModules.Context, ParentType extends ResolversParentTypes['CommonCharge'] = ResolversParentTypes['CommonCharge']> = {
|
|
6177
6208
|
accountantApproval?: Resolver<ResolversTypes['AccountantStatus'], ParentType, ContextType>;
|
|
6178
6209
|
additionalDocuments?: Resolver<ReadonlyArray<ResolversTypes['Document']>, ParentType, ContextType>;
|
|
@@ -8010,6 +8041,7 @@ export type Resolvers<ContextType = GraphQLModules.Context> = {
|
|
|
8010
8041
|
ChargeSuggestions?: ChargeSuggestionsResolvers<ContextType>;
|
|
8011
8042
|
ChargesWithLedgerChangesResult?: ChargesWithLedgerChangesResultResolvers<ContextType>;
|
|
8012
8043
|
Client?: ClientResolvers<ContextType>;
|
|
8044
|
+
ClientIntegrations?: ClientIntegrationsResolvers<ContextType>;
|
|
8013
8045
|
CommonCharge?: CommonChargeResolvers<ContextType>;
|
|
8014
8046
|
CommonError?: CommonErrorResolvers<ContextType>;
|
|
8015
8047
|
CommonTransaction?: CommonTransactionResolvers<ContextType>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/** Types generated for queries found in "src/modules/financial-entities/providers/clients.provider.ts" */
|
|
2
2
|
export type document_type = 'CREDIT_INVOICE' | 'INVOICE' | 'INVOICE_RECEIPT' | 'OTHER' | 'PROFORMA' | 'RECEIPT' | 'UNPROCESSED';
|
|
3
3
|
|
|
4
|
+
export type Json = null | boolean | number | string | Json[] | { [key: string]: Json };
|
|
5
|
+
|
|
4
6
|
export type stringArray = (string)[];
|
|
5
7
|
|
|
6
8
|
/** 'GetAllClients' parameters type */
|
|
@@ -13,6 +15,7 @@ export interface IGetAllClientsResult {
|
|
|
13
15
|
emails: stringArray | null;
|
|
14
16
|
green_invoice_id: string;
|
|
15
17
|
hive_id: string | null;
|
|
18
|
+
integrations: Json | null;
|
|
16
19
|
remark: string | null;
|
|
17
20
|
}
|
|
18
21
|
|
|
@@ -34,6 +37,7 @@ export interface IGetClientsByIdsResult {
|
|
|
34
37
|
emails: stringArray | null;
|
|
35
38
|
green_invoice_id: string;
|
|
36
39
|
hive_id: string | null;
|
|
40
|
+
integrations: Json | null;
|
|
37
41
|
remark: string | null;
|
|
38
42
|
}
|
|
39
43
|
|
|
@@ -53,8 +57,10 @@ export interface IGetClientsByGreenInvoiceIdsResult {
|
|
|
53
57
|
business_id: string;
|
|
54
58
|
document_type: document_type;
|
|
55
59
|
emails: stringArray | null;
|
|
60
|
+
green_invoice_business_id: string | null;
|
|
56
61
|
green_invoice_id: string;
|
|
57
62
|
hive_id: string | null;
|
|
63
|
+
integrations: Json | null;
|
|
58
64
|
remark: string | null;
|
|
59
65
|
}
|
|
60
66
|
|
|
@@ -68,8 +74,7 @@ export interface IGetClientsByGreenInvoiceIdsQuery {
|
|
|
68
74
|
export interface IUpdateClientParams {
|
|
69
75
|
businessId?: string | null | void;
|
|
70
76
|
emails?: stringArray | null | void;
|
|
71
|
-
|
|
72
|
-
hiveId?: string | null | void;
|
|
77
|
+
integrations?: Json | null | void;
|
|
73
78
|
newBusinessId?: string | null | void;
|
|
74
79
|
}
|
|
75
80
|
|
|
@@ -80,6 +85,7 @@ export interface IUpdateClientResult {
|
|
|
80
85
|
emails: stringArray | null;
|
|
81
86
|
green_invoice_id: string;
|
|
82
87
|
hive_id: string | null;
|
|
88
|
+
integrations: Json | null;
|
|
83
89
|
remark: string | null;
|
|
84
90
|
}
|
|
85
91
|
|
|
@@ -109,8 +115,7 @@ export interface IDeleteClientQuery {
|
|
|
109
115
|
export interface IInsertClientParams {
|
|
110
116
|
businessId?: string | null | void;
|
|
111
117
|
emails?: stringArray | null | void;
|
|
112
|
-
|
|
113
|
-
hiveId?: string | null | void;
|
|
118
|
+
integrations?: Json | null | void;
|
|
114
119
|
}
|
|
115
120
|
|
|
116
121
|
/** 'InsertClient' return type */
|
|
@@ -120,6 +125,7 @@ export interface IInsertClientResult {
|
|
|
120
125
|
emails: stringArray | null;
|
|
121
126
|
green_invoice_id: string;
|
|
122
127
|
hive_id: string | null;
|
|
128
|
+
integrations: Json | null;
|
|
123
129
|
remark: string | null;
|
|
124
130
|
}
|
|
125
131
|
|
|
@@ -17,7 +17,8 @@ export namespace FinancialEntitiesModule {
|
|
|
17
17
|
Suggestions: 'phrases' | 'tags' | 'description' | 'emails' | 'emailListener' | 'priority';
|
|
18
18
|
SuggestionsEmailListenerConfig: 'internalEmailLinks' | 'emailBody' | 'attachments';
|
|
19
19
|
PersonalFinancialEntity: 'id' | 'name' | 'email' | 'pcn874RecordType' | 'irsCode' | 'isActive' | 'createdAt' | 'updatedAt';
|
|
20
|
-
Client: 'id' | 'originalBusiness' | '
|
|
20
|
+
Client: 'id' | 'originalBusiness' | 'emails' | 'generatedDocumentType' | 'integrations';
|
|
21
|
+
ClientIntegrations: 'id' | 'hiveId' | 'linearId' | 'slackChannelKey' | 'notionId' | 'workflowyUrl';
|
|
21
22
|
PaginatedFinancialEntities: 'nodes' | 'pageInfo';
|
|
22
23
|
TaxCategory: 'id' | 'name' | 'irsCode' | 'createdAt' | 'updatedAt' | 'isActive';
|
|
23
24
|
CommonCharge: 'owner' | 'counterparty' | 'taxCategory';
|
|
@@ -61,8 +62,9 @@ export namespace FinancialEntitiesModule {
|
|
|
61
62
|
InsertNewBusinessInput: 'name' | 'sortCode' | 'country' | 'hebrewName' | 'address' | 'email' | 'website' | 'phoneNumber' | 'governmentId' | 'taxCategory' | 'exemptDealer' | 'suggestions' | 'optionalVAT' | 'isReceiptEnough' | 'isDocumentsOptional' | 'pcn874RecordType' | 'irsCode' | 'isActive';
|
|
62
63
|
SuggestionsInput: 'phrases' | 'tags' | 'description' | 'emails' | 'emailListener' | 'priority';
|
|
63
64
|
SuggestionsEmailListenerConfigInput: 'internalEmailLinks' | 'emailBody' | 'attachments';
|
|
64
|
-
ClientInsertInput: 'businessId' | '
|
|
65
|
-
ClientUpdateInput: '
|
|
65
|
+
ClientInsertInput: 'businessId' | 'emails' | 'generatedDocumentType' | 'integrations';
|
|
66
|
+
ClientUpdateInput: 'newBusinessId' | 'emails' | 'generatedDocumentType' | 'integrations';
|
|
67
|
+
ClientIntegrationsInput: 'greenInvoiceId' | 'hiveId' | 'linearId' | 'slackChannelKey' | 'notionId' | 'workflowyUrl';
|
|
66
68
|
UpdateTaxCategoryInput: 'name' | 'sortCode' | 'irsCode' | 'isActive' | 'hashavshevetName' | 'taxExcluded';
|
|
67
69
|
InsertTaxCategoryInput: 'name' | 'sortCode' | 'irsCode' | 'hashavshevetName' | 'taxExcluded' | 'isActive';
|
|
68
70
|
UpdateChargeInput: 'counterpartyId' | 'ownerId';
|
|
@@ -126,7 +128,8 @@ export namespace FinancialEntitiesModule {
|
|
|
126
128
|
export type ClientUpdateInput = Pick<Types.ClientUpdateInput, DefinedInputFields['ClientUpdateInput']>;
|
|
127
129
|
export type ClientInsertInput = Pick<Types.ClientInsertInput, DefinedInputFields['ClientInsertInput']>;
|
|
128
130
|
export type DocumentType = Types.DocumentType;
|
|
129
|
-
export type
|
|
131
|
+
export type ClientIntegrations = Pick<Types.ClientIntegrations, DefinedFields['ClientIntegrations']>;
|
|
132
|
+
export type ClientIntegrationsInput = Pick<Types.ClientIntegrationsInput, DefinedInputFields['ClientIntegrationsInput']>;
|
|
130
133
|
export type PaginatedFinancialEntities = Pick<Types.PaginatedFinancialEntities, DefinedFields['PaginatedFinancialEntities']>;
|
|
131
134
|
export type UpdateChargeInput = Types.UpdateChargeInput;
|
|
132
135
|
export type Transaction = Types.Transaction;
|
|
@@ -160,6 +163,7 @@ export namespace FinancialEntitiesModule {
|
|
|
160
163
|
export type SuggestionsEmailListenerConfigResolvers = Pick<Types.SuggestionsEmailListenerConfigResolvers, DefinedFields['SuggestionsEmailListenerConfig']>;
|
|
161
164
|
export type PersonalFinancialEntityResolvers = Pick<Types.PersonalFinancialEntityResolvers, DefinedFields['PersonalFinancialEntity'] | '__isTypeOf'>;
|
|
162
165
|
export type ClientResolvers = Pick<Types.ClientResolvers, DefinedFields['Client'] | '__isTypeOf'>;
|
|
166
|
+
export type ClientIntegrationsResolvers = Pick<Types.ClientIntegrationsResolvers, DefinedFields['ClientIntegrations']>;
|
|
163
167
|
export type PaginatedFinancialEntitiesResolvers = Pick<Types.PaginatedFinancialEntitiesResolvers, DefinedFields['PaginatedFinancialEntities']>;
|
|
164
168
|
export type TaxCategoryResolvers = Pick<Types.TaxCategoryResolvers, DefinedFields['TaxCategory'] | '__isTypeOf'>;
|
|
165
169
|
export type CommonChargeResolvers = Pick<Types.CommonChargeResolvers, DefinedFields['CommonCharge']>;
|
|
@@ -204,6 +208,7 @@ export namespace FinancialEntitiesModule {
|
|
|
204
208
|
SuggestionsEmailListenerConfig?: SuggestionsEmailListenerConfigResolvers;
|
|
205
209
|
PersonalFinancialEntity?: PersonalFinancialEntityResolvers;
|
|
206
210
|
Client?: ClientResolvers;
|
|
211
|
+
ClientIntegrations?: ClientIntegrationsResolvers;
|
|
207
212
|
PaginatedFinancialEntities?: PaginatedFinancialEntitiesResolvers;
|
|
208
213
|
TaxCategory?: TaxCategoryResolvers;
|
|
209
214
|
CommonCharge?: CommonChargeResolvers;
|
|
@@ -446,11 +451,18 @@ export namespace FinancialEntitiesModule {
|
|
|
446
451
|
'*'?: gm.Middleware[];
|
|
447
452
|
id?: gm.Middleware[];
|
|
448
453
|
originalBusiness?: gm.Middleware[];
|
|
449
|
-
greenInvoiceId?: gm.Middleware[];
|
|
450
|
-
hiveId?: gm.Middleware[];
|
|
451
454
|
emails?: gm.Middleware[];
|
|
452
455
|
generatedDocumentType?: gm.Middleware[];
|
|
453
|
-
|
|
456
|
+
integrations?: gm.Middleware[];
|
|
457
|
+
};
|
|
458
|
+
ClientIntegrations?: {
|
|
459
|
+
'*'?: gm.Middleware[];
|
|
460
|
+
id?: gm.Middleware[];
|
|
461
|
+
hiveId?: gm.Middleware[];
|
|
462
|
+
linearId?: gm.Middleware[];
|
|
463
|
+
slackChannelKey?: gm.Middleware[];
|
|
464
|
+
notionId?: gm.Middleware[];
|
|
465
|
+
workflowyUrl?: gm.Middleware[];
|
|
454
466
|
};
|
|
455
467
|
PaginatedFinancialEntities?: {
|
|
456
468
|
'*'?: gm.Middleware[];
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { GraphQLError } from 'graphql';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
// Zod schema matching the GraphQL `ClientIntegrations` type
|
|
5
|
+
export const ClientIntegrationsSchema = z
|
|
6
|
+
.object({
|
|
7
|
+
greenInvoiceId: z.uuid().optional().nullable(),
|
|
8
|
+
hiveId: z.string().optional().nullable(),
|
|
9
|
+
linearId: z.string().optional().nullable(),
|
|
10
|
+
slackChannelKey: z.string().optional().nullable(),
|
|
11
|
+
notionId: z.string().optional().nullable(),
|
|
12
|
+
workflowyUrl: z.string().optional().nullable(),
|
|
13
|
+
})
|
|
14
|
+
.strict();
|
|
15
|
+
|
|
16
|
+
export type ClientIntegrations = z.infer<typeof ClientIntegrationsSchema>;
|
|
17
|
+
|
|
18
|
+
export function validateClientIntegrations(input: unknown): ClientIntegrations {
|
|
19
|
+
try {
|
|
20
|
+
const { data, success, error } = ClientIntegrationsSchema.safeParse(input);
|
|
21
|
+
if (!success) {
|
|
22
|
+
throw new Error(`Parsing error: ${error}`);
|
|
23
|
+
}
|
|
24
|
+
return data;
|
|
25
|
+
} catch (error) {
|
|
26
|
+
throw new GraphQLError(`Failed to validate client integrations: ${error}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -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}`,
|