2
0
mirror of https://github.com/frappe/books.git synced 2024-12-22 19:09:01 +00:00

incr: simplify doc a bit

- allow nulls in converter else not not null'll fail
This commit is contained in:
18alantom 2022-04-24 12:18:44 +05:30
parent 76c61a5c29
commit 9877bf4fd3
61 changed files with 371 additions and 315 deletions

View File

@ -1,5 +1,5 @@
import { Fyo } from 'fyo';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { isPesa } from 'fyo/utils';
import { ValueError } from 'fyo/utils/errors';
import { DateTime } from 'luxon';
@ -267,14 +267,18 @@ function toRawFloat(value: DocValue, field: Field): number {
throwError(value, field, 'raw');
}
function toRawDate(value: DocValue, field: Field): string {
function toRawDate(value: DocValue, field: Field): string | null {
const dateTime = toRawDateTime(value, field);
if (dateTime === null) {
return null;
}
return dateTime.split('T')[0];
}
function toRawDateTime(value: DocValue, field: Field): string {
if (getIsNullOrUndef(value)) {
return '';
function toRawDateTime(value: DocValue, field: Field): string | null {
if (value === null) {
return null;
}
if (typeof value === 'string') {
@ -304,9 +308,9 @@ function toRawCheck(value: DocValue, field: Field): number {
throwError(value, field, 'raw');
}
function toRawString(value: DocValue, field: Field): string {
if (getIsNullOrUndef(value)) {
return '';
function toRawString(value: DocValue, field: Field): string | null {
if (value === null) {
return null;
}
if (typeof value === 'string') {

View File

@ -1,4 +1,4 @@
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { DocMap, ModelMap, SinglesMap } from 'fyo/model/types';
import { coreModels } from 'fyo/models';
import Observable from 'fyo/utils/observable';
@ -143,20 +143,10 @@ export class DocHandler {
return newDoc;
}
getEmptyDoc(schemaName: string, cacheDoc: boolean = true): Doc {
const doc = this.getNewDoc(schemaName);
doc.name = getRandomString();
if (cacheDoc) {
this.addToCache(doc);
}
return doc;
}
getNewDoc(
schemaName: string,
data: DocValueMap = {},
cacheDoc: boolean = true,
schema?: Schema,
Model?: typeof Doc
): Doc {
@ -166,12 +156,17 @@ export class DocHandler {
Model ??= this.models[schemaName];
schema ??= this.fyo.schemaMap[schemaName];
if (schema === undefined) {
throw new Error(`Schema not found for ${schemaName}`);
}
const doc = new Model!(schema, data, this.fyo);
doc.setDefaults();
doc.name ??= getRandomString();
if (cacheDoc) {
this.addToCache(doc);
}
return doc;
}
@ -184,12 +179,12 @@ export class DocHandler {
const docExists = await this.fyo.db.exists(schemaName, name);
if (!docExists) {
const doc = this.getNewDoc(schemaName, data);
await doc.insert;
await doc.sync();
return;
}
const doc = await this.getDoc(schemaName, name);
await doc.setMultiple(data);
await doc.update();
await doc.sync();
}
}

View File

@ -1,4 +1,4 @@
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import Money from 'pesa/dist/types/src/money';
import { RawValue } from 'schemas/types';
import { AuthDemuxBase } from 'utils/auth/types';

View File

@ -1,14 +1,14 @@
import config from 'utils/config';
export class Config {
#isElectron: boolean;
#useElectronConfig: boolean;
fallback: Map<string, unknown> = new Map();
constructor(isElectron: boolean) {
this.#isElectron = isElectron;
this.#useElectronConfig = isElectron;
}
get store(): Record<string, unknown> {
if (this.#isElectron) {
if (this.#useElectronConfig) {
return config.store;
} else {
const store: Record<string, unknown> = {};
@ -22,7 +22,7 @@ export class Config {
}
get(key: string, defaultValue?: unknown): unknown {
if (this.#isElectron) {
if (this.#useElectronConfig) {
return config.get(key, defaultValue);
} else {
return this.fallback.get(key) ?? defaultValue;
@ -30,7 +30,7 @@ export class Config {
}
set(key: string, value: unknown) {
if (this.#isElectron) {
if (this.#useElectronConfig) {
config.set(key, value);
} else {
this.fallback.set(key, value);
@ -38,7 +38,7 @@ export class Config {
}
delete(key: string) {
if (this.#isElectron) {
if (this.#useElectronConfig) {
config.delete(key);
} else {
this.fallback.delete(key);
@ -46,7 +46,7 @@ export class Config {
}
clear() {
if (this.#isElectron) {
if (this.#useElectronConfig) {
config.clear();
} else {
this.fallback.clear();

View File

@ -6,7 +6,7 @@ import { DatabaseHandler } from './core/dbHandler';
import { DocHandler } from './core/docHandler';
import { DocValue, FyoConfig } from './core/types';
import { Config } from './demux/config';
import Doc from './model/doc';
import { Doc } from './model/doc';
import { ModelMap } from './model/types';
import { TelemetryManager } from './telemetry/telemetry';
import {
@ -60,7 +60,7 @@ export class Fyo {
});
this.telemetry = new TelemetryManager(this);
this.config = new Config(this.isElectron);
this.config = new Config(this.isElectron && !this.isTest);
}
get initialized() {

View File

@ -45,7 +45,7 @@ import {
} from './types';
import { validateSelect } from './validationFunction';
export default class Doc extends Observable<DocValue | Doc[]> {
export class Doc extends Observable<DocValue | Doc[]> {
name?: string;
schema: Readonly<Schema>;
fyo: Fyo;
@ -72,12 +72,14 @@ export default class Doc extends Observable<DocValue | Doc[]> {
super();
this.fyo = fyo;
this.schema = schema;
this._setInitialValues(data);
this.fieldMap = getMapFromList(schema.fields, 'fieldname');
if (this.schema.isSingle) {
this.name = this.schemaName;
}
this._setDefaults();
this._setValuesWithoutChecks(data);
}
get schemaName(): string {
@ -103,23 +105,17 @@ export default class Doc extends Observable<DocValue | Doc[]> {
return fieldnames.map((f) => this.fieldMap[f]);
}
_setInitialValues(data: DocValueMap) {
for (const fieldname in data) {
const value = data[fieldname];
_setValuesWithoutChecks(data: DocValueMap) {
for (const field of this.schema.fields) {
const fieldname = field.fieldname;
const value = data[field.fieldname];
if (Array.isArray(value)) {
for (const row of value) {
this.push(fieldname, row);
}
} else {
this[fieldname] = value;
}
}
// set unset fields as null
for (const field of this.schema.fields) {
if (this[field.fieldname] === undefined) {
this[field.fieldname] = null;
this[fieldname] = value ?? null;
}
}
}
@ -198,7 +194,7 @@ export default class Doc extends Observable<DocValue | Doc[]> {
});
}
setDefaults() {
_setDefaults() {
for (const field of this.schema.fields) {
if (!getIsNullOrUndef(this[field.fieldname])) {
continue;
@ -224,21 +220,21 @@ export default class Doc extends Observable<DocValue | Doc[]> {
}
}
append(fieldname: string, docValueMap: Doc | DocValueMap = {}) {
async append(fieldname: string, docValueMap: Doc | DocValueMap = {}) {
// push child row and trigger change
this.push(fieldname, docValueMap);
this._dirty = true;
this._applyChange(fieldname);
await this._applyChange(fieldname);
}
push(fieldname: string, docValueMap: Doc | DocValueMap = {}) {
// push child row without triggering change
this[fieldname] ??= [];
const childDoc = this._initChild(docValueMap, fieldname);
const childDoc = this._getChildDoc(docValueMap, fieldname);
(this[fieldname] as Doc[]).push(childDoc);
}
_initChild(docValueMap: Doc | DocValueMap, fieldname: string): Doc {
_getChildDoc(docValueMap: Doc | DocValueMap, fieldname: string): Doc {
if (docValueMap instanceof Doc) {
return docValueMap;
}
@ -258,14 +254,13 @@ export default class Doc extends Observable<DocValue | Doc[]> {
data.name = getRandomString();
}
const childSchemaName = this.fieldMap[fieldname] as TargetField;
const schema = this.fyo.db.schemaMap[childSchemaName.target] as Schema;
const targetField = this.fieldMap[fieldname] as TargetField;
const schema = this.fyo.db.schemaMap[targetField.target] as Schema;
const childDoc = new Doc(schema, data as DocValueMap, this.fyo);
childDoc.setDefaults();
return childDoc;
}
async validateInsert() {
async _validateInsert() {
this._validateMandatory();
await this._validateFields();
}
@ -373,10 +368,6 @@ export default class Doc extends Observable<DocValue | Doc[]> {
if (data && data.name) {
this.syncValues(data);
if (this.schema.isSingle) {
this.setDefaults();
}
await this.loadLinks();
} else {
throw new NotFoundError(`Not Found: ${this.schemaName} ${this.name}`);
@ -420,7 +411,7 @@ export default class Doc extends Observable<DocValue | Doc[]> {
syncValues(data: DocValueMap) {
this.clearValues();
this._setInitialValues(data);
this._setValuesWithoutChecks(data);
this._dirty = false;
this.trigger('change', {
doc: this,
@ -436,7 +427,7 @@ export default class Doc extends Observable<DocValue | Doc[]> {
this._notInserted = true;
}
setChildIdx() {
_setChildIdx() {
const childFields = this.schema.fields.filter(
(f) => f.fieldtype === FieldTypeEnum.Table
) as TargetField[];
@ -450,7 +441,7 @@ export default class Doc extends Observable<DocValue | Doc[]> {
}
}
async compareWithCurrentDoc() {
async _compareWithCurrentDoc() {
if (this.isNew || !this.name) {
return;
}
@ -556,24 +547,24 @@ export default class Doc extends Observable<DocValue | Doc[]> {
return;
}
if (Array.isArray(value) && field.fieldtype === FieldTypeEnum.Table) {
value = value.map((row) => this._initChild(row, field.fieldname));
value = value.map((row) => this._getChildDoc(row, field.fieldname));
}
return value;
}
async commit() {
async _commit() {
// re-run triggers
this.setChildIdx();
this._setChildIdx();
await this._applyFormula();
await this.trigger('validate', null);
}
async insert() {
async _insert() {
await setName(this, this.fyo);
this._setBaseMetaValues();
await this.commit();
await this.validateInsert();
await this._commit();
await this._validateInsert();
await this.trigger('beforeInsert', null);
const oldName = this.name!;
@ -591,9 +582,9 @@ export default class Doc extends Observable<DocValue | Doc[]> {
return this;
}
async update() {
await this.compareWithCurrentDoc();
await this.commit();
async _update() {
await this._compareWithCurrentDoc();
await this._commit();
await this.trigger('beforeUpdate');
// before submit
@ -617,11 +608,11 @@ export default class Doc extends Observable<DocValue | Doc[]> {
return this;
}
async insertOrUpdate() {
async sync() {
if (this._notInserted) {
return await this.insert();
return await this._insert();
} else {
return await this.update();
return await this._update();
}
}
@ -633,11 +624,11 @@ export default class Doc extends Observable<DocValue | Doc[]> {
this.fyo.telemetry.log(Verb.Deleted, this.schemaName);
}
async submitOrRevert(isSubmit: boolean) {
async _submitOrRevert(isSubmit: boolean) {
const wasSubmitted = this.submitted;
this.submitted = isSubmit;
try {
await this.update();
await this.sync();
} catch (e) {
this.submitted = wasSubmitted;
throw e;
@ -646,11 +637,11 @@ export default class Doc extends Observable<DocValue | Doc[]> {
async submit() {
this.cancelled = false;
await this.submitOrRevert(true);
await this._submitOrRevert(true);
}
async revert() {
await this.submitOrRevert(false);
await this._submitOrRevert(false);
}
async rename(newName: string) {
@ -701,15 +692,12 @@ export default class Doc extends Observable<DocValue | Doc[]> {
return this.fyo.doc.getCachedValue(schemaName, name, fieldname);
}
async setAndUpdate(
fieldname: string | DocValueMap,
value?: DocValue | Doc[]
) {
async setAndSync(fieldname: string | DocValueMap, value?: DocValue | Doc[]) {
await this.set(fieldname, value);
return await this.update();
return await this.sync();
}
async duplicate(shouldInsert: boolean = true): Promise<Doc> {
async duplicate(shouldSync: boolean = true): Promise<Doc> {
const updateMap: DocValueMap = {};
const docValueMap = this.getValidDict();
const fieldnames = this.schema.fields.map((f) => f.fieldname);
@ -736,11 +724,11 @@ export default class Doc extends Observable<DocValue | Doc[]> {
updateMap.name = updateMap.name + ' CPY';
}
const doc = this.fyo.doc.getEmptyDoc(this.schemaName, false);
const doc = this.fyo.doc.getNewDoc(this.schemaName, {}, false);
await doc.setMultiple(updateMap);
if (shouldInsert) {
await doc.insert();
if (shouldSync) {
await doc.sync();
}
return doc;

View File

@ -5,7 +5,7 @@ import { isEqual } from 'lodash';
import Money from 'pesa/dist/types/src/money';
import { Field, FieldType, FieldTypeEnum } from 'schemas/types';
import { getIsNullOrUndef } from 'utils';
import Doc from './doc';
import { Doc } from './doc';
export function areDocValuesEqual(
dvOne: DocValue | Doc[],

View File

@ -4,7 +4,7 @@ import { DEFAULT_SERIES_START } from 'fyo/utils/consts';
import { BaseError } from 'fyo/utils/errors';
import { Field, Schema } from 'schemas/types';
import { getRandomString } from 'utils';
import Doc from './doc';
import { Doc } from './doc';
export function getNumberSeries(schema: Schema): Field | undefined {
const numberSeries = schema.fields.find(
@ -119,5 +119,5 @@ export async function createNumberSeries(
referenceType,
});
await series.insert();
await series.sync();
}

View File

@ -4,7 +4,7 @@ import SystemSettings from 'fyo/models/SystemSettings';
import { FieldType } from 'schemas/types';
import { QueryFilter } from 'utils/db/types';
import { Router } from 'vue-router';
import Doc from './doc';
import { Doc } from './doc';
/**
* The functions below are used for dynamic evaluation

View File

@ -1,4 +1,4 @@
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
function getPaddedName(prefix: string, next: number, padZeros: number): string {
return prefix + next.toString().padStart(padZeros ?? 4, '0');
@ -21,7 +21,7 @@ export default class NumberSeries extends Doc {
}
this.current = (this.current as number) + 1;
await this.update();
await this.sync();
return this.getPaddedName(this.current as number);
}

View File

@ -1,5 +1,5 @@
import { DocValue } from 'fyo/core/types';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { ValidationMap } from 'fyo/model/types';
import { ValidationError } from 'fyo/utils/errors';
import { t } from 'fyo/utils/translation';

View File

@ -58,14 +58,14 @@ describe('Fyo Docs', function () {
await fyo.close();
});
specify('getEmptyDoc', async function () {
specify('getNewDoc', async function () {
for (const schemaName in schemaMap) {
const schema = schemaMap[schemaName];
if (schema?.isSingle) {
continue;
}
const doc = fyo.doc.getEmptyDoc(schemaName);
const doc = fyo.doc.getNewDoc(schemaName);
}
});
});

View File

@ -1,6 +1,6 @@
import { Fyo } from 'fyo';
import { DocValue } from 'fyo/core/types';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { DateTime } from 'luxon';
import Money from 'pesa/dist/types/src/money';
import { Field, FieldType, FieldTypeEnum } from 'schemas/types';

View File

@ -1,5 +1,5 @@
import { Fyo } from 'fyo';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { Action } from 'fyo/model/types';
import { pesa } from 'pesa';

View File

@ -1,5 +1,5 @@
import { Fyo } from 'fyo';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import {
FiltersMap,
ListViewSettings,

View File

@ -1,4 +1,4 @@
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { ListViewSettings } from 'fyo/model/types';
export class AccountingLedgerEntry extends Doc {

View File

@ -1,4 +1,4 @@
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { FiltersMap, ListsMap, ValidationMap } from 'fyo/model/types';
import { validateEmail } from 'fyo/model/validationFunction';
import { getCountryInfo } from 'utils/misc';

View File

@ -1,5 +1,5 @@
import { Fyo } from 'fyo';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { EmptyMessageMap, FormulaMap, ListsMap } from 'fyo/model/types';
import { stateCodeMap } from 'regional/in';
import { titleCase } from 'utils';

View File

@ -1,5 +1,5 @@
import { DocValue } from 'fyo/core/types';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { DefaultMap, FiltersMap, FormulaMap } from 'fyo/model/types';
import { getExchangeRate } from 'models/helpers';
import { LedgerPosting } from 'models/ledgerPosting/ledgerPosting';

View File

@ -1,5 +1,5 @@
import { DocValue } from 'fyo/core/types';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import {
DependsOnMap,
FiltersMap,

View File

@ -1,6 +1,6 @@
import { Fyo } from 'fyo';
import { DocValue } from 'fyo/core/types';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import {
Action,
DependsOnMap,
@ -68,8 +68,8 @@ export class Item extends Doc {
label: fyo.t`New Invoice`,
condition: (doc) => !doc.isNew,
action: async (doc, router) => {
const invoice = await fyo.doc.getEmptyDoc('SalesInvoice');
invoice.append('items', {
const invoice = await fyo.doc.getNewDoc('SalesInvoice');
await invoice.append('items', {
item: doc.name as string,
rate: doc.rate as Money,
tax: doc.tax as string,
@ -81,8 +81,8 @@ export class Item extends Doc {
label: fyo.t`New Bill`,
condition: (doc) => !doc.isNew,
action: async (doc, router) => {
const invoice = await fyo.doc.getEmptyDoc('PurchaseInvoice');
invoice.append('items', {
const invoice = await fyo.doc.getNewDoc('PurchaseInvoice');
await invoice.append('items', {
item: doc.name as string,
rate: doc.rate as Money,
tax: doc.tax as string,

View File

@ -1,5 +1,5 @@
import { Fyo } from 'fyo';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import {
Action,
DefaultMap,

View File

@ -1,4 +1,4 @@
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { FiltersMap, FormulaMap } from 'fyo/model/types';
import Money from 'pesa/dist/types/src/money';

View File

@ -1,5 +1,5 @@
import { Fyo } from 'fyo';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import {
Action,
FiltersMap,
@ -47,7 +47,7 @@ export class Party extends Doc {
.reduce((a, b) => a.add(b), this.fyo.pesa(0));
await this.set('outstandingAmount', totalOutstanding);
await this.update();
await this.sync();
}
formulas: FormulaMap = {
@ -111,7 +111,7 @@ export class Party extends Doc {
condition: (doc: Doc) =>
!doc.isNew && (doc.role as PartyRole) !== 'Customer',
action: async (partyDoc, router) => {
const doc = await fyo.doc.getEmptyDoc('PurchaseInvoice');
const doc = await fyo.doc.getNewDoc('PurchaseInvoice');
router.push({
path: `/edit/PurchaseInvoice/${doc.name}`,
query: {
@ -146,7 +146,7 @@ export class Party extends Doc {
condition: (doc: Doc) =>
!doc.isNew && (doc.role as PartyRole) !== 'Supplier',
action: async (partyDoc, router) => {
const doc = await fyo.doc.getEmptyDoc('SalesInvoice');
const doc = await fyo.doc.getNewDoc('SalesInvoice');
router.push({
path: `/edit/SalesInvoice/${doc.name}`,
query: {

View File

@ -1,7 +1,6 @@
import { LedgerPosting } from 'models/ledgerPosting/ledgerPosting';
import { Fyo } from 'fyo';
import { DocValue } from 'fyo/core/types';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import {
Action,
DefaultMap,
@ -14,6 +13,7 @@ import {
} from 'fyo/model/types';
import { ValidationError } from 'fyo/utils/errors';
import { getLedgerLinkAction } from 'models/helpers';
import { LedgerPosting } from 'models/ledgerPosting/ledgerPosting';
import Money from 'pesa/dist/types/src/money';
import { getIsNullOrUndef } from 'utils';
import { Party } from '../Party/Party';
@ -237,7 +237,7 @@ export class Payment extends Doc {
// update outstanding amounts in invoice and party
const newOutstanding = outstandingAmount.sub(amount);
await referenceDoc.set('outstandingAmount', newOutstanding);
await referenceDoc.update();
await referenceDoc.sync();
const party = (await this.fyo.doc.getDoc(
'Party',
this.party!
@ -276,7 +276,7 @@ export class Payment extends Doc {
amount as Money
),
});
refDoc.update();
refDoc.sync();
}
);
}

View File

@ -1,4 +1,4 @@
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { FiltersMap, FormulaMap } from 'fyo/model/types';
import Money from 'pesa/dist/types/src/money';

View File

@ -1,5 +1,5 @@
import { t } from 'fyo';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import {
DependsOnMap,
FormulaMap,
@ -7,8 +7,7 @@ import {
ValidationMap,
} from 'fyo/model/types';
import { validateEmail } from 'fyo/model/validationFunction';
import { DateTime } from 'luxon';
import { getCountryInfo } from 'utils/misc';
import { getCountryInfo, getFiscalYear } from 'utils/misc';
export function getCOAList() {
return [
@ -42,35 +41,19 @@ export class SetupWizard extends Doc {
fiscalYearStart: async () => {
if (!this.country) return;
const today = DateTime.local();
const countryInfo = getCountryInfo();
const fyStart = countryInfo[this.country as string]?.fiscal_year_start as
| string
| undefined;
if (fyStart) {
return DateTime.fromFormat(fyStart, 'MM-dd')
.plus({ year: [1, 2, 3].includes(today.month) ? -1 : 0 })
.toISODate();
}
const fyStart =
countryInfo[this.country as string]?.fiscal_year_start ?? '';
return getFiscalYear(fyStart, true);
},
fiscalYearEnd: async () => {
if (!this.country) {
return;
}
const today = DateTime.local();
const countryInfo = getCountryInfo();
const fyEnd = countryInfo[this.country as string]?.fiscal_year_end as
| string
| undefined;
if (fyEnd) {
return DateTime.fromFormat(fyEnd, 'MM-dd')
.plus({ year: [1, 2, 3].includes(today.month) ? 0 : 1 })
.toISODate();
}
const fyEnd = countryInfo[this.country as string]?.fiscal_year_end ?? '';
return getFiscalYear(fyEnd, false);
},
currency: async () => {
if (!this.country) {

View File

@ -1,4 +1,4 @@
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { ListViewSettings } from 'fyo/model/types';
export class Tax extends Doc {

View File

@ -1,4 +1,4 @@
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { FormulaMap } from 'fyo/model/types';
import Money from 'pesa/dist/types/src/money';

View File

@ -1,5 +1,5 @@
import { Fyo } from 'fyo';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { Action, ColumnConfig } from 'fyo/model/types';
import { NotFoundError } from 'fyo/utils/errors';
import { DateTime } from 'luxon';
@ -34,7 +34,7 @@ export function getTransactionActions(schemaName: string, fyo: Fyo): Action[] {
condition: (doc: Doc) =>
(doc.submitted as boolean) && (doc.outstandingAmount as Money).gt(0),
action: async function makePayment(doc: Doc) {
const payment = await fyo.doc.getEmptyDoc('Payment');
const payment = await fyo.doc.getNewDoc('Payment');
payment.once('afterInsert', async () => {
await payment.submit();
});

View File

@ -1,5 +1,5 @@
import { Fyo } from 'fyo';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { ValidationError } from 'fyo/utils/errors';
import Money from 'pesa/dist/types/src/money';
import {
@ -127,7 +127,7 @@ export class LedgerPosting {
entry.name as string
);
entryDoc.reverted = true;
await entryDoc.update();
await entryDoc.sync();
}
let temp;
@ -193,13 +193,13 @@ export class LedgerPosting {
for (const entry of this.entries) {
const entryDoc = this.fyo.doc.getNewDoc('AccountingLedgerEntry');
Object.assign(entryDoc, entry);
await entryDoc.insert();
await entryDoc.sync();
}
for (const entry of this.accountEntries) {
const entryDoc = await this.fyo.doc.getDoc('Account', entry.name);
const balance = entryDoc.get('balance') as Money;
entryDoc.balance = balance.add(entry.balanceChange);
await entryDoc.update();
await entryDoc.sync();
}
}

View File

@ -1,4 +1,4 @@
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import Money from 'pesa/dist/types/src/money';
export interface LedgerPostingOptions {

View File

@ -101,7 +101,7 @@ export default {
},
async setupComplete(setupWizardOptions) {
const filePath = fyo.config.get(ConfigKeys.LastSelectedFilePath);
await setupInstance(filePath, setupWizardOptions);
await setupInstance(filePath, setupWizardOptions, fyo);
await this.setDesk();
},
async showSetupWizardOrDesk(filePath) {
@ -113,7 +113,7 @@ export default {
return;
}
await initializeInstance(filePath, false, countryCode);
await initializeInstance(filePath, false, countryCode, fyo);
await this.setDesk();
},
async setDeskRoute() {

View File

@ -17,3 +17,8 @@ All of them are triggered from `src/App.vue`.
1. Connect to db.
2. Check if _Setup Wizard_ has been completed, if not, jump to **New Instance**
3. Call `initFyo/initializeInstance` with `dbPath` and `countryCode`
## Global Fyo
Global fyo is exported from `initFyo.ts`. Only code that isn't going to be unit
tested should use this.

View File

@ -104,7 +104,7 @@ export default {
},
async openNewDoc() {
let doctype = this.df.target;
let doc = await fyo.getEmptyDoc(doctype);
let doc = await fyo.doc.getNewDoc(doctype);
let filters = await this.getFilters();
openQuickEdit({
doctype,

View File

@ -78,7 +78,7 @@ export default {
'dd/MM/yyyy'
).toISO();
payment.set({ clearanceDate });
await payment.update();
await payment.sync();
}
this.close();
await this.afterReconcile();

View File

@ -87,7 +87,7 @@
</div>
</template>
<script>
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import Button from 'src/components/Button.vue';
import FormControl from 'src/components/Controls/FormControl.vue';
import { getErrorMessage, handleErrorWithDialog } from 'src/errorHandling';
@ -201,14 +201,11 @@ export default {
if (df.fieldtype === 'Table') {
return;
}
this.doc.update();
this.doc.sync();
}
},
insertOrUpdate() {
return this.doc.insertOrUpdate().catch(this.handleError);
},
insert() {
return this.doc.insert().catch(this.handleError);
sync() {
return this.doc.sync().catch(this.handleError);
},
submit() {
return this.doc.submit().catch(this.handleError);
@ -223,7 +220,7 @@ export default {
this.inlineEditField = df;
if (!this.doc[df.fieldname]) {
this.inlineEditDoc = await fyo.doc.getEmptyDoc(df.target);
this.inlineEditDoc = await fyo.doc.getNewDoc(df.target);
this.inlineEditDoc.once('afterInsert', () => {
this.onChangeCommon(df, this.inlineEditDoc.name);
});
@ -239,7 +236,7 @@ export default {
if (!this.inlineEditDoc) {
return;
}
await this.$refs.inlineEditForm[0].insertOrUpdate();
await this.$refs.inlineEditForm[0].sync();
await this.doc.loadLinks();
if (this.emitChange && df.inline) {

View File

@ -1,6 +1,6 @@
import { Fyo, t } from 'fyo';
import { DocValueMap } from 'fyo/core/types';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { isNameAutoSet } from 'fyo/model/naming';
import { Noun, Verb } from 'fyo/telemetry/types';
import {
@ -389,7 +389,7 @@ export class Importer {
delete docObj[key];
}
const doc: Doc = this.fyo.doc.getEmptyDoc(this.schemaName, false);
const doc: Doc = this.fyo.doc.getNewDoc(this.schemaName, {}, false);
try {
await this.makeEntry(doc, docObj);
entriesMade += 1;
@ -425,7 +425,7 @@ export class Importer {
async makeEntry(doc: Doc, docObj: Map) {
await doc.setMultiple(docObj as DocValueMap);
await doc.insert();
await doc.sync();
if (this.shouldSubmit) {
await doc.submit();
}

View File

@ -1,7 +1,7 @@
import { ipcRenderer } from 'electron';
import { t } from 'fyo';
import { ConfigKeys } from 'fyo/core/types';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { TelemetrySetting } from 'fyo/telemetry/types';
import {
DuplicateEntryError,

View File

@ -1,5 +1,6 @@
import { Fyo } from 'fyo';
import { getRegionalModels, models } from 'models';
import { ModelNameEnum } from 'models/types';
import { getValueMapFromList } from 'utils';
export const fyo = new Fyo({ isTest: false, isElectron: true });
@ -15,7 +16,8 @@ async function closeDbIfConnected() {
export async function initializeInstance(
dbPath: string,
isNew: boolean,
countryCode: string
countryCode: string,
fyo: Fyo
) {
if (isNew) {
await closeDbIfConnected();
@ -27,17 +29,17 @@ export async function initializeInstance(
const regionalModels = await getRegionalModels(countryCode);
await fyo.initializeAndRegister(models, regionalModels);
await setSingles();
await setCurrencySymbols();
await setSingles(fyo);
await setCurrencySymbols(fyo);
}
async function setSingles() {
await fyo.doc.getSingle('AccountingSettings');
await fyo.doc.getSingle('GetStarted');
async function setSingles(fyo: Fyo) {
await fyo.doc.getSingle(ModelNameEnum.AccountingSettings);
await fyo.doc.getSingle(ModelNameEnum.GetStarted);
}
async function setCurrencySymbols() {
const currencies = (await fyo.db.getAll('Currency', {
async function setCurrencySymbols(fyo: Fyo) {
const currencies = (await fyo.db.getAll(ModelNameEnum.Currency, {
fields: ['name', 'symbol'],
})) as { name: string; symbol: string }[];

View File

@ -240,7 +240,7 @@ export default {
this.insertingAccount = true;
accountName = accountName.trim();
let account = await fyo.getEmptyDoc('Account');
let account = await fyo.doc.getNewDoc('Account');
try {
let { name, rootType, accountType } = parentAccount;
await account.set({
@ -250,7 +250,7 @@ export default {
accountType,
isGroup,
});
await account.insert();
await account.sync();
// turn off editing
parentAccount.addingAccount = 0;

View File

@ -74,7 +74,6 @@ export default {
},
methods: {
selectOption(value) {
console.log(value);
this.$emit('change', value);
this.$refs.dropdown.toggleDropdown(false);
},

View File

@ -143,7 +143,7 @@ export default {
this.invoices = await Promise.all(promises);
},
async newInvoice(invoice) {
let doc = await fyo.doc.getEmptyDoc(invoice.doctype);
let doc = await fyo.doc.getNewDoc(invoice.doctype);
routeTo(`/edit/${invoice.doctype}/${doc.name}`);
},
},

View File

@ -308,7 +308,7 @@ export default {
await this.updateChecks({ onboardingComplete });
const systemSettings = await fyo.getSingle('SystemSettings');
await systemSettings.set({ hideGetStarted: 1 });
await systemSettings.update();
await systemSettings.sync();
}
return onboardingComplete;
@ -361,7 +361,7 @@ export default {
},
async updateChecks(toUpdate) {
await fyo.GetStarted.setMultiple(toUpdate);
await fyo.GetStarted.update();
await fyo.GetStarted.sync();
fyo.GetStarted = await fyo.getSingle('GetStarted');
},
isCompleted(item) {

View File

@ -293,7 +293,7 @@ export default {
'items',
this.doc.items.filter((row) => row.item)
);
return this.doc.insertOrUpdate().catch(this.handleError);
return this.doc.sync().catch(this.handleError);
},
onSubmitClick() {
let message =

View File

@ -204,7 +204,7 @@ export default {
},
methods: {
async onSaveClick() {
return this.doc.insertOrUpdate().catch(this.handleError);
return this.doc.sync().catch(this.handleError);
},
async onSubmitClick() {
showMessageDialog({

View File

@ -63,7 +63,7 @@ export default {
methods: {
async makeNewDoc() {
const doctype = this.listConfig.doctype;
const doc = await fyo.doc.getEmptyDoc(doctype);
const doc = await fyo.doc.getNewDoc(doctype);
if (this.listConfig.filters) {
doc.set(this.listConfig.filters);
}

View File

@ -14,7 +14,7 @@
<StatusBadge :status="status" />
<Button
:icon="true"
@click="insertDoc"
@click="sync"
type="primary"
v-if="doc && doc._notInserted"
class="ml-2 text-white text-xs"
@ -210,8 +210,8 @@ export default {
valueChange(df, value) {
this.$refs.form.onChange(df, value);
},
insertDoc() {
this.$refs.form.insert();
sync() {
this.$refs.form.sync();
},
async submitDoc() {
try {

View File

@ -7,7 +7,7 @@
@change="
(value) => {
doc.set('logo', value);
doc.update();
doc.sync();
forwardChangeEvent(getField('logo'));
}
"
@ -27,7 +27,7 @@
@change="
(value) => {
doc.set('displayLogo', value);
doc.update();
doc.sync();
forwardChangeEvent(getField('displayLogo'));
}
"

View File

@ -1,30 +1,26 @@
import { fyo } from 'src/initFyo';
import { Fyo } from 'fyo';
export type TaxType = 'GST' | 'IGST' | 'Exempt-GST' | 'Exempt-IGST';
export async function createIndianRecords() {
await generateTaxes();
export async function createIndianRecords(fyo: Fyo) {
await createTaxes(fyo);
}
async function generateTaxes() {
async function createTaxes(fyo: Fyo) {
const GSTs = {
GST: [28, 18, 12, 6, 5, 3, 0.25, 0],
IGST: [28, 18, 12, 6, 5, 3, 0.25, 0],
'Exempt-GST': [0],
'Exempt-IGST': [0],
};
const newTax = await fyo.doc.getEmptyDoc('Tax');
for (const type of Object.keys(GSTs)) {
for (const percent of GSTs[type as TaxType]) {
const name = `${type}-${percent}`;
// Not cross checking cause hardcoded values.
await fyo.db.delete('Tax', name);
const details = getTaxDetails(type as TaxType, percent);
await newTax.set({ name, details });
await newTax.insert();
const newTax = fyo.doc.getNewDoc('Tax', { name, details });
await newTax.sync();
}
}
}
@ -41,12 +37,12 @@ function getTaxDetails(type: TaxType, percent: number) {
rate: percent / 2,
},
];
} else {
return [
{
account: type.toString().split('-')[0],
rate: percent,
},
];
}
return [
{
account: type.toString().split('-')[0],
rate: percent,
},
];
}

View File

@ -1,8 +1,9 @@
import { Fyo } from 'fyo';
import { createIndianRecords } from './in/in';
export async function createRegionalRecords(country: string) {
export async function createRegionalRecords(country: string, fyo: Fyo) {
if (country === 'India') {
await createIndianRecords();
await createIndianRecords(fyo);
}
return;

View File

@ -1,3 +1,4 @@
import { Fyo } from 'fyo';
import {
AccountRootType,
COAChildAccount,
@ -5,57 +6,66 @@ import {
COATree,
} from 'models/baseModels/Account/types';
import { getCOAList } from 'models/baseModels/SetupWizard/SetupWizard';
import { fyo } from 'src/initFyo';
import { getStandardCOA } from './standardCOA';
const accountFields = ['accountType', 'accountNumber', 'rootType', 'isGroup'];
function getAccountName(accountName: string, accountNumber?: string) {
if (accountNumber) {
return `${accountName} - ${accountNumber}`;
export class CreateCOA {
fyo: Fyo;
chartOfAccounts: string;
constructor(chartOfAccounts: string, fyo: Fyo) {
this.chartOfAccounts = chartOfAccounts;
this.fyo = fyo;
}
return accountName;
}
async run() {
const chart = await getCOA(this.chartOfAccounts);
await this.createCOAAccounts(chart, null, '', true);
}
async function createCOAAccounts(
children: COATree | COARootAccount | COAChildAccount,
parentAccount: string,
rootType: AccountRootType | '',
rootAccount: boolean
) {
for (const rootName in children) {
if (accountFields.includes(rootName)) {
continue;
async createCOAAccounts(
children: COATree | COARootAccount | COAChildAccount,
parentAccount: string | null,
rootType: AccountRootType | '',
rootAccount: boolean
) {
for (const rootName in children) {
if (accountFields.includes(rootName)) {
continue;
}
const child = children[rootName];
if (rootAccount) {
rootType = (child as COARootAccount).rootType as AccountRootType;
}
const accountType = (child as COAChildAccount).accountType ?? '';
const accountNumber = (child as COAChildAccount).accountNumber;
const accountName = getAccountName(rootName, accountNumber);
const isGroup = identifyIsGroup(
child as COAChildAccount | COARootAccount
);
const doc = this.fyo.doc.getNewDoc('Account', {
name: accountName,
parentAccount,
isGroup,
rootType,
balance: 0,
accountType,
});
await doc.sync();
await this.createCOAAccounts(
child as COAChildAccount,
accountName,
rootType,
false
);
}
const child = children[rootName];
if (rootAccount) {
rootType = (child as COARootAccount).rootType as AccountRootType;
}
const accountType = (child as COAChildAccount).accountType ?? '';
const accountNumber = (child as COAChildAccount).accountNumber;
const accountName = getAccountName(rootName, accountNumber);
const isGroup = identifyIsGroup(child as COAChildAccount | COARootAccount);
const doc = fyo.doc.getNewDoc('Account', {
name: accountName,
parentAccount,
isGroup,
rootType,
balance: 0,
accountType,
});
await doc.insert();
await createCOAAccounts(
child as COAChildAccount,
accountName,
rootType,
false
);
}
}
@ -92,7 +102,10 @@ async function getCOA(chartOfAccounts: string) {
}
}
export async function createCOA(chartOfAccounts: string) {
const chart = await getCOA(chartOfAccounts);
await createCOAAccounts(chart, '', '', true);
function getAccountName(accountName: string, accountNumber?: string) {
if (accountNumber) {
return `${accountName} - ${accountNumber}`;
}
return accountName;
}

View File

@ -1,5 +1,6 @@
import { Fyo } from 'fyo';
import { ConfigFile, DocValueMap } from 'fyo/core/types';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { createNumberSeries } from 'fyo/model/naming';
import { getId } from 'fyo/telemetry/helpers';
import {
@ -8,51 +9,55 @@ import {
DEFAULT_SERIES_START,
} from 'fyo/utils/consts';
import { AccountingSettings } from 'models/baseModels/AccountingSettings/AccountingSettings';
import { fyo, initializeInstance } from 'src/initFyo';
import { initializeInstance } from 'src/initFyo';
import { createRegionalRecords } from 'src/regional';
import { getCountryCodeFromCountry, getCountryInfo } from 'utils/misc';
import { CountryInfo } from 'utils/types';
import { createCOA } from './createCOA';
import { CreateCOA } from './createCOA';
import { SetupWizardOptions } from './types';
export default async function setupInstance(
dbPath: string,
setupWizardOptions: SetupWizardOptions
setupWizardOptions: SetupWizardOptions,
fyo: Fyo
) {
const { companyName, country, bankName, chartOfAccounts } =
setupWizardOptions;
await initializeDatabase(dbPath, country);
await updateSystemSettings(setupWizardOptions);
await updateAccountingSettings(setupWizardOptions);
await updatePrintSettings(setupWizardOptions);
await initializeDatabase(dbPath, country, fyo);
await updateSystemSettings(setupWizardOptions, fyo);
await updateAccountingSettings(setupWizardOptions, fyo);
await updatePrintSettings(setupWizardOptions, fyo);
await createCurrencyRecords();
await createAccountRecords(bankName, country, chartOfAccounts);
await createRegionalRecords(country);
await createDefaultNumberSeries();
await createCurrencyRecords(fyo);
await createAccountRecords(bankName, country, chartOfAccounts, fyo);
await createRegionalRecords(country, fyo);
await createDefaultNumberSeries(fyo);
await completeSetup(companyName);
await completeSetup(companyName, fyo);
}
async function initializeDatabase(dbPath: string, country: string) {
async function initializeDatabase(dbPath: string, country: string, fyo: Fyo) {
const countryCode = getCountryCodeFromCountry(country);
await initializeInstance(dbPath, true, countryCode);
await initializeInstance(dbPath, true, countryCode, fyo);
}
async function updateAccountingSettings({
companyName,
country,
fullname,
email,
bankName,
fiscalYearStart,
fiscalYearEnd,
}: SetupWizardOptions) {
async function updateAccountingSettings(
{
companyName,
country,
fullname,
email,
bankName,
fiscalYearStart,
fiscalYearEnd,
}: SetupWizardOptions,
fyo: Fyo
) {
const accountingSettings = (await fyo.doc.getSingle(
'AccountingSettings'
)) as AccountingSettings;
await accountingSettings.setAndUpdate({
await accountingSettings.setAndSync({
companyName,
country,
fullname,
@ -64,13 +69,12 @@ async function updateAccountingSettings({
return accountingSettings;
}
async function updatePrintSettings({
companyLogo,
companyName,
email,
}: SetupWizardOptions) {
async function updatePrintSettings(
{ companyLogo, companyName, email }: SetupWizardOptions,
fyo: Fyo
) {
const printSettings = await fyo.doc.getSingle('PrintSettings');
await printSettings.setAndUpdate({
await printSettings.setAndSync({
logo: companyLogo,
companyName,
email,
@ -78,23 +82,23 @@ async function updatePrintSettings({
});
}
async function updateSystemSettings({
country,
currency: companyCurrency,
}: SetupWizardOptions) {
async function updateSystemSettings(
{ country, currency: companyCurrency }: SetupWizardOptions,
fyo: Fyo
) {
const countryInfo = getCountryInfo();
const countryOptions = countryInfo[country] as CountryInfo;
const currency =
companyCurrency ?? countryOptions.currency ?? DEFAULT_CURRENCY;
const locale = countryOptions.locale ?? DEFAULT_LOCALE;
const systemSettings = await fyo.doc.getSingle('SystemSettings');
systemSettings.setAndUpdate({
systemSettings.setAndSync({
locale,
currency,
});
}
async function createCurrencyRecords() {
async function createCurrencyRecords(fyo: Fyo) {
const promises: Promise<Doc | undefined>[] = [];
const queue: string[] = [];
const countrySettings = Object.values(getCountryInfo()) as CountryInfo[];
@ -120,7 +124,7 @@ async function createCurrencyRecords() {
symbol: currency_symbol ?? '',
};
const doc = checkAndCreateDoc('Currency', docObject);
const doc = checkAndCreateDoc('Currency', docObject, fyo);
if (doc) {
promises.push(doc);
queue.push(currency);
@ -132,10 +136,12 @@ async function createCurrencyRecords() {
async function createAccountRecords(
bankName: string,
country: string,
chartOfAccounts: string
chartOfAccounts: string,
fyo: Fyo
) {
await createCOA(chartOfAccounts);
const parentAccount = await getBankAccountParentName(country);
const createCOA = new CreateCOA(chartOfAccounts, fyo);
await createCOA.run();
const parentAccount = await getBankAccountParentName(country, fyo);
const docObject = {
name: bankName,
rootType: 'Asset',
@ -143,16 +149,16 @@ async function createAccountRecords(
accountType: 'Bank',
isGroup: false,
};
await checkAndCreateDoc('Account', docObject);
await checkAndCreateDoc('Account', docObject, fyo);
}
async function completeSetup(companyName: string) {
updateInitializationConfig(companyName);
async function completeSetup(companyName: string, fyo: Fyo) {
updateInitializationConfig(companyName, fyo);
await fyo.singles.AccountingSettings!.set('setupComplete', true);
await fyo.singles.AccountingSettings!.update();
await fyo.singles.AccountingSettings!.sync();
}
function updateInitializationConfig(companyName: string) {
function updateInitializationConfig(companyName: string, fyo: Fyo) {
const dbPath = fyo.db.dbPath;
const files = fyo.config.get('files', []) as ConfigFile[];
@ -166,19 +172,24 @@ function updateInitializationConfig(companyName: string) {
fyo.config.set('files', files);
}
async function checkAndCreateDoc(schemaName: string, docObject: DocValueMap) {
const canCreate = await checkIfExactRecordAbsent(schemaName, docObject);
async function checkAndCreateDoc(
schemaName: string,
docObject: DocValueMap,
fyo: Fyo
) {
const canCreate = await checkIfExactRecordAbsent(schemaName, docObject, fyo);
if (!canCreate) {
return;
}
const doc = await fyo.doc.getNewDoc(schemaName, docObject);
return doc.insert();
return doc.sync();
}
async function checkIfExactRecordAbsent(
schemaName: string,
docMap: DocValueMap
docMap: DocValueMap,
fyo: Fyo
) {
const name = docMap.name as string;
const newDocObject = Object.assign({}, docMap);
@ -207,7 +218,7 @@ async function checkIfExactRecordAbsent(
return false;
}
async function getBankAccountParentName(country: string) {
async function getBankAccountParentName(country: string, fyo: Fyo) {
const parentBankAccount = await fyo.db.getAllRaw('Account', {
fields: ['*'],
filters: { isGroup: true, accountType: 'Bank' },
@ -228,7 +239,7 @@ async function getBankAccountParentName(country: string) {
return parentBankAccount[0].name;
}
async function createDefaultNumberSeries() {
async function createDefaultNumberSeries(fyo: Fyo) {
await createNumberSeries('SINV-', 'SalesInvoice', DEFAULT_SERIES_START, fyo);
await createNumberSeries(
'PINV-',

View File

@ -1,4 +1,4 @@
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { Field, OptionField, SelectOption } from 'schemas/types';
import { fyo } from 'src/initFyo';

View File

@ -1,10 +1,9 @@
/**
* General purpose utils used by the frontend.
*/
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { isPesa } from 'fyo/utils';
import Money from 'pesa/dist/types/src/money';
import { fyo } from 'src/initFyo';
export function stringifyCircular(
obj: unknown,

View File

@ -40,6 +40,7 @@ export async function getSetupWizardDoc() {
return await fyo.doc.getNewDoc(
'SetupWizard',
{},
false,
SetupWizardSchema as Schema,
SetupWizard
);

View File

@ -4,7 +4,7 @@
*/
import { ipcRenderer } from 'electron';
import { t } from 'fyo';
import Doc from 'fyo/model/doc';
import { Doc } from 'fyo/model/doc';
import { Action } from 'fyo/model/types';
import { getActions } from 'fyo/utils';
import { handleErrorWithDialog } from 'src/errorHandling';
@ -222,7 +222,7 @@ export async function cancelDocWithPrompt(doc: Doc) {
async action() {
const entryDoc = await fyo.doc.getDoc(doc.schemaName, doc.name!);
entryDoc.cancelled = 1;
await entryDoc.update();
await entryDoc.sync();
entryDoc
.revert()
.then(() => resolve(true))

17
tests/helpers.ts Normal file
View File

@ -0,0 +1,17 @@
import { SetupWizardOptions } from 'src/setup/types';
import { getFiscalYear } from 'utils/misc';
export function getTestSetupWizardOptions(): SetupWizardOptions {
return {
companyLogo: '',
companyName: 'Test Company',
country: 'India',
fullname: 'Test Person',
email: 'test@testmyfantasy.com',
bankName: 'Test Bank of Scriptia',
currency: 'INR',
fiscalYearStart: getFiscalYear('04-01', true),
fiscalYearEnd: getFiscalYear('04-01', false),
chartOfAccounts: 'India - Chart of Accounts',
};
}

View File

@ -0,0 +1,25 @@
import { DatabaseManager } from 'backend/database/manager';
import { assertDoesNotThrow } from 'backend/database/tests/helpers';
import { Fyo } from 'fyo';
import { DummyAuthDemux } from 'fyo/tests/helpers';
import 'mocha';
import setupInstance from 'src/setup/setupInstance';
import { getTestSetupWizardOptions } from './helpers';
const DB_PATH = '/Users/alan/Desktop/test.db';
describe('setupInstance', function () {
const fyo = new Fyo({
DatabaseDemux: DatabaseManager,
AuthDemux: DummyAuthDemux,
isTest: true,
isElectron: false,
});
const setupOptions = getTestSetupWizardOptions();
specify('setupInstance', async function () {
await setupInstance(DB_PATH, setupOptions, fyo);
await assertDoesNotThrow(async () => {
// await setupInstance(':memory:', setupOptions, fyo);
}, 'setup instance failed');
});
});

View File

@ -46,6 +46,7 @@
"regional/**/*.ts",
"reports/**/*.ts",
"utils/**/*.ts",
"tests/**/*.ts",
],
"exclude": ["node_modules"]
}

View File

@ -1,4 +1,5 @@
import countryInfo from 'fixtures/countryInfo.json';
import { DateTime } from 'luxon';
import { CountryInfoMap } from './types';
export function getCountryInfo(): CountryInfoMap {
@ -15,3 +16,21 @@ export function getCountryCodeFromCountry(countryName: string): string {
return countryInfo.code;
}
export function getFiscalYear(date: string, isStart: boolean) {
if (!date) {
return '';
}
const today = DateTime.local();
const dateTime = DateTime.fromFormat(date, 'MM-dd');
if (isStart) {
return dateTime
.plus({ year: [1, 2, 3].includes(today.month) ? -1 : 0 })
.toISODate();
}
return dateTime
.plus({ year: [1, 2, 3].includes(today.month) ? 0 : 1 })
.toISODate();
}