@accounter/server
Version:
Accounter GraphQL server
128 lines • 6.88 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { GraphQLError } from 'graphql';
import { Injectable, Scope } from 'graphql-modules';
import { parseUniformFormatFiles } from '../../../../../shaam-uniform-format-generator/src/index.js';
import { CountryCode } from '../../../shared/enums.js';
import { TenantAwareDBClient } from '../../app-providers/tenant-db-client.js';
import { BusinessesProvider } from '../../financial-entities/providers/businesses.provider.js';
import { FinancialEntitiesProvider } from '../../financial-entities/providers/financial-entities.provider.js';
import { greenInvoiceCountryToCountryCode } from '../../green-invoice/helpers/green-invoice.helper.js';
import { SortCodesProvider } from '../../sort-codes/providers/sort-codes.provider.js';
let ShaamImportProvider = class ShaamImportProvider {
db;
sortCodesProvider;
businessProvider;
financialEntitiesProvider;
constructor(db, sortCodesProvider, businessProvider, financialEntitiesProvider) {
this.db = db;
this.sortCodesProvider = sortCodesProvider;
this.businessProvider = businessProvider;
this.financialEntitiesProvider = financialEntitiesProvider;
}
async importShaamFile(ownerId, bkmvdataContent, iniContent) {
const parseResult = parseUniformFormatFiles(iniContent ?? '', bkmvdataContent, {
validationMode: 'strict',
});
if (parseResult.summary.errors.some(e => e.severity === 'error')) {
const messages = parseResult.summary.errors
.filter(e => e.severity === 'error')
.map(e => `[${e.recordType}] ${e.field}: ${e.message}`)
.join('; ');
throw new GraphQLError(`SHAAM file validation failed: ${messages}`, {
extensions: { code: 'BAD_USER_INPUT' },
});
}
const accounts = parseResult.data.accounts;
// Collect unique sort codes by key
const sortCodeMap = new Map();
for (const account of accounts) {
const key = account.sortCode.key ? parseInt(account.sortCode.key, 10) : NaN;
if (!Number.isNaN(key) && !sortCodeMap.has(key)) {
sortCodeMap.set(key, account.sortCode.name ?? undefined);
}
}
return this.db.transaction(async (client) => {
// Override RLS context to the target owner so inserts pass the tenant_isolation policy
await client.query(`SELECT set_config('app.current_business_id', $1, true)`, [ownerId]);
// Insert sort codes that don't exist yet
const existingSortCodes = await this.sortCodesProvider.getSortCodesByOwnerIdLoader.load(ownerId);
const existingKeys = new Set(existingSortCodes.map(sc => sc.key));
const newSortCodes = [...sortCodeMap]
.filter(([key]) => !existingKeys.has(key))
.map(([key, name]) => ({ key, name: name ?? null, defaultIrsCode: null, ownerId }));
if (newSortCodes.length > 0) {
await this.sortCodesProvider.addSortCodes({ sortCodes: newSortCodes }, client);
}
const insertedSortCodesCount = newSortCodes.length;
// Insert a business entity for each account
let insertedBusinessesCount = 0;
for (const account of accounts) {
const addressStreet = account.address?.street
? [account.address.street, account.address.houseNumber].filter(Boolean).join(' ')
: undefined;
const financialEntity = {
ownerId,
name: account.name ?? account.id,
sortCode: account.sortCode?.key ? parseInt(account.sortCode.key, 10) : null,
type: 'business',
irsCode: account.accountingClassificationCode
? parseInt(account.accountingClassificationCode, 10)
: null,
isActive: true,
};
try {
const [{ id: financialEntityId } = {}] = await this.financialEntitiesProvider.insertFinancialEntity(financialEntity, client);
if (!financialEntityId) {
throw new GraphQLError(`Failed to insert financial entity for account "${account.name ?? account.id}"`);
}
// if account.name includes Hebrew characters, use it as the hebrewName, otherwise leave hebrewName null
const hebrewName = /[\u0590-\u05FF]/.test(account.name ?? '') ? account.name : undefined;
let country = CountryCode.Israel;
if (account.countryCode) {
try {
country = greenInvoiceCountryToCountryCode(account.countryCode);
}
catch {
console.warn(`Unknown country code "${account.countryCode}" for account "${account.name ?? account.id}", skipping country mapping`);
}
}
const business = {
id: financialEntityId,
ownerId,
address: addressStreet,
city: account.address?.city ?? undefined,
zipCode: account.address?.zip ?? undefined,
email: null,
exemptDealer: false,
governmentId: account.vatId ?? undefined,
hebrewName,
phoneNumber: null,
website: null,
optionalVat: false,
isReceiptEnough: false,
isDocumentsOptional: false,
country,
suggestions: null,
pcn874RecordTypeOverride: null,
};
await this.businessProvider.insertBusiness(business, client);
insertedBusinessesCount++;
}
catch (e) {
console.error(`Error ensuring business for entity ${financialEntity.name}`, e);
throw new GraphQLError(`Error ensuring business for account "${financialEntity.name}": ${e?.message ?? 'Unknown error'}`);
}
}
return { insertedSortCodesCount, insertedBusinessesCount };
});
}
};
ShaamImportProvider = __decorate([
Injectable({ scope: Scope.Operation }),
__metadata("design:paramtypes", [TenantAwareDBClient,
SortCodesProvider,
BusinessesProvider,
FinancialEntitiesProvider])
], ShaamImportProvider);
export { ShaamImportProvider };
//# sourceMappingURL=shaam-import.provider.js.map