UNPKG

@accounter/server

Version:

444 lines • 15.4 kB
import { __decorate, __metadata, __param } from "tslib"; import DataLoader from 'dataloader'; import { CONTEXT, Inject, Injectable, Scope } from 'graphql-modules'; import { DBProvider } from '../../app-providers/db.provider.js'; import { BusinessTripAttendeesProvider } from '../../business-trips/providers/business-trips-attendees.provider.js'; import { DividendsProvider } from '../../dividends/providers/dividends.provider.js'; import { BalanceCancellationProvider } from '../../ledger/providers/balance-cancellation.provider.js'; import { UnbalancedBusinessesProvider } from '../../ledger/providers/unbalanced-businesses.provider.js'; import { EmployeesProvider } from '../../salaries/providers/employees.provider.js'; import { FundsProvider } from '../../salaries/providers/funds.provider.js'; import { sql } from '@pgtyped/runtime'; import { getCacheInstance } from '../../../shared/helpers/index.js'; import { BusinessesGreenInvoiceMatcherProvider } from './businesses-green-invoice-match.provider.js'; import { TaxCategoriesProvider } from './tax-categories.provider.js'; const getBusinessesByIds = sql ` SELECT * FROM accounter_schema.businesses b INNER JOIN accounter_schema.financial_entities fe USING (id) WHERE b.id IN $$ids;`; const getAllBusinesses = sql ` SELECT * FROM accounter_schema.businesses b INNER JOIN accounter_schema.financial_entities fe USING (id);`; const updateBusiness = sql ` UPDATE accounter_schema.businesses SET vat_number = COALESCE( $vatNumber, vat_number ), tax_siduri_number_2021 = COALESCE( $taxSiduriNumber2021, tax_siduri_number_2021 ), password = COALESCE( $password, password ), username_vat_website = COALESCE( $usernameVatWebsite, username_vat_website ), website_login_screenshot = COALESCE( $websiteLoginScreenshot, website_login_screenshot ), nikuim = COALESCE( $nikuim, nikuim ), pinkas_social_security_2021 = COALESCE( $pinkasSocialSecurity2021, pinkas_social_security_2021 ), hebrew_name = COALESCE( $hebrewName, hebrew_name ), tax_pinkas_number_2020 = COALESCE( $taxPinkasNumber2020, tax_pinkas_number_2020 ), address = COALESCE( $address, address ), address_hebrew = COALESCE( $addressHebrew, address_hebrew ), wizcloud_token = COALESCE( $wizcloudToken, wizcloud_token ), wizcloud_company_id = COALESCE( $wizcloudCompany_id, wizcloud_company_id ), advance_tax_rate = COALESCE( $advanceTaxRate, advance_tax_rate ), email = COALESCE( $email, email ), website = COALESCE( $website, website ), phone_number = COALESCE( $phoneNumber, phone_number ), bank_account_bank_number = COALESCE( $bankAccountBankNumber, bank_account_bank_number ), bank_account_branch_number = COALESCE( $bankAccountBranchNumber, bank_account_branch_number ), bank_account_account_number = COALESCE( $bankAccountAccountNumber, bank_account_account_number ), "bank_account_IBAN" = COALESCE( $bankAccountIBAN, "bank_account_IBAN" ), tax_nikuim_pinkas_number = COALESCE( $taxNikuimPinkasNumber, tax_nikuim_pinkas_number ), bank_account_swift = COALESCE( $bankAccountSwift, bank_account_swift ), vat_report_cadence = COALESCE( $vatReportCadence, vat_report_cadence ), contract = COALESCE( $contract, contract ), country = COALESCE( $country, country ), pinkas_social_security_2022 = COALESCE( $pinkasSocialSecurity2022, pinkas_social_security_2022 ), tax_siduri_number_2022 = COALESCE( $taxSiduriNumber2022, tax_siduri_number_2022 ), registration_date = COALESCE( $registrationDate, registration_date ), no_invoices_required = COALESCE( $noInvoicesRequired, no_invoices_required ), suggestion_data = COALESCE( $suggestionData, suggestion_data ), can_settle_with_receipt = COALESCE( $canSettleWithReceipt, can_settle_with_receipt ), exempt_dealer = COALESCE( $exemptDealer, exempt_dealer ), optional_vat = COALESCE( $optionalVat, optional_vat ) WHERE id = $businessId RETURNING *; `; const insertBusinesses = sql ` INSERT INTO accounter_schema.businesses (id, hebrew_name, address, email, website, phone_number, vat_number, exempt_dealer, suggestion_data, optional_vat, country) VALUES $$businesses(id, hebrewName, address, email, website, phoneNumber, governmentId, exemptDealer, suggestions, optionalVat, country) RETURNING *;`; const deleteBusiness = sql ` DELETE FROM accounter_schema.businesses WHERE id = $businessId RETURNING id; `; 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 ), businesses_green_invoice_match as ( UPDATE accounter_schema.businesses_green_invoice_match SET business_id = $targetBusinessId WHERE business_id = $businessIdToReplace RETURNING green_invoice_id ) UPDATE accounter_schema.transactions SET business_id = $targetBusinessId WHERE business_id = $businessIdToReplace RETURNING id; `; let BusinessesProvider = class BusinessesProvider { context; dbProvider; taxCategoryProvider; businessesGreenInvoiceMatcherProvider; employeesProvider; fundsProvider; dividendsProvider; businessTripAttendeesProvider; balanceCancellationProvider; unbalancedBusinessesProvider; cache = getCacheInstance({ stdTTL: 60 * 5, }); constructor(context, dbProvider, taxCategoryProvider, businessesGreenInvoiceMatcherProvider, employeesProvider, fundsProvider, dividendsProvider, businessTripAttendeesProvider, balanceCancellationProvider, unbalancedBusinessesProvider) { this.context = context; this.dbProvider = dbProvider; this.taxCategoryProvider = taxCategoryProvider; this.businessesGreenInvoiceMatcherProvider = businessesGreenInvoiceMatcherProvider; this.employeesProvider = employeesProvider; this.fundsProvider = fundsProvider; this.dividendsProvider = dividendsProvider; this.businessTripAttendeesProvider = businessTripAttendeesProvider; this.balanceCancellationProvider = balanceCancellationProvider; this.unbalancedBusinessesProvider = unbalancedBusinessesProvider; } async batchBusinessesByIds(ids) { const uniqueIds = [...new Set(ids)]; const businesses = await getBusinessesByIds.run({ ids: uniqueIds, }, this.dbProvider); return ids.map(id => businesses.find(fe => fe.id === id)); } getBusinessByIdLoader = new DataLoader((ids) => this.batchBusinessesByIds(ids), { cacheKeyFn: id => `business-${id}`, cacheMap: this.cache, }); getAllBusinesses() { const data = this.cache.get('all-businesses'); if (data) { return Promise.resolve(data); } return getAllBusinesses.run(undefined, this.dbProvider); } async updateBusiness(params) { if (params.businessId) await this.invalidateBusinessById(params.businessId); return updateBusiness.run(params, this.dbProvider); } insertBusiness(business) { this.cache.delete('all-businesses'); return insertBusinesses.run({ businesses: [business] }, this.dbProvider); } async batchInsertBusinesses(newBusinesses) { const businesses = await insertBusinesses.run({ businesses: newBusinesses, }, this.dbProvider); return newBusinesses.map(nb => businesses.find(b => b.id === nb.id) ?? null); } insertBusinessesLoader = new DataLoader((businesses) => this.batchInsertBusinesses(businesses), { cache: false, }); insertBusinesses(params) { this.cache.delete('all-businesses'); return insertBusinesses.run(params, this.dbProvider); } async invalidateBusinessById(businessId) { this.cache.delete('all-businesses'); this.cache.delete(`business-${businessId}`); } async deleteBusinessById(businessId) { this.invalidateBusinessById(businessId); // remove employee const employeePromise = this.employeesProvider.getEmployeesByIdLoader .load(businessId) .then(employee => { if (employee) throw new Error('Cannot delete business as it represent an employee'); }); // remove pension funds const fundPromise = this.fundsProvider.getAllFunds().then(funds => { const fund = funds.find(f => f.id === businessId); if (fund) throw new Error('Cannot delete business as it represent a pension/training fund'); }); // remove business trips attendees const tripsPromise = this.businessTripAttendeesProvider .getBusinessTripsByAttendeeId(businessId) .then(trips => { if (trips.length) throw new Error('Cannot delete business as it represent business trip attendee'); }); // remove from dividends const dividendsPromise = this.dividendsProvider.getDividendsByBusinessIdLoader .load(businessId) .then(dividends => { if (dividends.length) throw new Error('Cannot delete business as it represent dividends receiver'); }); // some validations before deleting the business await Promise.all([employeePromise, tripsPromise, fundPromise, dividendsPromise]); // remove from charge unbalanced ledger businesses const deleteUnbalancedChargesBusinesses = this.unbalancedBusinessesProvider.deleteChargeUnbalancedBusinessesByBusinessId(businessId); // remove from charge balance cancellation const deleteBalanceCancellation = this.balanceCancellationProvider.deleteBalanceCancellationByBusinessId(businessId); // remove from business green invoice match const deleteGreenInvoiceMatch = this.businessesGreenInvoiceMatcherProvider.deleteBusinessMatch(businessId); // TODO: remove when corporate: corporate-tax-variables // TODO: remove when owner: financial entities, charges, business-tax-category, ledger // TODO: should remove transactions, documents? // remove business-tax-category matches const deleteMatchingTaxCategory = this.taxCategoryProvider.deleteBusinessTaxCategory({ businessId, ownerId: this.context.currentUser.userId, }); await Promise.all([ deleteUnbalancedChargesBusinesses, deleteBalanceCancellation, deleteGreenInvoiceMatch, deleteMatchingTaxCategory, ]); // delete businesses deleteBusiness.run({ businessId }, this.dbProvider); } async replaceBusiness(targetBusinessId, businessIdToReplace, deleteBusiness = false) { 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.dbProvider); // TODO: convert when owner: financial entities, charges, business-tax-category, ledger // TODO: should convert business tax category matches? // delete businesses if (deleteBusiness) { await this.deleteBusinessById(businessIdToReplace); } } clearCache() { this.cache.clear(); } }; BusinessesProvider = __decorate([ Injectable({ scope: Scope.Operation, global: true, }), __param(0, Inject(CONTEXT)), __metadata("design:paramtypes", [Object, DBProvider, TaxCategoriesProvider, BusinessesGreenInvoiceMatcherProvider, EmployeesProvider, FundsProvider, DividendsProvider, BusinessTripAttendeesProvider, BalanceCancellationProvider, UnbalancedBusinessesProvider]) ], BusinessesProvider); export { BusinessesProvider }; //# sourceMappingURL=businesses.provider.js.map