From 5c5d4b55337a5fb0f7cb19f9f618cab7d7429d32 Mon Sep 17 00:00:00 2001 From: Seesti Date: Fri, 14 Jun 2024 18:21:01 +0300 Subject: [PATCH] changed configuration of variables, removed SendInvoiceToMyCompany --- maventa/MaventaConfig.ts | 16 ----- maventa/MaventaService.system.test.ts | 85 ++++++++++++++++++--------- maventa/MaventaService.ts | 75 +++++++++++------------ maventa/maventa-constants.ts | 3 + maventa/types/MaventaAction.ts | 16 +++-- maventa/types/MaventaConfig.ts | 8 +++ maventa/types/MaventaFile.ts | 16 +++-- maventa/types/MaventaInvoice.ts | 71 +++++++++++++++------- maventa/types/MaventaRecipient.ts | 14 ++--- maventa/types/MaventaSender.ts | 14 ++--- 10 files changed, 176 insertions(+), 142 deletions(-) delete mode 100644 maventa/MaventaConfig.ts create mode 100644 maventa/maventa-constants.ts create mode 100644 maventa/types/MaventaConfig.ts diff --git a/maventa/MaventaConfig.ts b/maventa/MaventaConfig.ts deleted file mode 100644 index 87acfd7..0000000 --- a/maventa/MaventaConfig.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { ProcessUtils } from '../ProcessUtils'; - -ProcessUtils.initEnvFromDefaultFiles(); - -const isTesting = process.env.IS_TESTING === 'true'; - -const MaventaConfig = { - baseUrl: isTesting ? 'https://ax-stage.maventa.com' : 'https://ax.maventa.com', - clientId: process.env.CLIENT_ID!, - clientSecret: process.env.CLIENT_SECRET!, - scope: process.env.SCOPE!, - vendorApiKey: process.env.VENDOR_API_KEY!, - companyEDI: process.env.COMPANY_EDI!, -}; - -export { MaventaConfig }; diff --git a/maventa/MaventaService.system.test.ts b/maventa/MaventaService.system.test.ts index 24f8803..81da89c 100644 --- a/maventa/MaventaService.system.test.ts +++ b/maventa/MaventaService.system.test.ts @@ -1,32 +1,59 @@ +// MaventaService.system.test.ts + +import { ProcessUtils } from "../ProcessUtils"; +ProcessUtils.initEnvFromDefaultFiles(); + import { MaventaService } from './MaventaService'; -import { MaventaConfig } from './MaventaConfig'; +import { LogLevel } from "../types/LogLevel"; +import { RequestClientImpl } from "../RequestClientImpl"; +import { HttpService } from "../HttpService"; import { HgNode } from '../../node/HgNode'; +import { MaventaConfig } from './types/MaventaConfig'; +import { DEFAULT_MAVENTA_BASE_URL_TEST, DEFAULT_MAVENTA_SCOPE } from "./maventa-constants"; + +const MAVENTA_BASE_URL = DEFAULT_MAVENTA_BASE_URL_TEST; +const CLIENT_ID = process.env.CLIENT_ID ?? ''; +const CLIENT_SECRET = process.env.CLIENT_SECRET ?? ''; +const SCOPE = DEFAULT_MAVENTA_SCOPE; +const VENDOR_API_KEY = process.env.VENDOR_API_KEY ?? ''; +const COMPANY_EDI = process.env.COMPANY_EDI ?? ''; + +RequestClientImpl.setLogLevel(LogLevel.NONE); +HttpService.setLogLevel(LogLevel.NONE); + +console.log('MaventaService system tests loaded'); + +(CLIENT_ID && CLIENT_SECRET && VENDOR_API_KEY && COMPANY_EDI ? describe : describe.skip)('system', () => { + + describe('MaventaService', () => { + let service: MaventaService; + let config: MaventaConfig; + + beforeAll(() => { + HgNode.initialize(); + }); + + beforeEach(() => { + config = { + baseUrl: MAVENTA_BASE_URL, + clientId: CLIENT_ID, + clientSecret: CLIENT_SECRET, + scope: SCOPE, + vendorApiKey: VENDOR_API_KEY, + companyEDI: COMPANY_EDI + }; + service = new MaventaService(config); + }); + + describe('#listInvoices', () => { + it('should fetch real invoices from the Maventa API', async () => { + const invoices = await service.listInvoices(); + expect(Array.isArray(invoices)).toBe(true); + expect(invoices.length).toBeGreaterThan(0); + expect(invoices[0]).toHaveProperty('id'); + expect(invoices[0]).toHaveProperty('status'); + }); + }); + }); -describe('MaventaService System Tests', () => { - - beforeAll(() => { - HgNode.initialize(); - console.log('Running system tests against:', MaventaConfig.baseUrl); - }); - - it('should fetch real invoices from the Maventa API', async () => { - const invoices = await MaventaService.listInvoices(); - console.log('Fetched invoices:', invoices); - - expect(invoices).toBeInstanceOf(Array); - if (invoices.length > 0) { - console.log(`Displaying details of the first invoice:`); - console.log(`Invoice ID: ${invoices[0].id}`); - console.log(`Invoice Status: ${invoices[0].status}`); - console.log(`Invoice Amount: ${invoices[0].sum}`); - - expect(invoices[0]).toHaveProperty('id'); - expect(invoices[0]).toHaveProperty('status'); - expect(invoices[0].id).toBeDefined(); - expect(invoices[0].status).toBeDefined(); - } else { - console.log('No invoices found.'); - } - }); - -}); +}); \ No newline at end of file diff --git a/maventa/MaventaService.ts b/maventa/MaventaService.ts index 15f6312..f010f5b 100644 --- a/maventa/MaventaService.ts +++ b/maventa/MaventaService.ts @@ -1,21 +1,34 @@ -function isMaventaInvoice(data: any): data is MaventaInvoice { - return data && typeof data === 'object' && 'id' in data && 'status' in data; -} - import { HttpService } from '../HttpService'; -import { MaventaConfig as config } from './MaventaConfig'; -import { MaventaInvoice } from './types/MaventaInvoice'; +import { MaventaConfig } from './types/MaventaConfig'; +import { MaventaInvoice, isMaventaInvoice } from './types/MaventaInvoice'; import { MaventaTokenResponse } from './types/MaventaTokenResponse'; +import { DEFAULT_MAVENTA_BASE_URL, DEFAULT_MAVENTA_BASE_URL_TEST, DEFAULT_MAVENTA_SCOPE } from './maventa-constants'; export class MaventaService { + private readonly _config: MaventaConfig; + private _token: string | undefined; + + constructor(config: Partial) { + const isTesting = process.env.IS_TESTING === 'true'; + this._config = { + baseUrl: config.baseUrl || (isTesting ? DEFAULT_MAVENTA_BASE_URL_TEST : DEFAULT_MAVENTA_BASE_URL), + clientId: config.clientId || process.env.CLIENT_ID!, + clientSecret: config.clientSecret || process.env.CLIENT_SECRET!, + scope: config.scope || DEFAULT_MAVENTA_SCOPE, + vendorApiKey: config.vendorApiKey || process.env.VENDOR_API_KEY!, + companyEDI: config.companyEDI || process.env.COMPANY_EDI!, + }; + } + + private async _getAccessToken(): Promise { + if (this._token) return this._token; - private static async _getAccessToken(): Promise { const postData = new URLSearchParams({ grant_type: 'client_credentials', - client_id: config.clientId, - client_secret: config.clientSecret, - scope: config.scope, - vendor_api_key: config.vendorApiKey, + client_id: this._config.clientId, + client_secret: this._config.clientSecret, + scope: this._config.scope, + vendor_api_key: this._config.vendorApiKey, }).toString(); const headers = { @@ -23,23 +36,24 @@ export class MaventaService { 'Content-Length': Buffer.byteLength(postData).toString(), }; - const url = `${config.baseUrl}/oauth2/token`; + const url = `${this._config.baseUrl}/oauth2/token`; const result = await HttpService.postText(url, postData, headers); if (!result) throw new Error("Failed to retrieve access token"); const response: MaventaTokenResponse = JSON.parse(result); - return response.access_token; + this._token = response.access_token; + return this._token; } - public static async listInvoices(): Promise { - const token = await MaventaService._getAccessToken(); + public async listInvoices(): Promise { + const token = await this._getAccessToken(); const headers = { 'Authorization': `Bearer ${token}`, - 'Accept': 'from json', - 'User-Api-Key': config.clientSecret, - 'Company-UUID': config.clientId, + 'Accept': 'application/json', + 'User-Api-Key': this._config.clientSecret, + 'Company-UUID': this._config.clientId, }; - const url = `${config.baseUrl}/v1/invoices`; + const url = `${this._config.baseUrl}/v1/invoices`; const response = await HttpService.getJson(url, headers); if (!response || !Array.isArray(response)) throw new Error("Failed to list invoices or wrong format"); @@ -49,25 +63,4 @@ export class MaventaService { } return invoices; } - - public static async sendInvoiceToMyCompany(): Promise { - const token = await MaventaService._getAccessToken(); - const url = `${config.baseUrl}/v1/invoices`; - const headers = { - 'Authorization': `Bearer ${token}`, - 'User-Api-Key': config.clientSecret, - 'Company-UUID': config.clientId, - }; - - const formData = { - file: { path: './src/io/hyperify/core/maventa/types/invoice.xml', filename: 'invoice.xml' }, - format: 'VISMAXL60', - recipient_eia: config.companyEDI, - }; - - const result = await HttpService.postJson(url, formData, headers); - if (!result || !isMaventaInvoice(result)) throw new Error("Failed to send invoice or response format is incorrect"); - - return result; - } -} +} \ No newline at end of file diff --git a/maventa/maventa-constants.ts b/maventa/maventa-constants.ts new file mode 100644 index 0000000..3ee4645 --- /dev/null +++ b/maventa/maventa-constants.ts @@ -0,0 +1,3 @@ +export const DEFAULT_MAVENTA_BASE_URL = 'https://ax.maventa.com'; +export const DEFAULT_MAVENTA_BASE_URL_TEST = 'https://ax-stage.maventa.com'; +export const DEFAULT_MAVENTA_SCOPE = 'eui'; \ No newline at end of file diff --git a/maventa/types/MaventaAction.ts b/maventa/types/MaventaAction.ts index 62b369d..03a3734 100644 --- a/maventa/types/MaventaAction.ts +++ b/maventa/types/MaventaAction.ts @@ -1,9 +1,7 @@ -interface MaventaAction { - type: string; - channel: string; - message: string | null; - key: string | null; - happened_at: string; -} - -export { MaventaAction } \ No newline at end of file +export interface MaventaAction { + readonly type: string; + readonly channel: string; + readonly message: string | null; + readonly key: string | null; + readonly happened_at: string; +} \ No newline at end of file diff --git a/maventa/types/MaventaConfig.ts b/maventa/types/MaventaConfig.ts new file mode 100644 index 0000000..d20b3dd --- /dev/null +++ b/maventa/types/MaventaConfig.ts @@ -0,0 +1,8 @@ +export interface MaventaConfig { + readonly baseUrl: string; + readonly clientId: string; + readonly clientSecret: string; + readonly scope: string; + readonly vendorApiKey: string; + readonly companyEDI: string; +} diff --git a/maventa/types/MaventaFile.ts b/maventa/types/MaventaFile.ts index da7335a..a75ef80 100644 --- a/maventa/types/MaventaFile.ts +++ b/maventa/types/MaventaFile.ts @@ -1,9 +1,7 @@ -interface MaventaFile { - id: string; - filename: string; - type: string; - mimetype: string; - href: string; -} - -export { MaventaFile } +export interface MaventaFile { + readonly id: string; + readonly filename: string; + readonly type: string; + readonly mimetype: string; + readonly href: string; +} \ No newline at end of file diff --git a/maventa/types/MaventaInvoice.ts b/maventa/types/MaventaInvoice.ts index f9e7a10..1215414 100644 --- a/maventa/types/MaventaInvoice.ts +++ b/maventa/types/MaventaInvoice.ts @@ -1,28 +1,57 @@ import { MaventaAction } from "./MaventaAction"; import { MaventaRecipient } from "./MaventaRecipient"; import { MaventaSender } from "./MaventaSender"; +import { MaventaFile } from "./MaventaFile"; +export interface MaventaRevisionObject { + readonly [key: string]: unknown; +} -interface MaventaInvoice { - id: string; - status: string; - reference: string | null; - number: string; - sender: MaventaSender; - recipient: MaventaRecipient; - received_at?: string; - created_at: string; - date: string; - date_due: string; - source_format: string; - sum: number; - sum_tax: number; - currency: string; - destination: string | null; - comment: string | null; - files: Array; - actions: Array; - revision: Record; +export interface MaventaInvoice { + readonly id: string; + readonly status: string; + readonly reference: string | null; + readonly number: string; + readonly sender: MaventaSender; + readonly recipient: MaventaRecipient; + readonly received_at?: string; + readonly created_at: string; + readonly date: string; + readonly date_due: string; + readonly source_format: string; + readonly sum: number; + readonly sum_tax: number; + readonly currency: string; + readonly destination: string | null; + readonly comment: string | null; + readonly files: readonly MaventaFile[]; + readonly actions: readonly MaventaAction[]; + readonly revision: MaventaRevisionObject; } -export { MaventaInvoice }; \ No newline at end of file +export function isMaventaInvoice(data: unknown): data is MaventaInvoice { + const record = data as MaventaInvoice; + return record != null && + typeof record === 'object' && + typeof record.id === 'string' && + typeof record.status === 'string' && + (typeof record.reference === 'string' || record.reference === null) && + typeof record.number === 'string' && + typeof record.sender === 'object' && record.sender !== null && + typeof record.recipient === 'object' && record.recipient !== null && + (typeof record.received_at === 'string' || record.received_at === undefined) && + typeof record.created_at === 'string' && + typeof record.date === 'string' && + typeof record.date_due === 'string' && + typeof record.source_format === 'string' && + typeof record.sum === 'number' && + typeof record.sum_tax === 'number' && + typeof record.currency === 'string' && + (typeof record.destination === 'string' || record.destination === null) && + (typeof record.comment === 'string' || record.comment === null) && + Array.isArray(record.files) && + record.files.every(file => typeof file === 'object' && file !== null) && + Array.isArray(record.actions) && + record.actions.every(action => typeof action === 'object' && action !== null) && + typeof record.revision === 'object' && record.revision !== null; +} diff --git a/maventa/types/MaventaRecipient.ts b/maventa/types/MaventaRecipient.ts index 0c0d8ab..b4619e6 100644 --- a/maventa/types/MaventaRecipient.ts +++ b/maventa/types/MaventaRecipient.ts @@ -1,9 +1,5 @@ -interface MaventaRecipient { - eia: string | null; - bid: string | null; - name: string; - country: string; - operator: string | null; -} - -export { MaventaRecipient } \ No newline at end of file +export interface MaventaRecipient { + readonly name: string; + readonly country: string; + readonly operator: string | null; +} \ No newline at end of file diff --git a/maventa/types/MaventaSender.ts b/maventa/types/MaventaSender.ts index 7eb6957..e2bd6f6 100644 --- a/maventa/types/MaventaSender.ts +++ b/maventa/types/MaventaSender.ts @@ -1,8 +1,6 @@ -interface MaventaSender { - eia: string | null; - bid: string | null; - name: string; - country: string; -} - -export { MaventaSender } \ No newline at end of file +export interface MaventaSender { + readonly eia: string | null; + readonly bid: string | null; + readonly name: string; + readonly country: string; +} \ No newline at end of file