2022-04-24 12:18:44 +05:30
|
|
|
import { Fyo } from 'fyo';
|
2022-04-20 16:11:27 +05:30
|
|
|
import { ConfigFile, DocValueMap } from 'fyo/core/types';
|
2022-04-24 12:18:44 +05:30
|
|
|
import { Doc } from 'fyo/model/doc';
|
2022-04-22 16:32:03 +05:30
|
|
|
import { createNumberSeries } from 'fyo/model/naming';
|
2022-04-20 16:11:27 +05:30
|
|
|
import { getId } from 'fyo/telemetry/helpers';
|
2022-04-22 16:32:03 +05:30
|
|
|
import {
|
|
|
|
DEFAULT_CURRENCY,
|
|
|
|
DEFAULT_LOCALE,
|
|
|
|
DEFAULT_SERIES_START,
|
|
|
|
} from 'fyo/utils/consts';
|
2022-04-20 16:11:27 +05:30
|
|
|
import { AccountingSettings } from 'models/baseModels/AccountingSettings/AccountingSettings';
|
2022-04-24 12:18:44 +05:30
|
|
|
import { initializeInstance } from 'src/initFyo';
|
2022-04-20 16:11:27 +05:30
|
|
|
import { createRegionalRecords } from 'src/regional';
|
2022-04-23 14:53:44 +05:30
|
|
|
import { getCountryCodeFromCountry, getCountryInfo } from 'utils/misc';
|
|
|
|
import { CountryInfo } from 'utils/types';
|
2022-04-24 12:18:44 +05:30
|
|
|
import { CreateCOA } from './createCOA';
|
2022-04-23 14:53:44 +05:30
|
|
|
import { SetupWizardOptions } from './types';
|
2022-04-20 16:11:27 +05:30
|
|
|
|
|
|
|
export default async function setupInstance(
|
2022-04-23 14:53:44 +05:30
|
|
|
dbPath: string,
|
2022-04-24 12:18:44 +05:30
|
|
|
setupWizardOptions: SetupWizardOptions,
|
|
|
|
fyo: Fyo
|
2022-04-20 16:11:27 +05:30
|
|
|
) {
|
|
|
|
const { companyName, country, bankName, chartOfAccounts } =
|
|
|
|
setupWizardOptions;
|
2022-04-23 14:53:44 +05:30
|
|
|
|
2022-04-24 12:18:44 +05:30
|
|
|
await initializeDatabase(dbPath, country, fyo);
|
|
|
|
await updateSystemSettings(setupWizardOptions, fyo);
|
|
|
|
await updateAccountingSettings(setupWizardOptions, fyo);
|
|
|
|
await updatePrintSettings(setupWizardOptions, fyo);
|
2022-04-20 16:11:27 +05:30
|
|
|
|
2022-04-24 12:18:44 +05:30
|
|
|
await createCurrencyRecords(fyo);
|
|
|
|
await createAccountRecords(bankName, country, chartOfAccounts, fyo);
|
|
|
|
await createRegionalRecords(country, fyo);
|
|
|
|
await createDefaultNumberSeries(fyo);
|
2022-04-20 16:11:27 +05:30
|
|
|
|
2022-04-24 12:18:44 +05:30
|
|
|
await completeSetup(companyName, fyo);
|
2022-04-20 16:11:27 +05:30
|
|
|
}
|
|
|
|
|
2022-04-24 12:18:44 +05:30
|
|
|
async function initializeDatabase(dbPath: string, country: string, fyo: Fyo) {
|
2022-04-23 14:53:44 +05:30
|
|
|
const countryCode = getCountryCodeFromCountry(country);
|
2022-04-24 12:18:44 +05:30
|
|
|
await initializeInstance(dbPath, true, countryCode, fyo);
|
2022-04-23 14:53:44 +05:30
|
|
|
}
|
|
|
|
|
2022-04-24 12:18:44 +05:30
|
|
|
async function updateAccountingSettings(
|
|
|
|
{
|
|
|
|
companyName,
|
|
|
|
country,
|
|
|
|
fullname,
|
|
|
|
email,
|
|
|
|
bankName,
|
|
|
|
fiscalYearStart,
|
|
|
|
fiscalYearEnd,
|
|
|
|
}: SetupWizardOptions,
|
|
|
|
fyo: Fyo
|
|
|
|
) {
|
2022-04-20 16:11:27 +05:30
|
|
|
const accountingSettings = (await fyo.doc.getSingle(
|
|
|
|
'AccountingSettings'
|
|
|
|
)) as AccountingSettings;
|
2022-04-24 12:18:44 +05:30
|
|
|
await accountingSettings.setAndSync({
|
2022-04-20 16:11:27 +05:30
|
|
|
companyName,
|
|
|
|
country,
|
2022-04-23 14:53:44 +05:30
|
|
|
fullname,
|
2022-04-20 16:11:27 +05:30
|
|
|
email,
|
|
|
|
bankName,
|
|
|
|
fiscalYearStart,
|
|
|
|
fiscalYearEnd,
|
|
|
|
});
|
|
|
|
return accountingSettings;
|
|
|
|
}
|
|
|
|
|
2022-04-24 12:18:44 +05:30
|
|
|
async function updatePrintSettings(
|
|
|
|
{ companyLogo, companyName, email }: SetupWizardOptions,
|
|
|
|
fyo: Fyo
|
|
|
|
) {
|
2022-04-20 16:11:27 +05:30
|
|
|
const printSettings = await fyo.doc.getSingle('PrintSettings');
|
2022-04-24 12:18:44 +05:30
|
|
|
await printSettings.setAndSync({
|
2022-04-20 16:11:27 +05:30
|
|
|
logo: companyLogo,
|
|
|
|
companyName,
|
|
|
|
email,
|
|
|
|
displayLogo: companyLogo ? true : false,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-04-24 12:18:44 +05:30
|
|
|
async function updateSystemSettings(
|
|
|
|
{ country, currency: companyCurrency }: SetupWizardOptions,
|
|
|
|
fyo: Fyo
|
|
|
|
) {
|
2022-04-23 14:53:44 +05:30
|
|
|
const countryInfo = getCountryInfo();
|
|
|
|
const countryOptions = countryInfo[country] as CountryInfo;
|
2022-04-20 16:11:27 +05:30
|
|
|
const currency =
|
|
|
|
companyCurrency ?? countryOptions.currency ?? DEFAULT_CURRENCY;
|
|
|
|
const locale = countryOptions.locale ?? DEFAULT_LOCALE;
|
|
|
|
const systemSettings = await fyo.doc.getSingle('SystemSettings');
|
2022-04-24 12:18:44 +05:30
|
|
|
systemSettings.setAndSync({
|
2022-04-20 16:11:27 +05:30
|
|
|
locale,
|
|
|
|
currency,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-04-24 12:18:44 +05:30
|
|
|
async function createCurrencyRecords(fyo: Fyo) {
|
2022-04-20 16:11:27 +05:30
|
|
|
const promises: Promise<Doc | undefined>[] = [];
|
|
|
|
const queue: string[] = [];
|
2022-04-23 14:53:44 +05:30
|
|
|
const countrySettings = Object.values(getCountryInfo()) as CountryInfo[];
|
2022-04-20 16:11:27 +05:30
|
|
|
|
|
|
|
for (const country of countrySettings) {
|
|
|
|
const {
|
|
|
|
currency,
|
|
|
|
currency_fraction,
|
|
|
|
currency_fraction_units,
|
|
|
|
smallest_currency_fraction_value,
|
|
|
|
currency_symbol,
|
|
|
|
} = country;
|
|
|
|
|
|
|
|
if (!currency || queue.includes(currency)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const docObject = {
|
|
|
|
name: currency,
|
|
|
|
fraction: currency_fraction ?? '',
|
|
|
|
fractionUnits: currency_fraction_units ?? 100,
|
|
|
|
smallestValue: smallest_currency_fraction_value ?? 0.01,
|
|
|
|
symbol: currency_symbol ?? '',
|
|
|
|
};
|
|
|
|
|
2022-04-24 12:18:44 +05:30
|
|
|
const doc = checkAndCreateDoc('Currency', docObject, fyo);
|
2022-04-20 16:11:27 +05:30
|
|
|
if (doc) {
|
|
|
|
promises.push(doc);
|
|
|
|
queue.push(currency);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Promise.all(promises);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function createAccountRecords(
|
|
|
|
bankName: string,
|
|
|
|
country: string,
|
2022-04-24 12:18:44 +05:30
|
|
|
chartOfAccounts: string,
|
|
|
|
fyo: Fyo
|
2022-04-20 16:11:27 +05:30
|
|
|
) {
|
2022-04-24 12:18:44 +05:30
|
|
|
const createCOA = new CreateCOA(chartOfAccounts, fyo);
|
|
|
|
await createCOA.run();
|
|
|
|
const parentAccount = await getBankAccountParentName(country, fyo);
|
2022-04-20 16:11:27 +05:30
|
|
|
const docObject = {
|
|
|
|
name: bankName,
|
|
|
|
rootType: 'Asset',
|
|
|
|
parentAccount,
|
|
|
|
accountType: 'Bank',
|
|
|
|
isGroup: false,
|
|
|
|
};
|
2022-04-24 12:18:44 +05:30
|
|
|
await checkAndCreateDoc('Account', docObject, fyo);
|
2022-04-20 16:11:27 +05:30
|
|
|
}
|
|
|
|
|
2022-04-24 12:18:44 +05:30
|
|
|
async function completeSetup(companyName: string, fyo: Fyo) {
|
|
|
|
updateInitializationConfig(companyName, fyo);
|
2022-04-20 16:11:27 +05:30
|
|
|
await fyo.singles.AccountingSettings!.set('setupComplete', true);
|
2022-04-24 12:18:44 +05:30
|
|
|
await fyo.singles.AccountingSettings!.sync();
|
2022-04-20 16:11:27 +05:30
|
|
|
}
|
|
|
|
|
2022-04-24 12:18:44 +05:30
|
|
|
function updateInitializationConfig(companyName: string, fyo: Fyo) {
|
2022-04-20 16:11:27 +05:30
|
|
|
const dbPath = fyo.db.dbPath;
|
|
|
|
const files = fyo.config.get('files', []) as ConfigFile[];
|
|
|
|
|
|
|
|
files.forEach((file) => {
|
|
|
|
if (file.dbPath === dbPath) {
|
|
|
|
file.companyName = companyName;
|
|
|
|
file.id = getId();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
fyo.config.set('files', files);
|
|
|
|
}
|
|
|
|
|
2022-04-24 12:18:44 +05:30
|
|
|
async function checkAndCreateDoc(
|
|
|
|
schemaName: string,
|
|
|
|
docObject: DocValueMap,
|
|
|
|
fyo: Fyo
|
|
|
|
) {
|
|
|
|
const canCreate = await checkIfExactRecordAbsent(schemaName, docObject, fyo);
|
2022-04-20 16:11:27 +05:30
|
|
|
if (!canCreate) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const doc = await fyo.doc.getNewDoc(schemaName, docObject);
|
2022-04-24 12:18:44 +05:30
|
|
|
return doc.sync();
|
2022-04-20 16:11:27 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
async function checkIfExactRecordAbsent(
|
|
|
|
schemaName: string,
|
2022-04-24 12:18:44 +05:30
|
|
|
docMap: DocValueMap,
|
|
|
|
fyo: Fyo
|
2022-04-20 16:11:27 +05:30
|
|
|
) {
|
|
|
|
const name = docMap.name as string;
|
|
|
|
const newDocObject = Object.assign({}, docMap);
|
|
|
|
|
|
|
|
const rows = await fyo.db.getAllRaw(schemaName, {
|
|
|
|
fields: ['*'],
|
|
|
|
filters: { name },
|
|
|
|
});
|
|
|
|
|
|
|
|
if (rows.length === 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const storedDocObject = rows[0];
|
|
|
|
const matchList = Object.keys(newDocObject).map((key) => {
|
|
|
|
const newValue = newDocObject[key];
|
|
|
|
const storedValue = storedDocObject[key];
|
|
|
|
return newValue == storedValue; // Should not be type sensitive.
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!matchList.every(Boolean)) {
|
|
|
|
await fyo.db.delete(schemaName, name);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-04-24 12:18:44 +05:30
|
|
|
async function getBankAccountParentName(country: string, fyo: Fyo) {
|
2022-04-20 16:11:27 +05:30
|
|
|
const parentBankAccount = await fyo.db.getAllRaw('Account', {
|
|
|
|
fields: ['*'],
|
|
|
|
filters: { isGroup: true, accountType: 'Bank' },
|
|
|
|
});
|
|
|
|
|
|
|
|
if (parentBankAccount.length === 0) {
|
|
|
|
// This should not happen if the fixtures are correct.
|
|
|
|
return 'Bank Accounts';
|
|
|
|
} else if (parentBankAccount.length > 1) {
|
|
|
|
switch (country) {
|
|
|
|
case 'Indonesia':
|
|
|
|
return 'Bank Rupiah - 1121.000';
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return parentBankAccount[0].name;
|
|
|
|
}
|
2022-04-22 16:32:03 +05:30
|
|
|
|
2022-04-24 12:18:44 +05:30
|
|
|
async function createDefaultNumberSeries(fyo: Fyo) {
|
2022-04-22 16:32:03 +05:30
|
|
|
await createNumberSeries('SINV-', 'SalesInvoice', DEFAULT_SERIES_START, fyo);
|
|
|
|
await createNumberSeries(
|
|
|
|
'PINV-',
|
|
|
|
'PurchaseInvoice',
|
|
|
|
DEFAULT_SERIES_START,
|
|
|
|
fyo
|
|
|
|
);
|
|
|
|
await createNumberSeries('PAY-', 'Payment', DEFAULT_SERIES_START, fyo);
|
|
|
|
await createNumberSeries('JV-', 'JournalEntry', DEFAULT_SERIES_START, fyo);
|
|
|
|
}
|