UNPKG

@accounter/server

Version:
308 lines • 11.1 kB
import { __decorate, __metadata } from "tslib"; import DataLoader from 'dataloader'; import { Injectable, Scope } from 'graphql-modules'; import { sql } from '@pgtyped/runtime'; import { reassureOwnerIdExists } from '../../../shared/helpers/index.js'; import { AdminContextProvider } from '../../admin-context/providers/admin-context.provider.js'; import { TenantAwareDBClient } from '../../app-providers/tenant-db-client.js'; const getBusinessesByIds = sql ` SELECT fe.*, b.vat_number, b.hebrew_name, b.address, b.address_hebrew, b.email, b.website, b.phone_number, b.country, b.no_invoices_required, b.suggestion_data, b.can_settle_with_receipt, b.exempt_dealer, b.optional_vat, b.pcn874_record_type_override, b.city, b.zip_code FROM accounter_schema.businesses b INNER JOIN accounter_schema.financial_entities fe USING (id) WHERE b.id IN $$ids;`; const getAllBusinesses = sql ` SELECT fe.*, b.vat_number, b.hebrew_name, b.address, b.address_hebrew, b.email, b.website, b.phone_number, b.country, b.no_invoices_required, b.suggestion_data, b.can_settle_with_receipt, b.exempt_dealer, b.optional_vat, b.pcn874_record_type_override, b.city, b.zip_code FROM accounter_schema.businesses b INNER JOIN accounter_schema.financial_entities fe USING (id);`; const getBusinessByEmail = sql ` SELECT fe.*, b.vat_number, b.hebrew_name, b.address, b.address_hebrew, b.email, b.website, b.phone_number, b.country, b.no_invoices_required, b.suggestion_data, b.can_settle_with_receipt, b.exempt_dealer, b.optional_vat, b.pcn874_record_type_override, b.city, b.zip_code FROM accounter_schema.businesses b INNER JOIN accounter_schema.financial_entities fe USING (id) WHERE suggestion_data->'emails' ? $email::text LIMIT 1;`; const updateBusiness = sql ` UPDATE accounter_schema.businesses SET vat_number = COALESCE( $vatNumber, vat_number ), hebrew_name = COALESCE( $hebrewName, hebrew_name ), address = COALESCE( $address, address ), city = COALESCE( $city, city ), zip_code = COALESCE( $zipCode, zip_code ), address_hebrew = COALESCE( $addressHebrew, address_hebrew ), email = COALESCE( $email, email ), website = COALESCE( $website, website ), phone_number = COALESCE( $phoneNumber, phone_number ), country = COALESCE( $country, country ), no_invoices_required = COALESCE( $isDocumentsOptional, no_invoices_required ), suggestion_data = COALESCE( $suggestionData, suggestion_data ), can_settle_with_receipt = COALESCE( $isReceiptEnough, can_settle_with_receipt ), exempt_dealer = COALESCE( $exemptDealer, exempt_dealer ), optional_vat = COALESCE( $optionalVat, optional_vat ), pcn874_record_type_override = COALESCE( $pcn874RecordTypeOverride, pcn874_record_type_override ) WHERE id = $businessId RETURNING *; `; const insertBusinesses = sql ` INSERT INTO accounter_schema.businesses (id, hebrew_name, address, city, zip_code, email, website, phone_number, vat_number, exempt_dealer, suggestion_data, optional_vat, country, pcn874_record_type_override, can_settle_with_receipt, no_invoices_required, owner_id) VALUES $$businesses(id, hebrewName, address, city, zipCode, email, website, phoneNumber, governmentId, exemptDealer, suggestions, optionalVat, country, pcn874RecordTypeOverride, isReceiptEnough, isDocumentsOptional, ownerId) RETURNING *;`; const replaceBusinesses = sql ` WITH ledger_debit1 AS ( UPDATE accounter_schema.ledger_records SET debit_entity1 = $targetBusinessId WHERE debit_entity1 = $businessIdToReplace RETURNING id ), ledger_debit2 AS ( UPDATE accounter_schema.ledger_records SET debit_entity2 = $targetBusinessId WHERE debit_entity2 = $businessIdToReplace RETURNING id ), ledger_credit1 AS ( UPDATE accounter_schema.ledger_records SET credit_entity1 = $targetBusinessId WHERE credit_entity1 = $businessIdToReplace RETURNING id ), ledger_credit2 AS ( UPDATE accounter_schema.ledger_records SET credit_entity2 = $targetBusinessId WHERE credit_entity2 = $businessIdToReplace RETURNING id ), documents_debtor AS ( UPDATE accounter_schema.documents SET debtor_id = $targetBusinessId WHERE debtor_id = $businessIdToReplace RETURNING id ), documents_creditor AS ( UPDATE accounter_schema.documents SET creditor_id = $targetBusinessId WHERE creditor_id = $businessIdToReplace RETURNING id ), employees AS ( UPDATE accounter_schema.employees SET business_id = $targetBusinessId WHERE business_id = $businessIdToReplace RETURNING business_id ), funds AS ( UPDATE accounter_schema.pension_funds SET id = $targetBusinessId WHERE id = $businessIdToReplace RETURNING id ), business_trips_attendees AS ( UPDATE accounter_schema.business_trips_attendees SET attendee_business_id = $targetBusinessId WHERE attendee_business_id = $businessIdToReplace RETURNING business_trip_id ), business_trips_employee_payments AS ( UPDATE accounter_schema.business_trips_employee_payments SET employee_business_id = $targetBusinessId WHERE employee_business_id = $businessIdToReplace RETURNING id ), charge_unbalanced_ledger_businesses AS ( UPDATE accounter_schema.charge_unbalanced_ledger_businesses SET business_id = $targetBusinessId WHERE business_id = $businessIdToReplace RETURNING charge_id ), charge_balance_cancellation AS ( UPDATE accounter_schema.charge_balance_cancellation SET business_id = $targetBusinessId WHERE business_id = $businessIdToReplace RETURNING charge_id ), dividends AS ( UPDATE accounter_schema.dividends SET business_id = $targetBusinessId WHERE business_id = $businessIdToReplace RETURNING id ), corporate_tax_variables as ( UPDATE accounter_schema.corporate_tax_variables SET corporate_id = $targetBusinessId WHERE corporate_id = $businessIdToReplace RETURNING date ), clients AS ( UPDATE accounter_schema.clients SET business_id = $targetBusinessId WHERE business_id = $businessIdToReplace RETURNING (integrations->>'greenInvoiceId')::uuid ) UPDATE accounter_schema.transactions SET business_id = $targetBusinessId WHERE business_id = $businessIdToReplace RETURNING id; `; let BusinessesProvider = class BusinessesProvider { db; adminContextProvider; constructor(db, adminContextProvider) { this.db = db; this.adminContextProvider = adminContextProvider; } async batchBusinessesByIds(ids) { const uniqueIds = [...new Set(ids)]; const businesses = await getBusinessesByIds.run({ ids: uniqueIds, }, this.db); return ids.map(id => businesses.find(fe => fe.id === id)); } getBusinessByIdLoader = new DataLoader((ids) => this.batchBusinessesByIds(ids)); allBusinessesCache = null; getAllBusinesses() { if (this.allBusinessesCache) { return this.allBusinessesCache; } this.allBusinessesCache = getAllBusinesses.run(undefined, this.db).then(businesses => { businesses.map(business => { this.getBusinessByIdLoader.prime(business.id, business); }); return businesses; }); return this.allBusinessesCache; } getBusinessByEmail(email) { return getBusinessByEmail.run({ email }, this.db).then(res => { if (res?.length) { res.map(business => { this.getBusinessByIdLoader.prime(business.id, business); }); return res[0]; } return null; }); } async updateBusiness(params) { if (params.businessId) await this.invalidateBusinessById(params.businessId); return updateBusiness.run(params, this.db); } async batchInsertBusinesses(newBusinesses) { await Promise.all(newBusinesses.map(async (nb) => { if (nb.id) { await this.invalidateBusinessById(nb.id); } })); const { ownerId } = await this.adminContextProvider.getVerifiedAdminContext(); const businessesWithOwnerId = newBusinesses.map(business => reassureOwnerIdExists(business, ownerId)); const businesses = await insertBusinesses.run({ businesses: businessesWithOwnerId, }, this.db); return newBusinesses.map(nb => businesses.find(b => b.id === nb.id) ?? null); } insertBusinessLoader = new DataLoader((businesses) => this.batchInsertBusinesses(businesses), { cache: false, }); async insertBusiness(newBusiness, client) { if (newBusiness.id) { await this.invalidateBusinessById(newBusiness.id); } const ownerId = newBusiness.ownerId ?? (await this.adminContextProvider.getVerifiedAdminContext()).ownerId; const businessWithOwnerId = reassureOwnerIdExists(newBusiness, ownerId); const businesses = await insertBusinesses.run({ businesses: [businessWithOwnerId], }, client ?? this.db); return businesses[0]; } async replaceBusiness(targetBusinessId, businessIdToReplace) { const [businessToReplace, business] = await Promise.all([ this.getBusinessByIdLoader.load(businessIdToReplace), this.getBusinessByIdLoader.load(targetBusinessId), ]); if (!businessToReplace) { throw new Error(`Business with id ${businessIdToReplace} not found`); } if (!business) { throw new Error(`Business with id ${targetBusinessId} not found`); } this.invalidateBusinessById(businessIdToReplace); this.invalidateBusinessById(targetBusinessId); // convert transactions, ledger, documents, employees, funds, business trips attendees, business trips employee payments, charge unbalanced ledger businesses, charge balance cancellation, dividends, corporate tax variables, businesses green invoice match await replaceBusinesses.run({ targetBusinessId, businessIdToReplace, }, this.db); // TODO: convert when owner: financial entities, charges, business-tax-category, ledger // TODO: should convert business tax category matches? } async invalidateBusinessById(businessId) { this.getBusinessByIdLoader.clear(businessId); this.allBusinessesCache = null; } clearCache() { this.getBusinessByIdLoader.clearAll(); this.allBusinessesCache = null; } }; BusinessesProvider = __decorate([ Injectable({ scope: Scope.Operation, global: true, }), __metadata("design:paramtypes", [TenantAwareDBClient, AdminContextProvider]) ], BusinessesProvider); export { BusinessesProvider }; //# sourceMappingURL=businesses.provider.js.map