2
0
mirror of https://github.com/frappe/books.git synced 2025-01-03 07:12:21 +00:00

incr: type some files, frappe -> fyo

- get books to serve albiet broken
- one step at a time
This commit is contained in:
18alantom 2022-04-21 18:38:36 +05:30
parent 835deb4ce8
commit 27aed52044
91 changed files with 1238 additions and 1130 deletions

View File

@ -1,5 +1,6 @@
import frappe, { t } from 'fyo';
import { t } from 'fyo';
import { DateTime } from 'luxon';
import { fyo } from 'src/initFyo';
import { showMessageDialog } from 'src/utils';
import { stateCodeMap } from '../regional/in';
import { exportCsv, saveExportData } from '../reports/commonExporter';
@ -46,7 +47,7 @@ const IGST = {
};
export async function generateGstr1Json(getReportData) {
const { gstin } = frappe.AccountingSettings;
const { gstin } = fyo.AccountingSettings;
if (!gstin) {
showMessageDialog({
message: t`Export Failed`,
@ -106,7 +107,7 @@ async function generateB2bData(rows) {
itms: [],
};
const items = await frappe.db.getAllRaw('SalesInvoiceItem', {
const items = await fyo.db.getAllRaw('SalesInvoiceItem', {
fields: ['*'],
filters: { parent: invRecord.inum },
});
@ -115,18 +116,18 @@ async function generateB2bData(rows) {
const itemRecord = {
num: item.hsnCode,
itm_det: {
txval: frappe.pesa(item.baseAmount).float,
txval: fyo.pesa(item.baseAmount).float,
rt: GST[item.tax],
csamt: 0,
camt: frappe
camt: fyo
.pesa(CSGST[item.tax] || 0)
.mul(item.baseAmount)
.div(100).float,
samt: frappe
samt: fyo
.pesa(CSGST[item.tax] || 0)
.mul(item.baseAmount)
.div(100).float,
iamt: frappe
iamt: fyo
.pesa(IGST[item.tax] || 0)
.mul(item.baseAmount)
.div(100).float,
@ -167,7 +168,7 @@ async function generateB2clData(invoices) {
itms: [],
};
const items = await frappe.db.getAllRaw('SalesInvoiceItem', {
const items = await fyo.db.getAllRaw('SalesInvoiceItem', {
fields: ['*'],
filters: { parent: invRecord.inum },
});
@ -176,10 +177,10 @@ async function generateB2clData(invoices) {
const itemRecord = {
num: item.hsnCode,
itm_det: {
txval: frappe.pesa(item.baseAmount).float,
txval: fyo.pesa(item.baseAmount).float,
rt: GST[item.tax],
csamt: 0,
iamt: frappe
iamt: fyo
.pesa(invoice.rate || 0)
.mul(item.baseAmount)
.div(100).float,
@ -228,7 +229,7 @@ async function generateB2csData(invoices) {
}
export async function generateGstr2Csv(getReportData) {
const { gstin } = frappe.AccountingSettings;
const { gstin } = fyo.AccountingSettings;
if (!gstin) {
showMessageDialog({
message: t`Export Failed`,
@ -309,7 +310,7 @@ async function generateB2bCsvGstr2(rows, columns) {
}
export async function generateGstr1Csv(getReportData) {
const { gstin } = frappe.AccountingSettings;
const { gstin } = fyo.AccountingSettings;
if (!gstin) {
showMessageDialog({
message: t`Export Failed`,

View File

@ -1,8 +1,8 @@
import Doc from 'fyo/model/doc';
import { DocMap, ModelMap, SinglesMap } from 'fyo/model/types';
import { coreModels } from 'fyo/models';
import { getRandomString } from 'fyo/utils';
import Observable from 'fyo/utils/observable';
import { getRandomString } from 'utils';
import { Fyo } from '..';
import { DocValue, DocValueMap } from './types';

View File

@ -4,7 +4,14 @@ import { RawValue } from 'schemas/types';
import { AuthDemuxBase } from 'utils/auth/types';
import { DatabaseDemuxBase } from 'utils/db/types';
export type DocValue = string | number | boolean | Date | Money | null;
export type DocValue =
| string
| number
| boolean
| Date
| Money
| null
| undefined;
export type DocValueMap = Record<string, DocValue | Doc[] | DocValueMap[]>;
export type RawValueMap = Record<string, RawValue | RawValueMap[]>;

View File

@ -165,6 +165,11 @@ export class Fyo {
await this.auth.logout();
}
getField(schemaName: string, fieldname: string) {
const schema = this.schemaMap[schemaName];
return schema?.fields.find((f) => f.fieldname === fieldname);
}
store = {
isDevelopment: false,
appVersion: '',

View File

@ -16,8 +16,8 @@ import {
Schema,
TargetField,
} from 'schemas/types';
import { getIsNullOrUndef, getMapFromList } from 'utils';
import { getRandomString, isPesa } from '../utils/index';
import { getIsNullOrUndef, getMapFromList, getRandomString } from 'utils';
import { isPesa } from '../utils/index';
import {
areDocValuesEqual,
getMissingMandatoryMessage,

View File

@ -1,9 +1,9 @@
import { Fyo } from 'fyo';
import NumberSeries from 'fyo/models/NumberSeries';
import { getRandomString } from 'fyo/utils';
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';
export function getNumberSeries(schema: Schema): Field | undefined {

View File

@ -1,6 +1,6 @@
import * as assert from 'assert';
import 'mocha';
import models, { getRegionalModels } from 'models';
import { getRegionalModels, models } from 'models';
import { getSchemas } from 'schemas';
import { Fyo } from '..';
import { DatabaseManager } from '../../backend/database/manager';

View File

@ -1,4 +1,3 @@
import { Fyo } from 'fyo';
import Doc from 'fyo/model/doc';
import { Action } from 'fyo/model/types';
import { pesa } from 'pesa';
@ -11,23 +10,13 @@ export function slug(str: string) {
.replace(/\s+/g, '');
}
export function getRandomString() {
return Math.random().toString(36).substr(3);
}
export async function sleep(seconds: number) {
return new Promise((resolve) => {
setTimeout(resolve, seconds * 1000);
});
}
export function range(n: number) {
return Array(n)
.fill(null)
.map((_, i) => i);
}
export function unique(list: unknown[], key = (it: unknown) => String(it)) {
export function unique<T>(list: T[], key = (it: T) => String(it)) {
const seen: Record<string, boolean> = {};
return list.filter((item) => {
const k = key(item);
@ -54,11 +43,11 @@ export function isPesa(value: unknown): boolean {
return value instanceof pesa().constructor;
}
export function getActions(doc: Doc, fyo: Fyo): Action[] {
const Model = fyo.models[doc.schemaName];
export function getActions(doc: Doc): Action[] {
const Model = doc.fyo.models[doc.schemaName];
if (Model === undefined) {
return [];
}
return Model.getActions(fyo);
return Model.getActions(doc.fyo);
}

View File

@ -134,7 +134,7 @@ export default function registerIpcMainActionListeners(main: Main) {
countryCode
);
} catch (error) {
response.error = error.toString();
response.error = (error as Error).toString();
}
return response;
@ -151,7 +151,7 @@ export default function registerIpcMainActionListeners(main: Main) {
countryCode
);
} catch (error) {
response.error = error.toString();
response.error = (error as Error).toString();
}
return response;
@ -165,7 +165,7 @@ export default function registerIpcMainActionListeners(main: Main) {
try {
response.data = await databaseManager.call(method, ...args);
} catch (error) {
response.error = error.toString();
response.error = (error as Error).toString();
}
return response;
@ -179,7 +179,7 @@ export default function registerIpcMainActionListeners(main: Main) {
try {
response.data = await databaseManager.callBespoke(method, ...args);
} catch (error) {
response.error = error.toString();
response.error = (error as Error).toString();
}
return response;

View File

@ -26,6 +26,7 @@ export type AccountRootType =
| 'Income'
| 'Expense';
export interface COARootAccount {
rootType: AccountRootType;
[key: string]: COAChildAccount | AccountRootType;

View File

@ -17,7 +17,7 @@ import { SetupWizard } from './baseModels/SetupWizard/SetupWizard';
import { Tax } from './baseModels/Tax/Tax';
import { TaxSummary } from './baseModels/TaxSummary/TaxSummary';
export default {
export const models = {
Account,
AccountingLedgerEntry,
AccountingSettings,

View File

@ -1,4 +1,4 @@
import frappe from 'fyo';
import fyo from 'fyo';
export default class AccountsReceivablePayable {
async run(reportType, { date }) {
@ -65,7 +65,7 @@ async function getReceivablePayable({ reportType = 'Receivable', date }) {
// helpers
async function getVouchers() {
return await frappe.db.getAll({
return await fyo.db.getAll({
doctype: referenceType,
fields: ['name', 'date'],
filters: {
@ -140,7 +140,7 @@ async function getReceivablePayable({ reportType = 'Receivable', date }) {
const partyType = reportType === 'Receivable' ? 'customer' : 'supplier';
const partyList = (
await frappe.db.getAll({
await fyo.db.getAll({
doctype: 'Party',
filters: {
[partyType]: 1,
@ -148,7 +148,7 @@ async function getReceivablePayable({ reportType = 'Receivable', date }) {
})
).map((d) => d.name);
return await frappe.db.getAll({
return await fyo.db.getAll({
doctype: 'AccountingLedgerEntry',
fields: [
'name',

View File

@ -1,9 +1,13 @@
import { Fyo } from 'fyo';
import { unique } from 'fyo/utils';
import { getData } from '../FinancialStatements/FinancialStatements';
import { FinancialStatements } from 'reports/FinancialStatements/financialStatements';
import { FinancialStatementOptions } from 'reports/types';
class BalanceSheet {
async run({ fromDate, toDate, periodicity }) {
let asset = await getData({
async run(options: FinancialStatementOptions, fyo: Fyo) {
const { fromDate, toDate, periodicity } = options;
const fs = new FinancialStatements(fyo);
const asset = await fs.getData({
rootType: 'Asset',
balanceMustBe: 'Debit',
fromDate,
@ -12,7 +16,7 @@ class BalanceSheet {
accumulateValues: true,
});
let liability = await getData({
const liability = await fs.getData({
rootType: 'Liability',
balanceMustBe: 'Credit',
fromDate,
@ -21,7 +25,7 @@ class BalanceSheet {
accumulateValues: true,
});
let equity = await getData({
const equity = await fs.getData({
rootType: 'Equity',
balanceMustBe: 'Credit',
fromDate,

View File

@ -1,5 +1,6 @@
import frappe, { t } from 'fyo';
import { t } from 'fyo';
import getCommonExportActions from '../commonExporter';
import { fyo } from 'src/initFyo';
const periodicityMap = {
Monthly: t`Monthly`,
@ -19,7 +20,7 @@ export default {
label: t`To Date`,
required: 1,
default: async () => {
return (await frappe.getSingle('AccountingSettings')).fiscalYearEnd;
return (await fyo.doc.getSingle('AccountingSettings')).fiscalYearEnd;
},
},
{

View File

@ -1,4 +1,4 @@
import frappe from 'fyo';
import { fyo } from 'src/initFyo'
class BankReconciliation {
async run(params) {
@ -15,7 +15,7 @@ class BankReconciliation {
filters.paymentMethod = ['in', ['Cheque', 'Transfer']];
let data = await frappe.db.getAll({
let data = await fyo.db.getAll({
doctype: 'Payment',
fields: [
'date',
@ -31,7 +31,7 @@ class BankReconciliation {
});
for (var i = 0; i < data.length; i++) {
let ledger = await frappe.db.getAll({
let ledger = await fyo.db.getAll({
doctype: 'AccountingLedgerEntry',
fields: ['date', 'referenceType', 'referenceName', 'debit', 'credit'],
filters: {

View File

@ -1,5 +1,5 @@
import csv2json from 'csvjson-csv2json';
import frappe from 'fyo';
import { fyo } from 'src/initFyo';
import ReconciliationValidation from '../../src/components/ReconciliationValidation';
export const fileImportHandler = (file, report) => {
@ -42,7 +42,7 @@ export const findMatchingReferences = async (json, report) => {
const references = json.map((row) => {
return row[referenceField];
});
const payments = await frappe.db.getAll({
const payments = await fyo.db.getAll({
doctype: 'Payment',
fields: ['*'],
filters: {
@ -60,11 +60,11 @@ export const findMatchingReferences = async (json, report) => {
});
const normalizedEntries = entries.map((entry) => {
return {
'Posting Date': frappe.format(entry.date, 'Date'),
'Posting Date': fyo.format(entry.date, 'Date'),
'Payment Entry': entry.name,
'Ref/Cheq. ID': entry[referenceField],
'Cr/Dr':
frappe.parseNumber(entry[debitField]) > 0
fyo.parseNumber(entry[debitField]) > 0
? entry[debitField] + ' Dr.'
: entry[creditField] + ' Cr.',
'Clearance Date': entry[clearanceDateField],

View File

@ -1,40 +0,0 @@
import frappe from 'fyo';
import { DateTime } from 'luxon';
import {
getFiscalYear,
getPeriodList,
} from '../FinancialStatements/FinancialStatements';
class Cashflow {
async run({ fromDate, toDate, periodicity }) {
const res = await frappe.db.getCashflow(fromDate, toDate);
let fiscalYear = await getFiscalYear();
let periodList = getPeriodList(fromDate, toDate, periodicity, fiscalYear);
let data = periodList.map((periodKey) => {
let monthYear = this.getMonthYear(periodKey, 'MMM yyyy');
let cashflowForPeriod = res.find((d) => d['month-year'] === monthYear);
if (cashflowForPeriod) {
cashflowForPeriod.periodKey = periodKey;
return cashflowForPeriod;
}
return {
inflow: 0,
outflow: 0,
periodKey,
'month-year': monthYear,
};
});
return {
data,
periodList,
};
}
getMonthYear(periodKey, format) {
return DateTime.fromFormat(periodKey, format).toFormat('MM-yyyy');
}
}
export default Cashflow;

View File

@ -0,0 +1,52 @@
import { Fyo } from 'fyo';
import { DateTime } from 'luxon';
import {
getFiscalYear,
getPeriodList,
} from 'reports/FinancialStatements/financialStatements';
import { FinancialStatementOptions } from 'reports/types';
class Cashflow {
fyo: Fyo;
constructor(fyo: Fyo) {
this.fyo = fyo;
}
async run(options: FinancialStatementOptions) {
const { fromDate, toDate, periodicity } = options;
const res = await this.fyo.db.getCashflow(fromDate, toDate);
const fiscalYear = await getFiscalYear(this.fyo);
const periodList = getPeriodList(
fromDate,
toDate,
periodicity!,
fiscalYear
);
const data = periodList.map((periodKey) => {
const monthYear = this.getMonthYear(periodKey, 'MMM yyyy');
const cashflowForPeriod = res.find((d) => d['month-year'] === monthYear);
if (cashflowForPeriod) {
return { ...cashflowForPeriod, periodKey };
}
return {
inflow: 0,
outflow: 0,
periodKey,
'month-year': monthYear,
};
});
return {
data,
periodList,
};
}
getMonthYear(periodKey: string, format: string) {
return DateTime.fromFormat(periodKey, format).toFormat('MM-yyyy');
}
}
export default Cashflow;

View File

@ -1,334 +0,0 @@
import frappe from 'fyo';
import { DateTime } from 'luxon';
import { convertPesaValuesToFloat } from '../../src/utils';
export async function getData({
rootType,
balanceMustBe = 'Debit',
fromDate,
toDate,
periodicity = 'Monthly',
accumulateValues = false,
}) {
let accounts = await getAccounts(rootType);
let fiscalYear = await getFiscalYear();
let ledgerEntries = await getLedgerEntries(fromDate, toDate, accounts);
let periodList = getPeriodList(fromDate, toDate, periodicity, fiscalYear);
for (let account of accounts) {
const entries = ledgerEntries.filter(
(entry) => entry.account === account.name
);
for (let entry of entries) {
let periodKey = getPeriodKey(entry.date, periodicity, fiscalYear);
if (!account[periodKey]) {
account[periodKey] = frappe.pesa(0.0);
}
const multiplier = balanceMustBe === 'Debit' ? 1 : -1;
const value = entry.debit.sub(entry.credit).mul(multiplier);
account[periodKey] = value.add(account[periodKey]);
}
}
if (accumulateValues) {
periodList.forEach((periodKey, i) => {
if (i === 0) return;
const previousPeriodKey = periodList[i - 1];
for (let account of accounts) {
if (!account[periodKey]) {
account[periodKey] = frappe.pesa(0.0);
}
account[periodKey] = account[periodKey].add(
account[previousPeriodKey] ?? 0
);
}
});
}
// calculate totalRow
let totalRow = {
account: `Total ${rootType} (${balanceMustBe})`,
};
periodList.forEach((periodKey) => {
if (!totalRow[periodKey]) {
totalRow[periodKey] = frappe.pesa(0.0);
}
for (let account of accounts) {
totalRow[periodKey] = totalRow[periodKey].add(account[periodKey] ?? 0.0);
}
});
convertPesaValuesToFloat(totalRow);
accounts.forEach(convertPesaValuesToFloat);
return { accounts, totalRow, periodList };
}
export async function getTrialBalance({ rootType, fromDate, toDate }) {
let accounts = await getAccounts(rootType);
let ledgerEntries = await getLedgerEntries(null, toDate, accounts);
for (let account of accounts) {
const accountEntries = ledgerEntries.filter(
(entry) => entry.account === account.name
);
// opening
const beforePeriodEntries = accountEntries.filter(
(entry) => entry.date < fromDate
);
account.opening = beforePeriodEntries.reduce(
(acc, entry) => acc.add(entry.debit).sub(entry.credit),
frappe.pesa(0)
);
if (account.opening.gte(0)) {
account.openingDebit = account.opening;
account.openingCredit = frappe.pesa(0);
} else {
account.openingCredit = account.opening.neg();
account.openingDebit = frappe.pesa(0);
}
// debit / credit
const periodEntries = accountEntries.filter(
(entry) => entry.date >= fromDate && entry.date < toDate
);
account.debit = periodEntries.reduce(
(acc, entry) => acc.add(entry.debit),
frappe.pesa(0)
);
account.credit = periodEntries.reduce(
(acc, entry) => acc.add(entry.credit),
frappe.pesa(0)
);
// closing
account.closing = account.opening.add(account.debit).sub(account.credit);
if (account.closing.gte(0)) {
account.closingDebit = account.closing;
account.closingCredit = frappe.pesa(0);
} else {
account.closingCredit = account.closing.neg();
account.closingDebit = frappe.pesa(0);
}
if (account.debit.neq(0) || account.credit.neq(0)) {
setParentEntry(account, account.parentAccount);
}
}
function setParentEntry(leafAccount, parentName) {
for (let acc of accounts) {
if (acc.name === parentName) {
acc.debit = acc.debit.add(leafAccount.debit);
acc.credit = acc.credit.add(leafAccount.credit);
acc.closing = acc.opening.add(acc.debit).sub(acc.credit);
if (acc.closing.gte(0)) {
acc.closingDebit = acc.closing;
} else {
acc.closingCredit = acc.closing.neg();
}
if (acc.parentAccount) {
setParentEntry(leafAccount, acc.parentAccount);
} else {
return;
}
}
}
}
accounts.forEach(convertPesaValuesToFloat);
return accounts;
}
export function getPeriodList(fromDate, toDate, periodicity, fiscalYear) {
if (!fromDate) {
fromDate = fiscalYear.start;
}
let monthsToAdd = {
Monthly: 1,
Quarterly: 3,
'Half Yearly': 6,
Yearly: 12,
}[periodicity];
let startDate = DateTime.fromISO(fromDate).startOf('month');
let endDate = DateTime.fromISO(toDate).endOf('month');
let curDate = startDate;
let out = [];
while (curDate <= endDate) {
out.push(getPeriodKey(curDate, periodicity, fiscalYear));
curDate = curDate.plus({ months: monthsToAdd });
}
return out;
}
function getPeriodKey(date, periodicity, fiscalYear) {
let key;
let { start, end, quarters, isSplit } = fiscalYear;
let dateObj = DateTime.fromISO(date);
let { month, quarter, year } = dateObj;
let fisacalStart = DateTime.fromISO(start);
let fisacalEnd = DateTime.fromISO(end);
let getKey = {
Monthly: () => `${dateObj.monthShort} ${year}`,
Quarterly: () => {
const key =
month < fisacalStart.month
? `${year - 1} - ${year}`
: `${year} - ${year + 1}`;
let strYear = isSplit ? key : `${year}`;
return {
1: `Q1 ${strYear}`,
2: `Q2 ${strYear}`,
3: `Q3 ${strYear}`,
4: `Q4 ${strYear}`,
}[quarters[month - 1]];
},
'Half Yearly': () => {
const key =
month < fisacalStart.month
? `${year - 1} - ${year}`
: `${year} - ${year + 1}`;
let strYear = isSplit ? key : `${year}`;
return {
1: `1st Half ${strYear}`,
2: `1st Half ${strYear}`,
3: `2nd Half ${strYear}`,
4: `2nd Half ${strYear}`,
}[quarters[month - 1]];
},
Yearly: () => {
const key =
month < fisacalStart.month
? `${year - 1} - ${year}`
: `${year} - ${year + 1}`;
let strYear = isSplit ? key : `${year}`;
return `FY ${strYear}`;
},
}[periodicity];
return getKey();
}
function setIndentLevel(accounts, parentAccount, level) {
if (!parentAccount) {
// root
parentAccount = null;
level = 0;
}
accounts.forEach((account) => {
if (
account.parentAccount === parentAccount &&
account.indent === undefined
) {
account.indent = level;
setIndentLevel(accounts, account.name, level + 1);
}
});
return accounts;
}
function sortAccounts(accounts) {
let out = [];
let pushed = {};
pushToOut(null);
function pushToOut(parentAccount) {
accounts.forEach((account) => {
if (account.parentAccount === parentAccount && !pushed[account.name]) {
out.push(account);
pushed[account.name] = 1;
pushToOut(account.name);
}
});
}
return out;
}
async function getLedgerEntries(fromDate, toDate, accounts) {
const dateFilter = () => {
const before = ['<=', toDate];
const after = ['>=', fromDate];
if (fromDate) {
return [...after, ...before];
}
return before;
};
const ledgerEntries = await frappe.db.getAll({
doctype: 'AccountingLedgerEntry',
fields: ['account', 'debit', 'credit', 'date'],
filters: {
account: ['in', accounts.map((d) => d.name)],
date: dateFilter(),
},
});
return ledgerEntries;
}
async function getAccounts(rootType) {
let accounts = await frappe.db.getAll({
doctype: 'Account',
fields: ['name', 'parentAccount', 'isGroup'],
filters: {
rootType,
},
});
accounts = setIndentLevel(accounts);
accounts = sortAccounts(accounts);
accounts.forEach((account) => {
account.account = account.name;
});
return accounts;
}
export async function getFiscalYear() {
let { fiscalYearStart, fiscalYearEnd } = await frappe.getSingle(
'AccountingSettings'
);
//right now quaters received from luxon lib is fixed to Jan as starting quarter
//moving the financial quarters, according to of start of fiscal year month
let quarters = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4];
let start = DateTime.fromISO(fiscalYearStart);
quarters.unshift(...quarters.splice(13 - start.month, 11));
//check if fiscal year ends in next year
let end = DateTime.fromISO(fiscalYearEnd);
let isFiscalSplit = start.year - end.year;
return {
start: fiscalYearStart,
end: fiscalYearEnd,
quarters: quarters,
isSplit: isFiscalSplit,
};
}
export default {
getData,
getTrialBalance,
getPeriodList,
};

View File

@ -0,0 +1,426 @@
import { Fyo } from 'fyo';
import { DocValueMap } from 'fyo/core/types';
import { DateTime } from 'luxon';
import { AccountRootType } from 'models/baseModels/Account/types';
import Money from 'pesa/dist/types/src/money';
import {
BalanceType,
FinancialStatementOptions,
Periodicity,
} from 'reports/types';
import { convertPesaValuesToFloat } from 'src/utils';
interface FiscalYear {
start: string;
end: string;
quarters: number[];
isSplit: number;
}
interface AccountInfo extends DocValueMap {
name: string;
parentAccount: string;
isGroup: boolean;
account?: string;
indent?: number;
}
interface LedgerInfo extends DocValueMap {
account: string;
debit: Money;
credit: Money;
date: string;
}
export class FinancialStatements {
fyo: Fyo;
constructor(fyo: Fyo) {
this.fyo = fyo;
}
async getData(options: FinancialStatementOptions) {
const rootType = options.rootType;
const balanceMustBe = options.balanceMustBe ?? 'Debit';
const fromDate = options.fromDate;
const toDate = options.toDate;
const periodicity = options.periodicity ?? 'Monthly';
const accumulateValues = options.accumulateValues ?? false;
const accounts = await this.getAccounts(rootType);
const fiscalYear = await getFiscalYear(this.fyo);
const ledgerEntries = await this.getLedgerEntries(
fromDate,
toDate,
accounts
);
const periodList = getPeriodList(fromDate, toDate, periodicity, fiscalYear);
this.setPeriodAmounts(
accounts,
ledgerEntries,
periodicity,
fiscalYear,
balanceMustBe
);
if (accumulateValues) {
this.accumulateValues(accounts, periodList);
}
const totalRow = this.getTotalRow(
rootType,
balanceMustBe,
periodList,
accounts
);
accounts.forEach(convertPesaValuesToFloat);
return { accounts, totalRow, periodList };
}
setPeriodAmounts(
accounts: AccountInfo[],
ledgerEntries: LedgerInfo[],
periodicity: Periodicity,
fiscalYear: FiscalYear,
balanceMustBe: BalanceType
) {
for (const account of accounts) {
const entries = ledgerEntries.filter(
(entry) => entry.account === account.name
);
for (const entry of entries) {
const periodKey = getPeriodKey(entry.date, periodicity, fiscalYear);
if (account[periodKey] === undefined) {
account[periodKey] = this.fyo.pesa(0.0);
}
const multiplier = balanceMustBe === 'Debit' ? 1 : -1;
const value = entry.debit.sub(entry.credit).mul(multiplier);
account[periodKey] = value.add(account[periodKey] as Money);
}
}
}
getTotalRow(
rootType: AccountRootType,
balanceMustBe: BalanceType,
periodList: string[],
accounts: AccountInfo[]
) {
const totalRow: DocValueMap = {
account: `Total ${rootType} (${balanceMustBe})`,
};
periodList.forEach((periodKey) => {
if (totalRow[periodKey] === undefined) {
totalRow[periodKey] = this.fyo.pesa(0.0);
}
for (const account of accounts) {
totalRow[periodKey] = (totalRow[periodKey] as Money).add(
(account[periodKey] as Money) ?? 0.0
);
}
});
convertPesaValuesToFloat(totalRow);
return totalRow;
}
async accumulateValues(accounts: AccountInfo[], periodList: string[]) {
periodList.forEach((periodKey, i) => {
if (i === 0) {
return;
}
const previousPeriodKey = periodList[i - 1];
for (const account of accounts) {
if (!account[periodKey]) {
account[periodKey] = this.fyo.pesa(0.0);
}
account[periodKey] = (account[periodKey] as Money).add(
(account[previousPeriodKey] as Money | undefined) ?? 0
);
}
});
}
async getAccounts(rootType: AccountRootType) {
let accounts = (await this.fyo.db.getAll('Account', {
fields: ['name', 'parentAccount', 'isGroup'],
filters: {
rootType,
},
})) as AccountInfo[];
accounts = setIndentLevel(accounts);
accounts = sortAccounts(accounts);
accounts.forEach((account) => {
account.account = account.name;
});
return accounts;
}
async getLedgerEntries(
fromDate: string | null,
toDate: string,
accounts: AccountInfo[]
) {
const accountFilter = ['in', accounts.map((d) => d.name)];
let dateFilter: string[] = ['<=', toDate];
if (fromDate) {
dateFilter = ['>=', fromDate, '<=', toDate];
}
const ledgerEntries = (await this.fyo.db.getAll('AccountingLedgerEntry', {
fields: ['account', 'debit', 'credit', 'date'],
filters: {
account: accountFilter,
date: dateFilter,
},
})) as LedgerInfo[];
return ledgerEntries;
}
async getTrialBalance(options: FinancialStatementOptions) {
const { rootType, fromDate, toDate } = options;
const accounts = await this.getAccounts(rootType);
const ledgerEntries = await this.getLedgerEntries(null, toDate, accounts);
for (const account of accounts) {
const accountEntries = ledgerEntries.filter(
(entry) => entry.account === account.name
);
// opening
const beforePeriodEntries = accountEntries.filter(
(entry) => entry.date < fromDate
);
account.opening = beforePeriodEntries.reduce(
(acc, entry) => acc.add(entry.debit).sub(entry.credit),
this.fyo.pesa(0)
);
if (account.opening.gte(0)) {
account.openingDebit = account.opening;
account.openingCredit = this.fyo.pesa(0);
} else {
account.openingCredit = account.opening.neg();
account.openingDebit = this.fyo.pesa(0);
}
// debit / credit
const periodEntries = accountEntries.filter(
(entry) => entry.date >= fromDate && entry.date < toDate
);
account.debit = periodEntries.reduce(
(acc, entry) => acc.add(entry.debit),
this.fyo.pesa(0)
);
account.credit = periodEntries.reduce(
(acc, entry) => acc.add(entry.credit),
this.fyo.pesa(0)
);
// closing
account.closing = account.opening.add(account.debit).sub(account.credit);
if (account.closing.gte(0)) {
account.closingDebit = account.closing;
account.closingCredit = this.fyo.pesa(0);
} else {
account.closingCredit = account.closing.neg();
account.closingDebit = this.fyo.pesa(0);
}
if (account.debit.neq(0) || account.credit.neq(0)) {
setParentEntry(account, account.parentAccount);
}
}
function setParentEntry(leafAccount: AccountInfo, parentName: string) {
for (const acc of accounts) {
if (acc.name === parentName) {
acc.debit = (acc.debit as Money).add(leafAccount.debit as Money);
acc.credit = (acc.credit as Money).add(leafAccount.credit as Money);
acc.closing = (acc.opening as Money).add(acc.debit).sub(acc.credit);
if (acc.closing.gte(0)) {
acc.closingDebit = acc.closing;
} else {
acc.closingCredit = acc.closing.neg();
}
if (acc.parentAccount) {
setParentEntry(leafAccount, acc.parentAccount);
} else {
return;
}
}
}
}
accounts.forEach(convertPesaValuesToFloat);
return accounts;
}
}
function setIndentLevel(
accounts: AccountInfo[],
parentAccount?: string | null,
level?: number
): AccountInfo[] {
if (parentAccount === undefined) {
parentAccount = null;
level = 0;
}
accounts.forEach((account) => {
if (
account.parentAccount === parentAccount &&
account.indent === undefined
) {
account.indent = level;
setIndentLevel(accounts, account.name, (level ?? 0) + 1);
}
});
return accounts;
}
function sortAccounts(accounts: AccountInfo[]) {
const out: AccountInfo[] = [];
const pushed: Record<string, boolean> = {};
pushToOut(null);
function pushToOut(parentAccount: string | null) {
accounts.forEach((account) => {
if (pushed[account.name] && account.parentAccount !== parentAccount) {
return;
}
out.push(account);
pushed[account.name] = true;
pushToOut(account.name);
});
}
return out;
}
export function getPeriodList(
fromDate: string,
toDate: string,
periodicity: Periodicity,
fiscalYear: FiscalYear
) {
if (!fromDate) {
fromDate = fiscalYear.start;
}
const monthsToAdd = {
Monthly: 1,
Quarterly: 3,
'Half Yearly': 6,
Yearly: 12,
}[periodicity];
const startDate = DateTime.fromISO(fromDate).startOf('month');
const endDate = DateTime.fromISO(toDate).endOf('month');
let curDate = startDate;
const periodKeyList: string[] = [];
while (curDate <= endDate) {
const periodKey = getPeriodKey(curDate, periodicity, fiscalYear);
periodKeyList.push(periodKey);
curDate = curDate.plus({ months: monthsToAdd });
}
return periodKeyList;
}
function getPeriodKey(
dateObj: DateTime | string,
periodicity: Periodicity,
fiscalYear: FiscalYear
) {
if (typeof dateObj === 'string') {
dateObj = DateTime.fromISO(dateObj);
}
const { start, quarters, isSplit } = fiscalYear;
const { month, year } = dateObj;
const fisacalStart = DateTime.fromISO(start);
if (periodicity === 'Monthly') {
return `${dateObj.monthShort} ${year}`;
}
if (periodicity === 'Quarterly') {
const key =
month < fisacalStart.month
? `${year - 1} - ${year}`
: `${year} - ${year + 1}`;
const strYear = isSplit ? key : `${year}`;
return {
1: `Q1 ${strYear}`,
2: `Q2 ${strYear}`,
3: `Q3 ${strYear}`,
4: `Q4 ${strYear}`,
}[quarters[month - 1]] as string;
}
if (periodicity === 'Half Yearly') {
const key =
month < fisacalStart.month
? `${year - 1} - ${year}`
: `${year} - ${year + 1}`;
const strYear = isSplit ? key : `${year}`;
return {
1: `1st Half ${strYear}`,
2: `1st Half ${strYear}`,
3: `2nd Half ${strYear}`,
4: `2nd Half ${strYear}`,
}[quarters[month - 1]] as string;
}
const key =
month < fisacalStart.month
? `${year - 1} - ${year}`
: `${year} - ${year + 1}`;
const strYear = isSplit ? key : `${year}`;
return `FY ${strYear}`;
}
export async function getFiscalYear(fyo: Fyo): Promise<FiscalYear> {
const accountingSettings = await fyo.doc.getSingle('AccountingSettings');
const fiscalYearStart = accountingSettings.fiscalYearStart as string;
const fiscalYearEnd = accountingSettings.fiscalYearEnd as string;
//right now quaters received from luxon lib is fixed to Jan as starting quarter
//moving the financial quarters, according to of start of fiscal year month
const quarters = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4];
const start = DateTime.fromISO(fiscalYearStart);
quarters.unshift(...quarters.splice(13 - start.month, 11));
//check if fiscal year ends in next year
const end = DateTime.fromISO(fiscalYearEnd);
const isFiscalSplit = start.year - end.year;
return {
start: fiscalYearStart,
end: fiscalYearEnd,
quarters: quarters,
isSplit: isFiscalSplit,
};
}

View File

@ -1,4 +1,4 @@
import frappe from 'fyo';
import { fyo } from 'src/initFyo';
class GeneralLedger {
async run(params) {
@ -15,7 +15,7 @@ class GeneralLedger {
}
let data = (
await frappe.db.getAll({
await fyo.db.getAll({
doctype: 'AccountingLedgerEntry',
fields: [
'date',
@ -40,6 +40,7 @@ class GeneralLedger {
return this.appendOpeningEntry(data);
}
appendOpeningEntry(data) {
let glEntries = [];
let balance = 0,

View File

@ -1,4 +1,4 @@
import frappe from 'fyo';
import { fyo } from 'src/initFyo';
import { stateCodeMap } from '../../accounting/gst';
import { convertPesaValuesToFloat } from '../../src/utils';
@ -7,7 +7,7 @@ class BaseGSTR {
if (['GSTR-1', 'GSTR-2'].includes(gstrType)) {
const place = filters.place;
delete filters.place;
let entries = await frappe.db.getAll({
let entries = await fyo.db.getAll({
doctype: gstrType === 'GSTR-1' ? 'SalesInvoice' : 'PurchaseInvoice',
filters,
});
@ -39,21 +39,18 @@ class BaseGSTR {
}
async getRow(ledgerEntry) {
ledgerEntry = await frappe.doc.getDoc(
ledgerEntry.doctype,
ledgerEntry.name
);
ledgerEntry = await fyo.doc.getDoc(ledgerEntry.doctype, ledgerEntry.name);
const row = {};
const { gstin } = frappe.AccountingSettings;
const { gstin } = fyo.AccountingSettings;
let party = await frappe.doc.getDoc(
let party = await fyo.doc.getDoc(
'Party',
ledgerEntry.customer || ledgerEntry.supplier
);
if (party.address) {
let addressDetails = await frappe.doc.getDoc('Address', party.address);
let addressDetails = await fyo.doc.getDoc('Address', party.address);
row.place = addressDetails.pos || '';
}

View File

@ -1,83 +0,0 @@
import { unique } from 'fyo/utils';
import { getData } from '../FinancialStatements/FinancialStatements';
class ProfitAndLoss {
async run({ fromDate, toDate, periodicity }) {
let income = await getData({
rootType: 'Income',
balanceMustBe: 'Credit',
fromDate,
toDate,
periodicity,
});
let expense = await getData({
rootType: 'Expense',
balanceMustBe: 'Debit',
fromDate,
toDate,
periodicity,
});
let incomeTotalRow = income.totalRow;
incomeTotalRow.account = {
template: `<span class="font-semibold">${income.totalRow.account}</span>`,
};
let expenseTotalRow = expense.totalRow;
expenseTotalRow.account = {
template: `<span class="font-semibold">${expense.totalRow.account}</span>`,
};
let rows = [
...income.accounts,
incomeTotalRow,
{
account: {
template: '<span>&nbsp;</span>',
},
isGroup: 1,
},
...expense.accounts,
expenseTotalRow,
{
account: {
template: '<span>&nbsp;</span>',
},
isGroup: 1,
},
];
rows = rows.map((row) => {
if (row.indent === 0) {
row.account = {
template: `<span class="font-semibold">${row.account}</span>`,
};
}
return row;
});
const columns = unique([...income.periodList, ...expense.periodList]);
let profitRow = {
account: 'Total Profit',
};
for (let column of columns) {
profitRow[column] =
(income.totalRow[column] || 0.0) - (expense.totalRow[column] || 0.0);
rows.forEach((row) => {
if (!row.isGroup) {
row[column] = row[column] || 0.0;
}
});
}
rows.push(profitRow);
return { rows, columns };
}
}
export default ProfitAndLoss;

View File

@ -0,0 +1,107 @@
import { Fyo } from 'fyo';
import { unique } from 'fyo/utils';
import { FinancialStatements } from 'reports/FinancialStatements/financialStatements';
import { FinancialStatementOptions } from 'reports/types';
interface Row {
indent?: number;
account: string | { template: string };
isGroup?: boolean;
[key: string]: unknown;
}
export default class ProfitAndLoss {
fyo: Fyo;
constructor(fyo: Fyo) {
this.fyo = fyo;
}
async run(options: FinancialStatementOptions) {
const { fromDate, toDate, periodicity } = options;
const fs = new FinancialStatements(this.fyo);
const income = await fs.getData({
rootType: 'Income',
balanceMustBe: 'Credit',
fromDate,
toDate,
periodicity,
});
const expense = await fs.getData({
rootType: 'Expense',
balanceMustBe: 'Debit',
fromDate,
toDate,
periodicity,
});
const incomeAccount = income.totalRow.account as string;
const incomeTotalRow = {
...income.totalRow,
account: {
template: `<span class="font-semibold">${incomeAccount}</span>`,
},
};
const expenseAccount = expense.totalRow.account as string;
const expenseTotalRow = {
...expense.totalRow,
account: {
template: `<span class="font-semibold">${expenseAccount}</span>`,
},
};
let rows = [
...income.accounts,
incomeTotalRow,
{
account: {
template: '<span>&nbsp;</span>',
},
isGroup: true,
},
...expense.accounts,
expenseTotalRow,
{
account: {
template: '<span>&nbsp;</span>',
},
isGroup: true,
},
] as Row[];
rows = rows.map((row) => {
if (row.indent === 0) {
row.account = {
template: `<span class="font-semibold">${row.account}</span>`,
};
}
return row;
});
const columns = unique([...income.periodList, ...expense.periodList]);
const profitRow: Row = {
account: 'Total Profit',
};
for (const column of columns) {
const incomeAmount =
(income.totalRow[column] as number | undefined) ?? 0.0;
const expenseAmount =
(expense.totalRow[column] as number | undefined) ?? 0.0;
profitRow[column] = incomeAmount - expenseAmount;
rows.forEach((row) => {
if (!row.isGroup) {
row[column] = row[column] || 0.0;
}
});
}
rows.push(profitRow);
return { rows, columns };
}
}

View File

@ -1,4 +1,5 @@
import frappe, { t } from 'fyo';
import { t } from 'fyo';
import { fyo } from 'src/initFyo';
import getCommonExportActions from '../commonExporter';
const title = t`Profit and Loss`;
@ -22,7 +23,7 @@ export default {
label: t`From Date`,
required: 1,
default: async () => {
return (await frappe.getSingle('AccountingSettings')).fiscalYearStart;
return (await fyo.getSingle('AccountingSettings')).fiscalYearStart;
},
},
{
@ -33,7 +34,7 @@ export default {
label: t`To Date`,
required: 1,
default: async () => {
return (await frappe.getSingle('AccountingSettings')).fiscalYearEnd;
return (await fyo.getSingle('AccountingSettings')).fiscalYearEnd;
},
},
{

View File

@ -1,4 +1,4 @@
import frappe from 'fyo';
import { fyo } from 'src/initFyo';
class PurchaseRegister {
async run({ fromDate, toDate, supplier }) {
@ -18,7 +18,7 @@ class PurchaseRegister {
}
filters.submitted = 1;
const bills = await frappe.db.getAll({
const bills = await fyo.db.getAll({
doctype: 'PurchaseInvoice',
fields: ['name', 'date', 'supplier', 'account', 'netTotal', 'grandTotal'],
filters,
@ -28,7 +28,7 @@ class PurchaseRegister {
const billNames = bills.map((d) => d.name);
const taxes = await frappe.db.getAll({
const taxes = await fyo.db.getAll({
doctype: 'TaxSummary',
fields: ['parent', 'amount'],
filters: {

View File

@ -1,4 +1,4 @@
import frappe from 'fyo';
import { fyo } from 'src/initFyo';
class SalesRegister {
async run({ fromDate, toDate, customer }) {
@ -17,7 +17,7 @@ class SalesRegister {
filters.date = ['<=', toDate];
}
const invoices = await frappe.db.getAll({
const invoices = await fyo.db.getAll({
doctype: 'SalesInvoice',
fields: ['name', 'date', 'customer', 'account', 'netTotal', 'grandTotal'],
filters: filters,
@ -27,7 +27,7 @@ class SalesRegister {
const invoiceNames = invoices.map((d) => d.name);
const taxes = await frappe.db.getAll({
const taxes = await fyo.db.getAll({
doctype: 'TaxSummary',
fields: ['parent', 'amount'],
filters: {

View File

@ -1,4 +1,4 @@
import { getTrialBalance } from '../FinancialStatements/FinancialStatements';
import { getTrialBalance } from '../helpers/financialStatements';
export default class TrialBalance {
async run({ fromDate, toDate }) {

View File

@ -1,4 +1,5 @@
import frappe, { t } from 'fyo';
import { t } from 'fyo';
import { fyo } from 'src/initFyo';
import getCommonExportActions from '../commonExporter';
const title = t`Trial Balance`;
@ -16,7 +17,7 @@ export default {
placeholder: t`From Date`,
required: 1,
default: async () => {
return (await frappe.getSingle('AccountingSettings')).fiscalYearStart;
return (await fyo.getSingle('AccountingSettings')).fiscalYearStart;
},
},
{
@ -27,7 +28,7 @@ export default {
label: t`To Date`,
required: 1,
default: async () => {
return (await frappe.getSingle('AccountingSettings')).fiscalYearEnd;
return (await fyo.getSingle('AccountingSettings')).fiscalYearEnd;
},
},
],

161
reports/commonExporter.ts Normal file
View File

@ -0,0 +1,161 @@
import { DocValue, DocValueMap } from 'fyo/core/types';
import { Verb } from 'fyo/telemetry/types';
import { Field } from 'schemas/types';
import { fyo } from 'src/initFyo';
import { getSavePath, saveData, showExportInFolder } from 'src/utils/ipcCalls';
interface JSONExport {
columns: { fieldname: string; label: string }[];
rows: Record<string, DocValue>[];
filters: Record<string, string>;
timestamp: string;
reportName: string;
softwareName: string;
softwareVersion: string;
}
type GetReportData = () => {
rows: DocValueMap[];
columns: Field[];
filters: Record<string, string>;
};
type TemplateObject = { template: string };
function templateToInnerText(innerHTML: string): string {
const temp = document.createElement('template');
temp.innerHTML = innerHTML.trim();
// @ts-ignore
return temp.content.firstChild!.innerText;
}
function deObjectify(value: TemplateObject | DocValue) {
if (typeof value !== 'object') return value;
if (value === null) return '';
const innerHTML = (value as TemplateObject).template;
if (!innerHTML) return '';
return templateToInnerText(innerHTML);
}
function csvFormat(value: TemplateObject | DocValue): string {
if (typeof value === 'string') {
return `"${value}"`;
} else if (value === null) {
return '';
} else if (typeof value === 'object') {
const innerHTML = (value as TemplateObject).template;
if (!innerHTML) return '';
return csvFormat(deObjectify(value as TemplateObject));
}
return String(value);
}
export async function exportCsv(
rows: DocValueMap[],
columns: Field[],
filePath: string
) {
const fieldnames = columns.map(({ fieldname }) => fieldname);
const labels = columns.map(({ label }) => csvFormat(label));
const csvRows = [
labels.join(','),
...rows.map((row) =>
fieldnames.map((f) => csvFormat(row[f] as DocValue)).join(',')
),
];
saveExportData(csvRows.join('\n'), filePath);
}
async function exportJson(
rows: DocValueMap[],
columns: Field[],
filePath: string,
filters: Record<string, string>,
reportName: string
) {
const exportObject: JSONExport = {
columns: [],
rows: [],
filters: {},
timestamp: '',
reportName: '',
softwareName: '',
softwareVersion: '',
};
const fieldnames = columns.map(({ fieldname }) => fieldname);
exportObject.columns = columns.map(({ fieldname, label }) => ({
fieldname,
label,
}));
exportObject.rows = rows.map((row) =>
fieldnames.reduce((acc, f) => {
const value = row[f];
if (value === undefined) {
acc[f] = '';
} else {
acc[f] = deObjectify(value as DocValue | TemplateObject);
}
return acc;
}, {} as Record<string, DocValue>)
);
exportObject.filters = Object.keys(filters)
.filter((name) => filters[name] !== null && filters[name] !== undefined)
.reduce((acc, name) => {
acc[name] = filters[name];
return acc;
}, {} as Record<string, string>);
exportObject.timestamp = new Date().toISOString();
exportObject.reportName = reportName;
exportObject.softwareName = 'Frappe Books';
exportObject.softwareVersion = fyo.store.appVersion;
await saveExportData(JSON.stringify(exportObject), filePath);
}
async function exportReport(
extention: string,
reportName: string,
getReportData: GetReportData
) {
const { rows, columns, filters } = getReportData();
const { filePath, canceled } = await getSavePath(reportName, extention);
if (canceled || !filePath) return;
switch (extention) {
case 'csv':
await exportCsv(rows, columns, filePath);
break;
case 'json':
await exportJson(rows, columns, filePath, filters, reportName);
break;
default:
return;
}
fyo.telemetry.log(Verb.Exported, reportName, { extention });
}
export default function getCommonExportActions(reportName: string) {
return ['csv', 'json'].map((ext) => ({
group: fyo.t`Export`,
label: ext.toUpperCase(),
type: 'primary',
action: async (getReportData: GetReportData) =>
await exportReport(ext, reportName, getReportData),
}));
}
export async function saveExportData(data: string, filePath: string) {
await saveData(data, filePath);
showExportInFolder(fyo.t`Export Successful`, filePath);
}

View File

@ -1,3 +1,4 @@
/*
import AccountsReceivablePayable from './AccountsReceivablePayable/AccountsReceivablePayable';
import BalanceSheet from './BalanceSheet/BalanceSheet';
import BankReconciliation from './BankReconciliation/BankReconciliation';
@ -33,3 +34,7 @@ export function getReportData(method, filters) {
const ReportClass = reports[method];
return new ReportClass().run(filters);
}
*/
export function getReportData(method, filters) {
return { rows: [], columns: [] };
}

23
reports/types.ts Normal file
View File

@ -0,0 +1,23 @@
import { AccountRootType } from 'models/baseModels/Account/types';
export type ExportExtension = 'csv' | 'json';
export interface ReportData {
rows: unknown[];
columns: unknown[];
}
export abstract class Report {
abstract run(filters: Record<string, unknown>): ReportData;
}
export type BalanceType = 'Credit' | 'Debit';
export type Periodicity = 'Monthly' | 'Quarterly' | 'Half Yearly' | 'Yearly';
export interface FinancialStatementOptions {
rootType: AccountRootType;
fromDate: string;
toDate: string;
balanceMustBe?: BalanceType;
periodicity?: Periodicity;
accumulateValues?: boolean;
}

View File

@ -1,19 +1,21 @@
import BalanceSheetViewConfig from './BalanceSheet/viewConfig';
import GeneralLedgerViewConfig from './GeneralLedger/viewConfig';
import GoodsAndServiceTaxGSTR1View from './GoodsAndServiceTax/GSTR1View';
import GoodsAndServiceTaxGSTR2View from './GoodsAndServiceTax/GSTR2View';
import ProfitAndLossViewConfig from './ProfitAndLoss/viewConfig';
import PurchaseRegisterViewConfig from './PurchaseRegister/viewConfig';
import SalesRegisterViewConfig from './SalesRegister/viewConfig';
import TrialBalanceViewConfig from './TrialBalance/viewConfig';
// import BalanceSheetViewConfig from './BalanceSheet/viewConfig';
// import GeneralLedgerViewConfig from './GeneralLedger/viewConfig';
// import GoodsAndServiceTaxGSTR1View from './GoodsAndServiceTax/GSTR1View';
// import GoodsAndServiceTaxGSTR2View from './GoodsAndServiceTax/GSTR2View';
// import ProfitAndLossViewConfig from './ProfitAndLoss/viewConfig';
// import PurchaseRegisterViewConfig from './PurchaseRegister/viewConfig';
// import SalesRegisterViewConfig from './SalesRegister/viewConfig';
// import TrialBalanceViewConfig from './TrialBalance/viewConfig';
export default {
'general-ledger': GeneralLedgerViewConfig,
'sales-register': SalesRegisterViewConfig,
'purchase-register': PurchaseRegisterViewConfig,
'balance-sheet': BalanceSheetViewConfig,
'profit-and-loss': ProfitAndLossViewConfig,
'trial-balance': TrialBalanceViewConfig,
'gstr-1': GoodsAndServiceTaxGSTR1View,
'gstr-2': GoodsAndServiceTaxGSTR2View,
};
// export default {
// 'general-ledger': GeneralLedgerViewConfig,
// 'sales-register': SalesRegisterViewConfig,
// 'purchase-register': PurchaseRegisterViewConfig,
// 'balance-sheet': BalanceSheetViewConfig,
// 'profit-and-loss': ProfitAndLossViewConfig,
// 'trial-balance': TrialBalanceViewConfig,
// 'gstr-1': GoodsAndServiceTaxGSTR1View,
// 'gstr-2': GoodsAndServiceTaxGSTR2View,
// };
export default {};

View File

@ -3,17 +3,17 @@
id="app"
class="h-screen flex flex-col font-sans overflow-hidden antialiased"
>
<WindowsTitleBar v-if="platform === 'Windows'" />
<!-- <WindowsTitleBar v-if="platform === 'Windows'" />
<Desk
class="flex-1"
v-if="activeScreen === 'Desk'"
@change-db-file="changeDbFile"
/>
/>-->
<DatabaseSelector
v-if="activeScreen === 'DatabaseSelector'"
@database-connect="showSetupWizardOrDesk(true)"
/>
<SetupWizard
<!--<SetupWizard
v-if="activeScreen === 'SetupWizard'"
@setup-complete="setupComplete"
@setup-canceled="setupCanceled"
@ -25,29 +25,19 @@
>
<div id="toast-target" />
</div>
<TelemetryModal />
<TelemetryModal />-->
</div>
</template>
<script>
import { ipcRenderer } from 'electron';
import fs from 'fs/promises';
import frappe from 'fyo';
import WindowsTitleBar from 'src/components/WindowsTitleBar';
import config from 'src/config';
import {
connectToLocalDatabase,
postSetup,
purgeCache
} from 'src/initialization';
import { IPC_ACTIONS, IPC_MESSAGES } from 'utils/messages';
import TelemetryModal from './components/once/TelemetryModal.vue';
import { showErrorDialog } from './errorHandling';
import { IPC_MESSAGES } from 'utils/messages';
import { fyo } from './initFyo';
import DatabaseSelector from './pages/DatabaseSelector';
import Desk from './pages/Desk';
import SetupWizard from './pages/SetupWizard/SetupWizard';
// import Desk from './pages/Desk';
// import SetupWizard from './pages/SetupWizard/SetupWizard';
import './styles/index.css';
import telemetry from './telemetry/telemetry';
import { checkForUpdates, routeTo } from './utils';
export default {
@ -77,15 +67,16 @@ export default {
},
},
components: {
Desk,
SetupWizard,
// Desk,
// SetupWizard,
DatabaseSelector,
WindowsTitleBar,
TelemetryModal,
// WindowsTitleBar,
// TelemetryModal,
},
async mounted() {
telemetry.platform = this.platform;
const lastSelectedFilePath = config.get('lastSelectedFilePath', null);
fyo.telemetry.platform = this.platform;
/*
const lastSelectedFilePath = fyo.config.get('lastSelectedFilePath', null);
const { connectionSuccess, reason } = await connectToLocalDatabase(
lastSelectedFilePath
);
@ -101,16 +92,18 @@ export default {
await showErrorDialog(title, content);
}
*/
this.activeScreen = 'DatabaseSelector';
},
methods: {
async setupComplete() {
await postSetup();
// TODO: Complete this
// await postSetup();
await this.showSetupWizardOrDesk(true);
},
async showSetupWizardOrDesk(resetRoute = false) {
const { setupComplete } = frappe.AccountingSettings;
const { setupComplete } = fyo.singles.AccountingSettings;
if (!setupComplete) {
this.activeScreen = 'SetupWizard';
} else {
@ -122,8 +115,8 @@ export default {
return;
}
const { onboardingComplete } = await frappe.getSingle('GetStarted');
const { hideGetStarted } = await frappe.getSingle('SystemSettings');
const { onboardingComplete } = await fyo.getSingle('GetStarted');
const { hideGetStarted } = await fyo.getSingle('SystemSettings');
if (hideGetStarted || onboardingComplete) {
routeTo('/');
@ -132,13 +125,14 @@ export default {
}
},
async changeDbFile() {
config.set('lastSelectedFilePath', null);
fyo.config.set('lastSelectedFilePath', null);
telemetry.stop();
await purgeCache(true);
// TODO: purgeCache(true)
// await purgeCache(true);
this.activeScreen = 'DatabaseSelector';
},
async setupCanceled() {
const filePath = config.get('lastSelectedFilePath');
const filePath = fyo.config.get('lastSelectedFilePath');
await fs.unlink(filePath);
this.changeDbFile();
},

View File

@ -5,7 +5,7 @@
</template>
<script>
import { getBgTextColorClass } from '../colors';
import { getBgTextColorClass } from 'src/utils/colors';
export default {
name: 'Badge',

View File

@ -134,7 +134,7 @@
</template>
<script>
import Tooltip from '../Tooltip.vue';
import { prefixFormat } from './chartUtils';
import { prefixFormat } from 'src/utils/chart';
export default {
props: {

View File

@ -131,8 +131,8 @@
</div>
</template>
<script>
import { euclideanDistance, prefixFormat } from 'src/utils/chart';
import Tooltip from '../Tooltip.vue';
import { euclideanDistance, prefixFormat } from './chartUtils';
export default {
props: {

View File

@ -56,12 +56,12 @@
</template>
<script>
import frappe from 'frappe';
import { ipcRenderer } from 'electron';
import Base from './Base';
import { IPC_ACTIONS } from 'utils/messages';
import fs from 'fs';
import path from 'path';
import { fyo } from 'src/initFyo';
import { IPC_ACTIONS } from 'utils/messages';
import Base from './Base';
export default {
name: 'AttachImage',
@ -75,7 +75,7 @@ export default {
methods: {
async openFileSelector() {
const options = {
title: frappe.t`Select Image`,
title: fyo.t`Select Image`,
properties: ['openFile'],
filters: [
{ name: 'Image', extensions: ['png', 'jpg', 'jpeg', 'webp'] },

View File

@ -28,7 +28,7 @@
</template>
<script>
import frappe from 'frappe';
import { fyo } from 'src/initFyo';
import Float from './Float';
export default {
@ -48,12 +48,12 @@ export default {
this.$emit('focus', e);
},
parse(value) {
return frappe.pesa(value);
return fyo.pesa(value);
},
onBlur(e) {
let { value } = e.target;
if (value !== 0 && !value) {
value = frappe.pesa(0).round();
value = fyo.pesa(0).round();
}
this.showInput = false;
@ -68,7 +68,7 @@ export default {
},
computed: {
formattedValue() {
return frappe.format(this.value, this.df, this.doc);
return fyo.format(this.value, this.df, this.doc);
},
},
};

View File

@ -16,7 +16,7 @@
</template>
<script>
import frappe from 'frappe';
import { fyo } from 'src/initFyo';
import Base from './Base';
import DatePicker from '../DatePicker/DatePicker';
@ -33,7 +33,7 @@ export default {
},
methods: {
formatValue(value) {
return frappe.format(value, this.df);
return fyo.format(value, this.df);
}
}
};

View File

@ -7,10 +7,10 @@
/>
</template>
<script>
import { DEFAULT_LANGUAGE } from 'frappe/utils/consts';
import config from 'src/config';
import { languageCodeMap } from 'src/languageCodeMap';
import { DEFAULT_LANGUAGE } from 'fyo/utils/consts';
import { fyo } from 'src/initFyo';
import { setLanguageMap } from 'src/utils';
import { languageCodeMap } from 'src/utils/language';
import FormControl from './FormControl';
export default {
@ -31,16 +31,15 @@ export default {
components: { FormControl },
computed: {
value() {
return config.get('language') ?? DEFAULT_LANGUAGE;
return fyo.config.get('language') ?? DEFAULT_LANGUAGE;
},
languageDf() {
languageCodeMap;
return {
fieldname: 'language',
label: this.t`Language`,
fieldtype: 'Select',
options: Object.keys(languageCodeMap),
default: config.get('language') ?? DEFAULT_LANGUAGE,
default: fyo.config.get('language') ?? DEFAULT_LANGUAGE,
description: this.t`Set the display language.`,
};
},

View File

@ -1,11 +1,7 @@
import Badge from 'src/components/Badge';
import { openQuickEdit } from 'src/utils';
import frappe, { t } from 'frappe';
import { markRaw } from 'vue';
import AutoComplete from './AutoComplete';
<script>
import frappe, { t } from 'frappe';
import { t } from 'fyo';
import Badge from 'src/components/Badge';
import { fyo } from 'src/initFyo';
import { openQuickEdit } from 'src/utils';
import { markRaw } from 'vue';
import AutoComplete from './AutoComplete';
@ -19,7 +15,7 @@ export default {
let doctype = this.getTarget();
let meta;
try {
meta = frappe.getMeta(doctype);
meta = fyo.getMeta(doctype);
} catch (err) {
if (err.message.includes('not a registered doctype')) {
return [];
@ -30,7 +26,7 @@ export default {
if (keyword && !filters.keywords) {
filters.keywords = ['like', keyword];
}
let results = await frappe.db.getAll({
let results = await fyo.db.getAll({
doctype,
filters,
fields: [
@ -108,7 +104,7 @@ export default {
},
async openNewDoc() {
let doctype = this.df.target;
let doc = await frappe.getEmptyDoc(doctype);
let doc = await fyo.getEmptyDoc(doctype);
let filters = await this.getFilters();
openQuickEdit({
doctype,

View File

@ -61,8 +61,8 @@
</template>
<script>
import frappe from 'frappe';
import Row from 'src/components/Row';
import { fyo } from 'src/initFyo';
import Base from './Base';
import TableRow from './TableRow';
@ -122,7 +122,7 @@ export default {
return [0.3].concat(this.tableFields.map(() => 1));
},
tableFields() {
let meta = frappe.getMeta(this.df.childtype);
let meta = fyo.getMeta(this.df.childtype);
return meta.tableFields.map((fieldname) => meta.getField(fieldname));
},
},

View File

@ -32,6 +32,4 @@ export default {
return svg;
},
};
// https://github.com/frappe/frappejs/commits/master/ui/components/FeatherIcon.vue
</script>

View File

@ -116,8 +116,8 @@
</template>
<script>
import { t } from 'frappe';
import { getRandomString } from 'frappe/utils';
import { t } from 'fyo';
import { getRandomString } from 'utils';
import Button from './Button';
import FormControl from './Controls/FormControl';
import Icon from './Icon';
@ -153,9 +153,7 @@ export default {
this.addNewFilter();
},
methods: {
getRandomString() {
return getRandomString();
},
getRandomString,
addNewFilter() {
let df = this.fields[0];
this.addFilter(df.fieldname, 'like', '');

View File

@ -1,93 +0,0 @@
<template>
<div>
<div v-if="doc" class="p-4">
<div class="row">
<div class="col-6 text-center">
<h4>Customize</h4>
</div>
<div class="col-6 text-right">
<f-button secondary @click="saveAndClose">{{
t`Save & Close`
}}</f-button>
</div>
</div>
<div class="row">
<div class="col-12 mt-4">
<form-layout :doc="doc" :fields="fields" @updateDoc="saveDoc" />
<sketch-picker v-model="color" class="shadow-none" />
<div class="mt-3">
<f-button secondary @click="openCompanySettings">{{
t`Company Settings`
}}</f-button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import FormLayout from 'frappe/ui/components/Form/FormLayout';
import { Sketch } from 'vue-color';
export default {
name: 'InvoiceCustomizer',
emits: [
'changeTemplate',
'changeFont',
'closeInvoiceCustomizer',
'updateTemplateView',
'changeColor',
],
components: {
FormLayout,
'sketch-picker': Sketch,
},
data() {
return {
doc: null,
fields: [],
color: {},
};
},
async created() {
this.doc = await frappe.doc.getDoc('SalesInvoiceSettings');
this.color.hex = this.doc.themeColor;
const meta = frappe.getMeta('SalesInvoiceSettings');
this.fields = meta.fields.filter(
(field) => field.fieldname !== 'numberSeries'
);
},
methods: {
async saveDoc(updatedValue) {
let { fieldname, value } = updatedValue;
if (fieldname === 'template') {
this.$emit('changeTemplate', value);
} else if (fieldname === 'font') {
this.$emit('changeFont', value);
}
},
async saveAndClose() {
this.doc.themeColor = this.color.hex;
await this.doc.update();
this.$emit('closeInvoiceCustomizer');
},
async openCompanySettings() {
const settings = await frappe.getSingle('CompanySettings');
settings.on('afterSave', async () => {
this.$formModal.close();
this.$emit('updateTemplateView');
});
this.$formModal.open(settings);
},
},
watch: {
color: async function () {
if (this.doc) {
if (this.doc.themeColor != this.color.hex) {
this.$emit('changeColor', this.color.hex);
}
}
},
},
};
</script>

View File

@ -36,6 +36,7 @@
</template>
<script>
import luxon from 'luxon';
import { fyo } from 'src/initFyo';
export default {
props: ['entries', 'afterReconcile'],
@ -66,7 +67,7 @@ export default {
this.selectedEntries.push(this.entries[i]);
}
for (let entry of this.selectedEntries) {
const payment = await frappe.doc.getDoc('Payment', entry['Payment Entry']);
const payment = await fyo.doc.getDoc('Payment', entry['Payment Entry']);
const clearanceDate =
luxon.DateTime.fromFormat(
entry['Clearance Date'],

View File

@ -1,116 +0,0 @@
<template>
<div>
<div class="row no-gutters">
<div v-if="showInvoiceCustomizer" class="col-3 mt-4 mx-auto"></div>
<div class="col-8 mx-auto text-right mt-4">
<f-button
primary
@click="$emit('send', $refs.printComponent.innerHTML)"
>{{ t`Send` }}</f-button
>
<f-button secondary @click="toggleCustomizer">{{
t`Customize`
}}</f-button>
<f-button
secondary
@click="$emit('makePDF', $refs.printComponent.innerHTML)"
>{{ t`PDF` }}</f-button
>
</div>
</div>
<div class="row no-gutters">
<div v-if="showInvoiceCustomizer" class="col-3 mt-4 mx-auto">
<invoice-customizer
class="border"
style="position: fixed"
@closeInvoiceCustomizer="toggleCustomizer"
@changeColor="changeColor($event)"
@changeTemplate="changeTemplate($event)"
@changeFont="changeFont($event)"
@updateTemplateView="updateTemplateView"
/>
</div>
<div
class="col-8 bg-white mt-4 mx-auto border shadow"
ref="printComponent"
>
<component
:themeColor="themeColor"
:font="font"
:is="template"
v-if="doc"
:doc="doc"
:key="usedForReRender"
/>
</div>
</div>
</div>
</template>
<script>
import InvoiceTemplate1 from 'src/../models/doctype/SalesInvoice/Templates/InvoiceTemplate1';
import InvoiceTemplate2 from 'src/../models/doctype/SalesInvoice/Templates/InvoiceTemplate2';
import InvoiceTemplate3 from 'src/../models/doctype/SalesInvoice/Templates/InvoiceTemplate3';
import InvoiceCustomizer from 'src/components/InvoiceCustomizer';
const invoiceTemplates = {
'Basic I': InvoiceTemplate1,
'Basic II': InvoiceTemplate2,
Modern: InvoiceTemplate3,
};
export default {
name: 'InvoicePrint',
props: ['doc'],
emits: ['send', 'makePDF'],
components: {
InvoiceCustomizer,
},
data() {
return {
showInvoiceCustomizer: false,
themeColor: undefined,
template: undefined,
font: undefined,
usedForReRender: 0,
};
},
async created() {
await this.loadInvoice();
},
methods: {
async loadInvoice() {
await this.getTemplate();
await this.getColor();
await this.getFont();
},
async getTemplate() {
let invoiceSettings = await frappe.doc.getDoc('SalesInvoiceSettings');
this.template = invoiceTemplates[invoiceSettings.template];
},
async getColor() {
let invoiceSettings = await frappe.doc.getDoc('SalesInvoiceSettings');
this.themeColor = invoiceSettings.themeColor;
},
async getFont() {
let invoiceSettings = await frappe.doc.getDoc('SalesInvoiceSettings');
this.font = invoiceSettings.font;
},
async toggleCustomizer() {
await this.loadInvoice();
this.showInvoiceCustomizer = !this.showInvoiceCustomizer;
},
changeColor(color) {
this.themeColor = color;
},
changeTemplate(template) {
this.template = invoiceTemplates[template];
},
changeFont(font) {
this.font = font;
},
updateTemplateView() {
this.usedForReRender += 1;
},
},
};
</script>

View File

@ -1,5 +1,5 @@
<script>
import frappe from 'frappe';
import { fyo } from 'src/initFyo';
export default {
name: 'Base',
props: ['doc', 'printSettings'],
@ -7,7 +7,7 @@ export default {
methods: {
format(row, fieldname) {
let value = row.get(fieldname);
return frappe.format(value, row.meta.getField(fieldname));
return fyo.format(value, row.meta.getField(fieldname));
}
},
async mounted() {

View File

@ -14,7 +14,7 @@
/>
</div>
<div class="text-xl text-gray-700 font-semibold" v-else>
{{ frappe.AccountingSettings.companyName }}
{{ fyo.singles.AccountingSettings.companyName }}
</div>
</div>
<div class="w-1/3">
@ -23,8 +23,8 @@
</div>
<div class="w-1/3">
<div v-if="companyAddress">{{ companyAddress.addressDisplay }}</div>
<div v-if="frappe.AccountingSettings && frappe.AccountingSettings.gstin">
GSTIN: {{ frappe.AccountingSettings.gstin }}
<div v-if="fyo.singles.AccountingSettings && fyo.singles.AccountingSettings.gstin">
GSTIN: {{ fyo.singles.AccountingSettings.gstin }}
</div>
</div>
</div>
@ -36,7 +36,7 @@
{{ doc.name }}
</h1>
<div class="py-2 text-base">
{{ frappe.format(doc.date, 'Date') }}
{{ fyo.format(doc.date, 'Date') }}
</div>
</div>
<div class="w-1/3" v-if="party">
@ -97,7 +97,7 @@
<div class="w-1/2">
<div class="flex pl-2 justify-between py-3 border-b">
<div>{{ t`Subtotal` }}</div>
<div>{{ frappe.format(doc.netTotal, 'Currency') }}</div>
<div>{{ fyo.format(doc.netTotal, 'Currency') }}</div>
</div>
<div
class="flex pl-2 justify-between py-3"
@ -105,13 +105,13 @@
:key="tax.name"
>
<div>{{ tax.account }}</div>
<div>{{ frappe.format(tax.amount, 'Currency') }}</div>
<div>{{ fyo.format(tax.amount, 'Currency') }}</div>
</div>
<div
class="flex pl-2 justify-between py-3 border-t text-green-600 font-semibold text-base"
>
<div>{{ t`Grand Total` }}</div>
<div>{{ frappe.format(doc.grandTotal, 'Currency') }}</div>
<div>{{ fyo.format(doc.grandTotal, 'Currency') }}</div>
</div>
</div>
</div>

View File

@ -18,16 +18,16 @@
class="font-semibold text-xl"
:style="{ color: printSettings.color }"
>
{{ frappe.AccountingSettings.companyName }}
{{ fyo.singles.AccountingSettings.companyName }}
</div>
<div class="text-sm text-gray-800" v-if="companyAddress">
{{ companyAddress.addressDisplay }}
</div>
<div
class="text-sm text-gray-800"
v-if="frappe.AccountingSettings && frappe.AccountingSettings.gstin"
v-if="fyo.singles.AccountingSettings && fyo.singles.AccountingSettings.gstin"
>
GSTIN: {{ frappe.AccountingSettings.gstin }}
GSTIN: {{ fyo.singles.AccountingSettings.gstin }}
</div>
</div>
</div>
@ -41,7 +41,7 @@
{{ doc.name }}
</div>
<div>
{{ frappe.format(doc.date, 'Date') }}
{{ fyo.format(doc.date, 'Date') }}
</div>
</div>
</div>
@ -84,7 +84,7 @@
<div class="text-right">
<div class="text-gray-800">{{ t`Subtotal` }}</div>
<div class="text-xl mt-2">
{{ frappe.format(doc.netTotal, 'Currency') }}
{{ fyo.format(doc.netTotal, 'Currency') }}
</div>
</div>
<div
@ -96,7 +96,7 @@
{{ tax.account }}
</div>
<div class="text-xl mt-2">
{{ frappe.format(tax.amount, 'Currency') }}
{{ fyo.format(tax.amount, 'Currency') }}
</div>
</div>
</div>
@ -107,7 +107,7 @@
<div>
<div>{{ t`Grand Total` }}</div>
<div class="text-2xl mt-2 font-semibold">
{{ frappe.format(doc.grandTotal, 'Currency') }}
{{ fyo.format(doc.grandTotal, 'Currency') }}
</div>
</div>
</div>

View File

@ -18,10 +18,10 @@
class="font-semibold text-xl"
:style="{ color: printSettings.color }"
>
{{ frappe.AccountingSettings.companyName }}
{{ fyo.singles.AccountingSettings.companyName }}
</div>
<div>
{{ frappe.format(doc.date, 'Date') }}
{{ fyo.format(doc.date, 'Date') }}
</div>
</div>
</div>
@ -73,9 +73,9 @@
</div>
<div
class="mt-4 ml-8 text-black leading-relaxed text-lg"
v-if="frappe.AccountingSettings && frappe.AccountingSettings.gstin"
v-if="fyo.singles.AccountingSettings && fyo.singles.AccountingSettings.gstin"
>
GSTIN: {{ frappe.AccountingSettings.gstin }}
GSTIN: {{ fyo.singles.AccountingSettings.gstin }}
</div>
</div>
</div>
@ -117,7 +117,7 @@
<div class="w-1/2 text-lg">
<div class="flex pl-2 justify-between py-1">
<div>{{ t`Subtotal` }}</div>
<div>{{ frappe.format(doc.netTotal, 'Currency') }}</div>
<div>{{ fyo.format(doc.netTotal, 'Currency') }}</div>
</div>
<div
class="flex pl-2 justify-between py-1"
@ -125,14 +125,14 @@
:key="tax.name"
>
<div>{{ tax.account }}</div>
<div>{{ frappe.format(tax.amount, 'Currency') }}</div>
<div>{{ fyo.format(tax.amount, 'Currency') }}</div>
</div>
<div
class="flex pl-2 justify-between py-1 font-semibold"
:style="{ color: printSettings.color }"
>
<div>{{ t`Grand Total` }}</div>
<div>{{ frappe.format(doc.grandTotal, 'Currency') }}</div>
<div>{{ fyo.format(doc.grandTotal, 'Currency') }}</div>
</div>
</div>
</div>

View File

@ -41,10 +41,12 @@
</div>
</template>
<script>
import frappe, { t } from 'frappe';
import { t } from 'fyo';
import reports from 'reports/view';
import Dropdown from 'src/components/Dropdown';
import { fyo } from 'src/initFyo';
import { routeTo } from 'src/utils';
import reports from '../../reports/view';
export default {
data() {
@ -91,8 +93,8 @@ export default {
});
},
getDoctypes() {
let doctypes = Object.keys(frappe.models).sort();
let doctypeMetas = doctypes.map((doctype) => frappe.getMeta(doctype));
let doctypes = Object.keys(fyo.models).sort();
let doctypeMetas = doctypes.map((doctype) => fyo.getMeta(doctype));
let searchableDoctypes = doctypeMetas.filter((meta) => {
return !meta.isSingle && !meta.isChild;
});

View File

@ -99,6 +99,7 @@
import path from 'path';
import Button from 'src/components/Button';
import { reportIssue } from 'src/errorHandling';
import { fyo } from 'src/initFyo';
import { routeTo } from 'src/utils';
import router from '../router';
import sidebarConfig from '../sidebarConfig';
@ -117,10 +118,10 @@ export default {
},
computed: {
appVersion() {
return frappe.store.appVersion;
return fyo.store.appVersion;
},
dbPath() {
const splits = frappe.db.dbPath.split(path.sep);
const splits = fyo.db.dbPath.split(path.sep);
return path.join(...splits.slice(splits.length - 2));
},
},
@ -134,7 +135,7 @@ export default {
groups = groups.filter((group) => {
if (
group.route === '/get-started' &&
frappe.SystemSettings.hideGetStarted
fyo.singles.SystemSettings.hideGetStarted
) {
return false;
}

View File

@ -4,8 +4,7 @@
}}</Badge>
</template>
<script>
import Badge from 'src/components/Badge';
import { statusColor } from '../colors';
import { statusColor } from 'src/utils/colors';
export default {
name: 'StatusBadge',

View File

@ -17,7 +17,7 @@
:style="{ opacity }"
v-if="show"
>
<FeatherIcon :name="iconName" class="w-6 h-6 mr-3" :class="iconColor" />
<feather-icon :name="iconName" class="w-6 h-6 mr-3" :class="iconColor" />
<div @click="actionClicked" :class="actionText ? 'cursor-pointer' : ''">
<p class="text-base">{{ message }}</p>
<button
@ -35,8 +35,7 @@
</div>
</template>
<script>
import { getColorClass } from '../colors';
import FeatherIcon from './FeatherIcon.vue';
import { getColorClass } from 'src/utils/colors';
export default {
components: {

View File

@ -1,7 +1,3 @@
import Button from 'src/components/Button';
import FormControl from 'src/components/Controls/FormControl';
import frappe from 'frappe';
import { getErrorMessage, handleErrorWithDialog } from '../errorHandling';
<template>
<div class="text-sm" :class="{ 'border-t': !noBorder }">
<template v-for="df in formFields">
@ -90,9 +86,9 @@ import { getErrorMessage, handleErrorWithDialog } from '../errorHandling';
</div>
</template>
<script>
import frappe from 'frappe';
import Button from 'src/components/Button';
import FormControl from 'src/components/Controls/FormControl';
import { fyo } from 'src/initFyo';
import { getErrorMessage, handleErrorWithDialog } from '../errorHandling';
let TwoColumnForm = {
@ -224,7 +220,7 @@ let TwoColumnForm = {
this.inlineEditField = df;
if (!this.doc[df.fieldname]) {
this.inlineEditDoc = await frappe.getEmptyDoc(df.target);
this.inlineEditDoc = await fyo.doc.getEmptyDoc(df.target);
this.inlineEditDoc.once('afterInsert', () => {
this.onChangeCommon(df, this.inlineEditDoc.name);
});
@ -234,7 +230,7 @@ let TwoColumnForm = {
this.inlineEditDisplayField =
this.doc.meta.inlineEditDisplayField || 'name';
this.inlineEditFields = frappe.getMeta(df.target).getQuickEditFields();
this.inlineEditFields = fyo.getMeta(df.target).getQuickEditFields();
},
async saveInlineEditDoc(df) {
if (!this.inlineEditDoc) {

View File

@ -20,14 +20,14 @@
</div>
<div class="flex justify-between">
<span>
{{ frappe.format(invoice.date, invoiceMeta.getField('date')) }}
{{ fyo.format(invoice.date, invoiceMeta.getField('date')) }}
</span>
<div>
<span
class="font-medium text-gray-900"
>
{{
frappe.format(
fyo.format(
amountPaid(invoice),
invoiceMeta.getField('baseGrandTotal')
)
@ -35,7 +35,7 @@
</span>
<span class="text-gray-600" v-if="!fullyPaid(invoice)">
({{
frappe.format(
fyo.format(
invoice.outstandingAmount,
invoiceMeta.getField('outstandingAmount')
)
@ -49,7 +49,7 @@
</template>
<script>
import frappe from 'frappe';
import { fyo } from 'src/initFyo';
import { routeTo } from 'src/utils';
import { getStatusColumn } from '../Transaction/Transaction';
@ -67,7 +67,7 @@ export default {
return isCustomer ? 'SalesInvoice' : 'PurchaseInvoice';
},
invoiceMeta() {
return frappe.getMeta(this.invoiceDoctype);
return fyo.getMeta(this.invoiceDoctype);
},
},
mounted() {
@ -78,7 +78,7 @@ export default {
let isCustomer = this.doc.doctype === 'Customer';
let doctype = this.invoiceDoctype;
let partyField = isCustomer ? 'customer' : 'supplier';
this.pendingInvoices = await frappe.db.getAll({
this.pendingInvoices = await fyo.db.getAll({
doctype,
fields: [
'name',

View File

@ -49,10 +49,10 @@
</template>
<script>
import config, { ConfigKeys, TelemetrySetting } from 'src/config';
import { getTelemetryOptions } from 'src/telemetry/helpers';
import telemetry from 'src/telemetry/telemetry';
import { NounEnum, Verb } from 'src/telemetry/types';
import { ConfigKeys } from 'fyo/core/types';
import { getTelemetryOptions } from 'fyo/telemetry/helpers';
import { TelemetrySetting } from 'fyo/telemetry/types';
import { fyo } from 'src/initFyo';
import Button from '../Button.vue';
import FormControl from '../Controls/FormControl';
import FeatherIcon from '../FeatherIcon.vue';
@ -119,12 +119,12 @@ export default {
},
setOpen(telemetry) {
const openCount = config.get(ConfigKeys.OpenCount);
const openCount = fyo.config.get(ConfigKeys.OpenCount);
this.shouldOpen = !this.getIsSet(telemetry) && openCount >= 4;
},
},
mounted() {
const telemetry = config.get(ConfigKeys.Telemetry);
const telemetry = fyo.config.get(ConfigKeys.Telemetry);
this.setOpen(telemetry);
this.value = telemetry;
},

View File

@ -1,11 +1,17 @@
import { t } from 'fyo';
import { Fyo, t } from 'fyo';
import { DocValueMap } from 'fyo/core/types';
import Doc from 'fyo/model/doc';
import { isNameAutoSet } from 'fyo/model/naming';
import { Noun, Verb } from 'fyo/telemetry/types';
import { FieldType, FieldTypeEnum } from 'schemas/types';
import {
Field,
FieldType,
FieldTypeEnum,
OptionField,
SelectOption,
TargetField,
} from 'schemas/types';
import { parseCSV } from '../utils/csvParser';
import { fyo } from './initFyo';
export const importable = [
'SalesInvoice',
@ -44,8 +50,8 @@ interface TemplateField {
label: string;
fieldname: string;
required: boolean;
doctype: string;
options?: string[];
schemaName: string;
options?: SelectOption[];
fieldtype: FieldType;
parentField: string;
}
@ -59,7 +65,7 @@ function formatValue(value: string, fieldtype: FieldType): unknown {
return new Date(value);
case FieldTypeEnum.Currency:
// @ts-ignore
return frappe.pesa(value || 0);
return this.fyo.pesa(value || 0);
case FieldTypeEnum.Int:
case FieldTypeEnum.Float: {
const n = parseFloat(value);
@ -80,33 +86,26 @@ const exclusion: Exclusion = {
};
function getFilteredDocFields(
df: string | string[]
df: string | string[],
fyo: Fyo
): [TemplateField[], string[][]] {
let doctype = df[0];
let schemaName = df[0];
let parentField = df[1] ?? '';
if (typeof df === 'string') {
doctype = df;
schemaName = df;
parentField = '';
}
// @ts-ignore
const primaryFields: Field[] = frappe.models[doctype].fields;
const primaryFields: Field[] = fyo.schemaMap[schemaName]?.fields ?? [];
const fields: TemplateField[] = [];
const tableTypes: string[][] = [];
const exclusionFields: string[] = exclusion[doctype] ?? [];
const exclusionFields: string[] = exclusion[schemaName] ?? [];
primaryFields.forEach((field) => {
const { label, fieldtype, fieldname, readOnly, required, hidden } = field;
primaryFields.forEach(
({
label,
fieldtype,
childtype,
fieldname,
readOnly,
required,
hidden,
options,
}) => {
if (
!(fieldname === 'name' && !parentField) &&
(readOnly ||
@ -116,41 +115,46 @@ function getFilteredDocFields(
return;
}
if (fieldtype === FieldTypeEnum.Table && childtype) {
tableTypes.push([childtype, fieldname]);
if (fieldtype === FieldTypeEnum.Table && (field as TargetField).target) {
tableTypes.push([(field as TargetField).target, fieldname]);
return;
}
let options: SelectOption[] = [];
if ((field as OptionField).options !== undefined) {
options = (field as OptionField).options;
}
fields.push({
label,
fieldname,
doctype,
schemaName: schemaName,
options,
fieldtype,
parentField,
required: Boolean(required ?? false),
});
}
);
});
return [fields, tableTypes];
}
function getTemplateFields(doctype: string): TemplateField[] {
function getTemplateFields(schemaName: string, fyo: Fyo): TemplateField[] {
const fields: TemplateField[] = [];
if (!doctype) {
if (!schemaName) {
return [];
}
const doctypes: string[][] = [[doctype]];
while (doctypes.length > 0) {
const dt = doctypes.pop();
const schemaNames: string[][] = [[schemaName]];
while (schemaNames.length > 0) {
const dt = schemaNames.pop();
if (!dt) {
break;
}
const [templateFields, tableTypes] = getFilteredDocFields(dt);
const [templateFields, tableTypes] = getFilteredDocFields(dt, fyo);
fields.push(...templateFields);
doctypes.push(...tableTypes);
schemaNames.push(...tableTypes);
}
return fields;
}
@ -173,7 +177,7 @@ function getTemplate(templateFields: TemplateField[]): string {
}
export class Importer {
doctype: string;
schemaName: string;
templateFields: TemplateField[];
map: Map;
template: string;
@ -186,10 +190,12 @@ export class Importer {
shouldSubmit: boolean = false;
labelIndex: number = -1;
csv: string[][] = [];
fyo: Fyo;
constructor(doctype: string) {
this.doctype = doctype;
this.templateFields = getTemplateFields(doctype);
constructor(schemaName: string, fyo: Fyo) {
this.schemaName = schemaName;
this.fyo = fyo;
this.templateFields = getTemplateFields(schemaName, this.fyo);
this.map = getLabelFieldMap(this.templateFields);
this.template = getTemplate(this.templateFields);
this.assignedMap = this.assignableLabels.reduce((acc: Map, k) => {
@ -364,7 +370,7 @@ export class Importer {
async importData(setLoadingStatus: LoadingStatusCallback): Promise<Status> {
const status: Status = { success: false, names: [], message: '' };
const shouldDeleteName = isNameAutoSet(this.doctype, fyo);
const shouldDeleteName = isNameAutoSet(this.schemaName, this.fyo);
const docObjs = this.getDocs();
let entriesMade = 0;
@ -383,7 +389,7 @@ export class Importer {
delete docObj[key];
}
const doc: Doc = fyo.doc.getEmptyDoc(this.doctype, false);
const doc: Doc = this.fyo.doc.getEmptyDoc(this.schemaName, false);
try {
await this.makeEntry(doc, docObj);
entriesMade += 1;
@ -391,7 +397,7 @@ export class Importer {
} catch (err) {
setLoadingStatus(false, entriesMade, docObjs.length);
fyo.telemetry.log(Verb.Imported, this.doctype as Noun, {
this.fyo.telemetry.log(Verb.Imported, this.schemaName as Noun, {
success: false,
count: entriesMade,
});
@ -405,7 +411,7 @@ export class Importer {
setLoadingStatus(false, entriesMade, docObjs.length);
status.success = true;
fyo.telemetry.log(Verb.Imported, this.doctype as Noun, {
this.fyo.telemetry.log(Verb.Imported, this.schemaName as Noun, {
success: true,
count: entriesMade,
});
@ -426,7 +432,7 @@ export class Importer {
}
handleError(doc: Doc, err: Error, status: Status): Status {
const messages = [t`Could not import ${this.doctype} ${doc.name!}.`];
const messages = [t`Could not import ${this.schemaName} ${doc.name!}.`];
const message = err.message;
if (message?.includes('UNIQUE constraint failed')) {

View File

@ -10,8 +10,9 @@
const fs = require('fs/promises');
const path = require('path');
const fetch = require('node-fetch').default;
const { splitCsvLine } = require('../scripts/helpers');
import { LanguageMap } from '../utils/types';
import { splitCsvLine } from 'utils/translationHelpers';
import { LanguageMap } from 'utils/types';
const VALENTINES_DAY = 1644796800000;

View File

@ -1,5 +1,5 @@
import { Fyo } from 'fyo';
import models, { getRegionalModels } from 'models';
import { getRegionalModels, models } from 'models';
export const fyo = new Fyo({ isTest: false, isElectron: true });

View File

@ -129,9 +129,9 @@
</div>
</template>
<script>
import frappe from 'frappe';
import PageHeader from 'src/components/PageHeader';
import SearchBar from 'src/components/SearchBar';
import { fyo } from 'src/initFyo';
import { openQuickEdit } from 'src/utils';
import { nextTick } from 'vue';
import { handleErrorWithDialog } from '../errorHandling';
@ -158,8 +158,8 @@ export default {
},
methods: {
async fetchAccounts() {
this.settings = frappe.getMeta(this.doctype).treeSettings;
const { currency } = await frappe.getSingle('AccountingSettings');
this.settings = fyo.getMeta(this.doctype).treeSettings;
const { currency } = await fyo.getSingle('AccountingSettings');
this.root = {
label: await this.settings.getRootLabel(),
balance: 0,
@ -191,7 +191,7 @@ export default {
}
},
async getChildren(parent = null) {
const children = await frappe.db.getAll({
const children = await fyo.db.getAll({
doctype: this.doctype,
filters: {
parentAccount: parent,
@ -240,7 +240,7 @@ export default {
this.insertingAccount = true;
accountName = accountName.trim();
let account = await frappe.getEmptyDoc('Account');
let account = await fyo.getEmptyDoc('Account');
try {
let { name, rootType, accountType } = parentAccount;
await account.set({

View File

@ -100,11 +100,11 @@
</div>
</template>
<script>
import frappe from 'frappe';
import LineChart from 'src/components/Charts/LineChart.vue';
import { fyo } from 'src/initFyo';
import { formatXLabels, getYMax } from 'src/utils/chart';
import { getDatesAndPeriodicity } from 'src/utils/misc';
import Cashflow from '../../../reports/Cashflow/Cashflow';
import { getDatesAndPeriodicity } from './getDatesAndPeriodicity';
import PeriodSelector from './PeriodSelector';
export default {
@ -136,7 +136,7 @@ export default {
this.data.map((d) => d[k])
);
const colors = ['#2490EF', '#B7BFC6'];
const format = (value) => frappe.format(value ?? 0, 'Currency');
const format = (value) => fyo.format(value ?? 0, 'Currency');
const yMax = getYMax(points);
return { points, xLabels, colors, format, yMax, formatX: formatXLabels };
},
@ -147,7 +147,7 @@ export default {
this.period
);
const { data, periodList } = await new Cashflow().run({
const { data, periodList } = await new Cashflow(this.fyo).run({
fromDate,
toDate,
periodicity,

View File

@ -22,7 +22,7 @@
<div class="ml-3">{{ d.account }}</div>
</div>
<p class="whitespace-nowrap">
{{ frappe.format(d.total, 'Currency') }}
{{ fyo.format(d.total, 'Currency') }}
</p>
</div>
</div>
@ -33,7 +33,7 @@
:offset-x="3"
:thickness="11.5"
:text-offset-x="6.5"
:value-formatter="(value) => frappe.format(value, 'Currency')"
:value-formatter="(value) => fyo.format(value, 'Currency')"
:total-label="t`Total Spending`"
@change="(value) => (active = value)"
/>
@ -50,10 +50,10 @@
</template>
<script>
import frappe from 'frappe';
import { fyo } from 'src/initFyo';
import theme from 'src/theme';
import { getDatesAndPeriodicity } from 'src/utils/misc';
import DonutChart from '../../components/Charts/DonutChart.vue';
import { getDatesAndPeriodicity } from './getDatesAndPeriodicity';
import PeriodSelector from './PeriodSelector';
import SectionHeader from './SectionHeader';
@ -95,7 +95,7 @@ export default {
methods: {
async setData() {
const { fromDate, toDate } = await getDatesAndPeriodicity(this.period);
let topExpenses = await frappe.db.getTopExpenses(fromDate, toDate);
let topExpenses = await fyo.db.getTopExpenses(fromDate, toDate);
const shades = [
{ class: 'bg-gray-800', hex: theme.backgroundColor.gray['800'] },
{ class: 'bg-gray-600', hex: theme.backgroundColor.gray['600'] },

View File

@ -36,7 +36,7 @@
</template>
<script>
import { t } from 'frappe';
import { t } from 'fyo';
import Dropdown from 'src/components/Dropdown';
export default {

View File

@ -28,11 +28,11 @@
</div>
</template>
<script>
import frappe from 'frappe';
import { fyo } from 'src/initFyo';
import BarChart from 'src/components/Charts/BarChart.vue';
import { formatXLabels, getYMax, getYMin } from 'src/utils/chart';
import { getDatesAndPeriodicity } from 'src/utils/misc';
import ProfitAndLoss from '../../../reports/ProfitAndLoss/ProfitAndLoss';
import { getDatesAndPeriodicity } from './getDatesAndPeriodicity';
import PeriodSelector from './PeriodSelector';
import SectionHeader from './SectionHeader';
@ -58,7 +58,7 @@ export default {
chartData() {
const points = [this.periodList.map((p) => this.data[p])];
const colors = [{ positive: '#2490EF', negative: '#B7BFC6' }];
const format = (value) => frappe.format(value ?? 0, 'Currency');
const format = (value) => fyo.format(value ?? 0, 'Currency');
const yMax = getYMax(points);
const yMin = getYMin(points);
return {
@ -81,7 +81,7 @@ export default {
this.period
);
let pl = new ProfitAndLoss();
let pl = new ProfitAndLoss(this.fyo);
let res = await pl.run({
fromDate,
toDate,

View File

@ -29,7 +29,7 @@
class="text-sm bold"
:class="{ 'bg-gray-200 text-gray-200 rounded': !invoice.hasData }"
>
{{ frappe.format(invoice.paid, 'Currency') }}
{{ fyo.format(invoice.paid, 'Currency') }}
<span :class="{ 'text-gray-900': invoice.hasData }">{{
t`Paid`
}}</span>
@ -38,7 +38,7 @@
class="text-sm"
:class="{ 'bg-gray-200 text-gray-200 rounded': !invoice.hasData }"
>
{{ frappe.format(invoice.unpaid, 'Currency') }}
{{ fyo.format(invoice.unpaid, 'Currency') }}
<span :class="{ 'text-gray-900': invoice.hasData }">{{
t`Unpaid`
}}</span>
@ -68,10 +68,11 @@
</div>
</template>
<script>
import frappe, { t } from 'frappe';
import { t } from 'fyo';
import Button from 'src/components/Button';
import { fyo } from 'src/initFyo';
import { routeTo } from 'src/utils';
import { getDatesAndPeriodicity } from './getDatesAndPeriodicity';
import { getDatesAndPeriodicity } from 'src/utils/misc';
import PeriodSelector from './PeriodSelector';
import SectionHeader from './SectionHeader';
@ -124,7 +125,7 @@ export default {
this.$data[d.periodKey]
);
let result = await frappe.db.getTotalOutstanding(
let result = await fyo.db.getTotalOutstanding(
d.doctype,
fromDate,
toDate
@ -142,7 +143,7 @@ export default {
this.invoices = await Promise.all(promises);
},
async newInvoice(invoice) {
let doc = await frappe.getEmptyDoc(invoice.doctype);
let doc = await fyo.doc.getEmptyDoc(invoice.doctype);
routeTo(`/edit/${invoice.doctype}/${doc.name}`);
},
},

View File

@ -70,7 +70,7 @@
w-40
"
>
<p>{{ frappe.t`Submit on Import` }}</p>
<p>{{ t`Submit on Import` }}</p>
<FormControl
size="small"
input-class="bg-gray-100"
@ -337,7 +337,6 @@
</template>
<script>
import { ipcRenderer } from 'electron';
import frappe from 'frappe';
import Button from 'src/components/Button.vue';
import FormControl from 'src/components/Controls/FormControl';
import DropdownWithActions from 'src/components/DropdownWithActions.vue';
@ -345,6 +344,7 @@ import FeatherIcon from 'src/components/FeatherIcon.vue';
import HowTo from 'src/components/HowTo.vue';
import PageHeader from 'src/components/PageHeader.vue';
import { importable, Importer } from 'src/dataImport';
import { fyo } from 'src/initFyo';
import { getSavePath, saveData, showMessageDialog } from 'src/utils';
import { IPC_ACTIONS } from 'utils/messages';
import Loading from '../components/Loading.vue';
@ -440,7 +440,7 @@ export default {
isSubmittable() {
const doctype = this.importer?.doctype;
if (doctype) {
return frappe.models[doctype].isSubmittable ?? false;
return fyo.models[doctype].isSubmittable ?? false;
}
return false;
},
@ -450,14 +450,14 @@ export default {
label: this.t`Import Type`,
fieldtype: 'AutoComplete',
placeholder: this.t`Import Type`,
getList: () => importable.map((i) => frappe.models[i].label),
getList: () => importable.map((i) => fyo.models[i].label),
};
},
labelDoctypeMap() {
return importable
.map((i) => ({
name: i,
label: frappe.models[i].label,
label: fyo.models[i].label,
}))
.reduce((acc, { name, label }) => {
acc[label] = name;
@ -585,7 +585,7 @@ export default {
this.clear();
}
this.importType = importType;
this.importer = new Importer(this.labelDoctypeMap[this.importType]);
this.importer = new Importer(this.labelDoctypeMap[this.importType], fyo);
},
setLoadingStatus(isMakingEntries, entriesMade, totalEntries) {
this.isMakingEntries = isMakingEntries;

View File

@ -162,10 +162,8 @@ import { ipcRenderer } from 'electron';
import fs from 'fs';
import { DateTime } from 'luxon';
import LanguageSelector from 'src/components/Controls/LanguageSelector.vue';
import config from 'src/config';
import { connectToLocalDatabase, createNewDatabase } from 'src/initialization';
import { DB_CONN_FAILURE, IPC_ACTIONS } from '../../utils/messages';
import { showErrorDialog } from '../errorHandling';
import { fyo } from 'src/initFyo';
import { IPC_ACTIONS } from 'utils/messages';
export default {
name: 'DatabaseSelector',
@ -189,14 +187,17 @@ export default {
},
methods: {
setFiles() {
this.files = config
this.files = fyo.config
.get('files', [])
.filter(({ filePath }) => fs.existsSync(filePath));
},
async newDatabase() {
/*
TODO: Refactor this
this.fileSelectedFrom = 'New File';
let filePath = await createNewDatabase();
this.connectToDatabase(filePath);
*/
},
async existingDatabase() {
this.fileSelectedFrom = 'Existing File';
@ -214,6 +215,8 @@ export default {
await this.connectToDatabase(file.filePath);
},
async connectToDatabase(filePath) {
/*
TODO: Refactor this
if (!filePath) {
return;
}
@ -235,6 +238,7 @@ export default {
.t`Can't open database file: ${filePath}. Please create a new file.`;
}
await showErrorDialog(title, content);
*/
},
getFileLastModified(filePath) {
let stats = fs.statSync(filePath);

View File

@ -85,10 +85,11 @@
<script>
import { ipcRenderer } from 'electron';
import frappe, { t } from 'frappe';
import { t } from 'fyo';
import Button from 'src/components/Button';
import Icon from 'src/components/Icon';
import PageHeader from 'src/components/PageHeader';
import { fyo } from 'src/initFyo';
import { openSettings, routeTo } from 'src/utils';
import { IPC_MESSAGES } from 'utils/messages';
import { h } from 'vue';
@ -252,7 +253,7 @@ export default {
};
},
async activated() {
frappe.GetStarted = await frappe.getSingle('GetStarted');
fyo.GetStarted = await fyo.getSingle('GetStarted');
this.checkForCompletedTasks();
},
methods: {
@ -292,12 +293,12 @@ export default {
}
},
async checkIsOnboardingComplete() {
if (frappe.GetStarted.onboardingComplete) {
if (fyo.GetStarted.onboardingComplete) {
return true;
}
const meta = await frappe.getMeta('GetStarted');
const doc = await frappe.getSingle('GetStarted');
const meta = await fyo.getMeta('GetStarted');
const doc = await fyo.getSingle('GetStarted');
const onboardingComplete = !!meta.fields
.filter(({ fieldname }) => fieldname !== 'onboardingComplete')
.map(({ fieldname }) => doc.get(fieldname))
@ -305,7 +306,7 @@ export default {
if (onboardingComplete) {
await this.updateChecks({ onboardingComplete });
const systemSettings = await frappe.getSingle('SystemSettings');
const systemSettings = await fyo.getSingle('SystemSettings');
await systemSettings.set({ hideGetStarted: 1 });
await systemSettings.update();
}
@ -318,22 +319,22 @@ export default {
return;
}
if (!frappe.GetStarted.itemCreated) {
const count = await frappe.db.count('Item');
if (!fyo.GetStarted.itemCreated) {
const count = await fyo.db.count('Item');
if (count > 0) {
toUpdate.itemCreated = 1;
}
}
if (!frappe.GetStarted.invoiceCreated) {
const count = await frappe.db.count('SalesInvoice');
if (!fyo.GetStarted.invoiceCreated) {
const count = await fyo.db.count('SalesInvoice');
if (count > 0) {
toUpdate.invoiceCreated = 1;
}
}
if (!frappe.GetStarted.customerCreated) {
const count = frappe.db.count('Party', {
if (!fyo.GetStarted.customerCreated) {
const count = fyo.db.count('Party', {
filters: { role: 'Customer' },
});
if (count > 0) {
@ -341,15 +342,15 @@ export default {
}
}
if (!frappe.GetStarted.billCreated) {
const count = await frappe.db.count('SalesInvoice');
if (!fyo.GetStarted.billCreated) {
const count = await fyo.db.count('SalesInvoice');
if (count > 0) {
toUpdate.billCreated = 1;
}
}
if (!frappe.GetStarted.supplierCreated) {
const count = frappe.db.count('Party', {
if (!fyo.GetStarted.supplierCreated) {
const count = fyo.db.count('Party', {
filters: { role: 'Supplier' },
});
if (count > 0) {
@ -359,15 +360,15 @@ export default {
await this.updateChecks(toUpdate);
},
async updateChecks(toUpdate) {
await frappe.GetStarted.setMultiple(toUpdate);
await frappe.GetStarted.update();
frappe.GetStarted = await frappe.getSingle('GetStarted');
await fyo.GetStarted.setMultiple(toUpdate);
await fyo.GetStarted.update();
fyo.GetStarted = await fyo.getSingle('GetStarted');
},
isCompleted(item) {
return frappe.GetStarted.get(item.fieldname) || 0;
return fyo.GetStarted.get(item.fieldname) || 0;
},
getIconComponent(item) {
let completed = frappe.GetStarted[item.fieldname] || 0;
let completed = fyo.GetStarted[item.fieldname] || 0;
let name = completed ? 'green-check' : item.icon;
let size = completed ? '24' : '18';
return {

View File

@ -153,7 +153,7 @@
<div>{{ tax.account }}</div>
<div>
{{
frappe.format(tax.amount, {
fyo.format(tax.amount, {
fieldtype: 'Currency',
currency: doc.currency,
})
@ -198,7 +198,6 @@
</div>
</template>
<script>
import frappe from 'frappe';
import { getInvoiceStatus } from 'models/helpers';
import BackLink from 'src/components/BackLink';
import Button from 'src/components/Button';
@ -206,6 +205,7 @@ import FormControl from 'src/components/Controls/FormControl';
import DropdownWithActions from 'src/components/DropdownWithActions';
import PageHeader from 'src/components/PageHeader';
import StatusBadge from 'src/components/StatusBadge';
import { fyo } from 'src/initFyo';
import {
getActionsForDocument,
openSettings,
@ -242,7 +242,7 @@ export default {
},
computed: {
meta() {
return frappe.getMeta(this.doctype);
return fyo.getMeta(this.doctype);
},
partyField() {
let fieldname = {
@ -263,18 +263,18 @@ export default {
},
async mounted() {
try {
this.doc = await frappe.doc.getDoc(this.doctype, this.name);
this.doc = await fyo.doc.getDoc(this.doctype, this.name);
window.d = this.doc;
} catch (error) {
if (error instanceof frappe.errors.NotFoundError) {
if (error instanceof fyo.errors.NotFoundError) {
routeTo(`/list/${this.doctype}`);
return;
}
this.handleError(error);
}
this.printSettings = await frappe.getSingle('PrintSettings');
this.printSettings = await fyo.getSingle('PrintSettings');
this.companyName = (
await frappe.getSingle('AccountingSettings')
await fyo.getSingle('AccountingSettings')
).companyName;
let query = this.$route.query;
@ -327,7 +327,7 @@ export default {
doc = this.doc;
}
let df = doc.meta.getField(fieldname);
return frappe.format(doc[fieldname], df, doc);
return fyo.format(doc[fieldname], df, doc);
},
},
};

View File

@ -128,13 +128,13 @@
</div>
</template>
<script>
import frappe from 'frappe';
import BackLink from 'src/components/BackLink';
import Button from 'src/components/Button';
import FormControl from 'src/components/Controls/FormControl';
import DropdownWithActions from 'src/components/DropdownWithActions';
import PageHeader from 'src/components/PageHeader';
import StatusBadge from 'src/components/StatusBadge';
import { fyo } from 'src/initFyo';
import { getActionsForDocument, routeTo, showMessageDialog } from 'src/utils';
import { handleErrorWithDialog } from '../errorHandling';
@ -163,7 +163,7 @@ export default {
},
computed: {
meta() {
return frappe.getMeta(this.doctype);
return fyo.getMeta(this.doctype);
},
status() {
if (this.doc._notInserted || !this.doc.submitted) {
@ -177,14 +177,14 @@ export default {
if (this.doc.accounts) {
value = this.doc.getSum('accounts', 'debit');
}
return frappe.format(value, 'Currency');
return fyo.format(value, 'Currency');
},
totalCredit() {
let value = 0;
if (this.doc.accounts) {
value = this.doc.getSum('accounts', 'credit');
}
return frappe.format(value, 'Currency');
return fyo.format(value, 'Currency');
},
actions() {
return getActionsForDocument(this.doc);
@ -192,10 +192,10 @@ export default {
},
async mounted() {
try {
this.doc = await frappe.doc.getDoc(this.doctype, this.name);
this.doc = await fyo.doc.getDoc(this.doctype, this.name);
window.je = this.doc;
} catch (error) {
if (error instanceof frappe.errors.NotFoundError) {
if (error instanceof fyo.errors.NotFoundError) {
routeTo(`/list/${this.doctype}`);
return;
}

View File

@ -56,11 +56,11 @@
</div>
</template>
<script>
import frappe from 'frappe';
import Avatar from 'src/components/Avatar';
import Button from 'src/components/Button';
import Row from 'src/components/Row';
import { openQuickEdit, routeTo } from 'src/utils';
import { fyo } from 'src/initFyo';
import { openQuickEdit, routeTo } from 'src/utils/ui';
import ListCell from './ListCell';
export default {
@ -90,7 +90,7 @@ export default {
return this.prepareColumns();
},
meta() {
return frappe.getMeta(this.listConfig.doctype);
return fyo.getMeta(this.listConfig.doctype);
},
hasImage() {
return this.meta.hasField('image');
@ -98,7 +98,7 @@ export default {
},
async mounted() {
await this.setupColumnsAndData();
frappe.db.on(`change:${this.listConfig.doctype}`, () => {
fyo.db.on(`change:${this.listConfig.doctype}`, () => {
this.updateData();
});
},
@ -119,7 +119,7 @@ export default {
},
async updateData(filters) {
if (!filters) filters = this.getFilters();
this.data = await frappe.db.getAll({
this.data = await fyo.db.getAll({
doctype: this.doctype,
fields: ['*'],
filters,

View File

@ -5,7 +5,7 @@
</div>
</template>
<script>
import frappe from 'frappe';
import { fyo } from 'src/initFyo';
export default {
name: 'ListCell',
@ -14,7 +14,7 @@ export default {
columnValue() {
let { column, doc } = this;
let value = doc[column.fieldname];
return frappe.format(value, column, doc);
return fyo.format(value, column, doc);
},
customRenderer() {
if (!this.column.render) return;
@ -24,7 +24,7 @@ export default {
return ['Int', 'Float', 'Currency'].includes(this.column.fieldtype)
? 'justify-end'
: '';
}
}
},
},
};
</script>

View File

@ -30,11 +30,11 @@
</div>
</template>
<script>
import frappe from 'fyo';
import Button from 'src/components/Button';
import FilterDropdown from 'src/components/FilterDropdown';
import PageHeader from 'src/components/PageHeader';
import SearchBar from 'src/components/SearchBar';
import { fyo } from 'src/initFyo';
import { routeTo } from 'src/utils';
import List from './List';
@ -63,7 +63,7 @@ export default {
methods: {
async makeNewDoc() {
const doctype = this.listConfig.doctype;
const doc = await frappe.getEmptyDoc(doctype);
const doc = await fyo.doc.getEmptyDoc(doctype);
if (this.listConfig.filters) {
doc.set(this.listConfig.filters);
}
@ -104,9 +104,6 @@ export default {
},
},
computed: {
meta() {
return frappe.getMeta(this.doctype);
},
listConfig() {
if (this?.listConfigs?.[this?.doctype]) {
return this.listConfigs[this.doctype];
@ -114,7 +111,7 @@ export default {
return {
title: this.doctype,
doctype: this.doctype,
columns: this.meta.getKeywordFields(),
columns: fyo.schemaMap[this.doctype].keywordFields ?? ['name'],
};
}
},

View File

@ -52,14 +52,12 @@
</template>
<script>
import { ipcRenderer } from 'electron';
import frappe from 'fyo';
import { Verb } from 'fyo/telemetry/types';
import BackLink from 'src/components/BackLink';
import Button from 'src/components/Button';
import PageHeader from 'src/components/PageHeader';
import SearchBar from 'src/components/SearchBar';
import TwoColumnForm from 'src/components/TwoColumnForm';
import telemetry from 'src/telemetry/telemetry';
import { Verb } from 'src/telemetry/types';
import { makePDF } from 'src/utils';
import { IPC_ACTIONS } from 'utils/messages';
@ -81,12 +79,12 @@ export default {
};
},
async mounted() {
this.doc = await frappe.doc.getDoc(this.doctype, this.name);
this.printSettings = await frappe.getSingle('PrintSettings');
this.doc = await fyo.doc.getDoc(this.doctype, this.name);
this.printSettings = await fyo.getSingle('PrintSettings');
},
computed: {
meta() {
return frappe.getMeta(this.doctype);
return fyo.getMeta(this.doctype);
},
printTemplate() {
return this.meta.printTemplate;
@ -98,7 +96,7 @@ export default {
if (!savePath) return;
const html = this.$refs.printContainer.innerHTML;
telemetry.log(Verb.Exported, 'SalesInvoice', { extension: 'pdf' });
fyo.telemetry.log(Verb.Exported, 'SalesInvoice', { extension: 'pdf' });
makePDF(html, savePath);
},
async getSavePath() {

View File

@ -77,12 +77,13 @@
</template>
<script>
import frappe, { t } from 'frappe';
import { t } from 'fyo';
import Button from 'src/components/Button';
import FormControl from 'src/components/Controls/FormControl';
import DropdownWithActions from 'src/components/DropdownWithActions';
import StatusBadge from 'src/components/StatusBadge';
import TwoColumnForm from 'src/components/TwoColumnForm';
import { fyo } from 'src/initFyo';
import { getActionsForDocument, openQuickEdit } from 'src/utils';
export default {
@ -126,7 +127,7 @@ export default {
},
computed: {
meta() {
return frappe.getMeta(this.doctype);
return fyo.getMeta(this.doctype);
},
status() {
if (this.doc && this.doc._notInserted) {
@ -186,7 +187,7 @@ export default {
},
async fetchDoc() {
try {
this.doc = await frappe.doc.getDoc(this.doctype, this.name);
this.doc = await fyo.doc.getDoc(this.doctype, this.name);
this.doc.once('afterRename', () => {
openQuickEdit({

View File

@ -136,18 +136,18 @@
</div>
</template>
<script>
import frappe from 'frappe';
import reportViewConfig from 'src/../reports/view';
import { getReportData } from 'reports/index';
import reportViewConfig from 'reports/view';
import Button from 'src/components/Button';
import FormControl from 'src/components/Controls/FormControl';
import DropdownWithActions from 'src/components/DropdownWithActions.vue';
import FeatherIcon from 'src/components/FeatherIcon.vue';
import PageHeader from 'src/components/PageHeader';
import Row from 'src/components/Row';
import SearchBar from 'src/components/SearchBar';
import WithScroll from 'src/components/WithScroll';
import { fyo } from 'src/initFyo';
import { h, markRaw } from 'vue';
import { getReportData } from '../../reports/index';
import DropdownWithActions from '../components/DropdownWithActions.vue';
export default {
name: 'Report',
@ -296,7 +296,7 @@ export default {
// default cell component
let formattedValue =
cellValue != null && cellValue !== ''
? frappe.format(cellValue, column)
? fyo.format(cellValue, column)
: '';
return {
render() {

View File

@ -1,6 +1,4 @@
<template>
<div class="flex flex-col overflow-hidden">
<PageHeader>
<template #title>
@ -52,16 +50,16 @@
</template>
<script>
import { ipcRenderer } from 'electron';
import frappe, { t } from 'fyo';
import { t } from 'fyo';
import Button from 'src/components/Button';
import Icon from 'src/components/Icon';
import PageHeader from 'src/components/PageHeader';
import Row from 'src/components/Row';
import StatusBadge from 'src/components/StatusBadge';
import WindowControls from 'src/components/WindowControls';
import { showToast } from 'src/utils/ui';
import { IPC_MESSAGES } from 'utils/messages';
import { h, markRaw } from 'vue';
import { callInitializeMoneyMaker, showToast } from '../../utils';
import TabGeneral from './TabGeneral.vue';
import TabInvoice from './TabInvoice.vue';
import TabSystem from './TabSystem.vue';
@ -113,23 +111,20 @@ export default {
if (
fieldnames.includes('displayPrecision') ||
fieldnames.includes('hideGetStarted')
fieldnames.includes('hideGetStarted') ||
fieldnames.includes('displayPrecision')
) {
this.showReloadToast();
}
if (fieldnames.includes('displayPrecision')) {
callInitializeMoneyMaker(undefined, true);
}
},
methods: {
showReloadToast() {
showToast({
message: t`Settings changes will be visible on reload`,
actionText: frappe.t`Reload App`,
actionText: t`Reload App`,
type: 'info',
action: async () => {
ipcRenderer.send(IPC_MESSAGES.RELOAD_MAIN_WINDOW)
ipcRenderer.send(IPC_MESSAGES.RELOAD_MAIN_WINDOW);
},
});
},

View File

@ -12,8 +12,8 @@
</template>
<script>
import frappe from 'fyo';
import TwoColumnForm from 'src/components/TwoColumnForm';
import { fyo } from 'src/initFyo';
export default {
name: 'TabGeneral',
@ -27,13 +27,16 @@ export default {
};
},
async mounted() {
this.doc = await frappe.doc.getDoc('AccountingSettings', 'AccountingSettings', {
this.doc = await fyo.doc.getDoc(
'AccountingSettings',
'AccountingSettings',
{
skipDocumentCache: true,
});
}
);
},
computed: {
fields() {
let meta = frappe.getMeta('AccountingSettings');
return [
'companyName',
'country',
@ -44,7 +47,7 @@ export default {
'fiscalYearStart',
'fiscalYearEnd',
'gstin',
].map((fieldname) => meta.getField(fieldname));
].map((fieldname) => fyo.getField('AccountingSettings', fieldname));
},
},
methods: {

View File

@ -2,13 +2,13 @@
<div v-if="doc">
<div class="flex items-center">
<FormControl
:df="meta.getField('logo')"
:df="getField('logo')"
:value="doc.logo"
@change="
(value) => {
doc.set('logo', value);
doc.update();
forwardChangeEvent(meta.getField('logo'));
forwardChangeEvent(getField('logo'));
}
"
/>
@ -21,14 +21,14 @@
</span>
<FormControl
class="mt-2"
:df="meta.getField('displayLogo')"
:df="getField('displayLogo')"
:value="doc.displayLogo"
:show-label="true"
@change="
(value) => {
doc.set('displayLogo', value);
doc.update();
forwardChangeEvent(meta.getField('displayLogo'));
forwardChangeEvent(getField('displayLogo'));
}
"
size="small"
@ -47,9 +47,9 @@
</template>
<script>
import { ipcRenderer } from 'electron';
import frappe from 'fyo';
import FormControl from 'src/components/Controls/FormControl';
import TwoColumnForm from 'src/components/TwoColumnForm';
import { fyo } from 'src/initFyo';
import { IPC_ACTIONS } from 'utils/messages';
export default {
@ -73,25 +73,25 @@ export default {
};
},
async mounted() {
this.doc = await frappe.getSingle('PrintSettings');
this.doc = await fyo.doc.getSingle('PrintSettings');
this.companyName = (
await frappe.getSingle('AccountingSettings')
await fyo.doc.getSingle('AccountingSettings')
).companyName;
},
computed: {
meta() {
return frappe.getMeta('PrintSettings');
},
fields() {
return ['template', 'color', 'font', 'email', 'phone', 'address'].map(
(field) => this.meta.getField(field)
(field) => this.getField(field)
);
},
},
methods: {
getField(fieldname) {
return fyo.getField('PrintSettings', fieldname);
},
async openFileSelector() {
const options = {
title: frappe.t`Select Logo`,
title: t`Select Logo`,
properties: ['openFile'],
filters: [{ name: 'Invoice Logo', extensions: ['png', 'jpg', 'svg'] }],
};

View File

@ -38,16 +38,13 @@
</template>
<script>
import frappe from 'fyo';
import { ConfigKeys } from 'fyo/core/types';
import { getTelemetryOptions } from 'fyo/telemetry/helpers';
import { TelemetrySetting } from 'fyo/telemetry/types';
import FormControl from 'src/components/Controls/FormControl';
import LanguageSelector from 'src/components/Controls/LanguageSelector.vue';
import TwoColumnForm from 'src/components/TwoColumnForm';
import config, {
ConfigKeys,
TelemetrySetting
} from 'src/config';
import { getTelemetryOptions } from 'src/telemetry/helpers';
import telemetry from 'src/telemetry/telemetry';
import { fyo } from 'src/initFyo';
import { checkForUpdates } from 'src/utils';
export default {
@ -65,9 +62,9 @@ export default {
};
},
async mounted() {
this.doc = frappe.SystemSettings;
this.companyName = frappe.AccountingSettings.companyName;
this.telemetry = config.get(ConfigKeys.Telemetry);
this.doc = fyo.singles.SystemSettings;
this.companyName = fyo.singles.AccountingSettings.companyName;
this.telemetry = fyo.config.get(ConfigKeys.Telemetry);
},
computed: {
df() {
@ -84,7 +81,7 @@ export default {
};
},
fields() {
let meta = frappe.getMeta('SystemSettings');
let meta = fyo.getMeta('SystemSettings');
return meta.getQuickEditFields();
},
},
@ -93,12 +90,12 @@ export default {
setValue(value) {
this.telemetry = value;
if (value === TelemetrySetting.dontLogAnything) {
telemetry.finalLogAndStop();
fyo.telemetry.finalLogAndStop();
} else {
telemetry.log(Verb.Started, NounEnum.Telemetry);
fyo.telemetry.log(Verb.Started, NounEnum.Telemetry);
}
config.set(ConfigKeys.Telemetry, value);
fyo.config.set(ConfigKeys.Telemetry, value);
},
forwardChangeEvent(...args) {
this.$emit('change', ...args);

View File

@ -91,14 +91,14 @@
<script>
import { ipcRenderer } from 'electron';
import fs from 'fs';
import frappe from 'fyo';
import path from 'path';
import FormControl from 'src/components/Controls/FormControl';
import LanguageSelector from 'src/components/Controls/LanguageSelector.vue';
import Popover from 'src/components/Popover';
import TwoColumnForm from 'src/components/TwoColumnForm';
import config from 'src/config';
import { fyo } from 'src/initFyo';
import { connectToLocalDatabase, purgeCache } from 'src/initialization';
import { setupInstance } from 'src/setup/setupInstance';
import { setLanguageMap, showMessageDialog } from 'src/utils';
import { IPC_MESSAGES } from 'utils/messages';
import {
@ -106,7 +106,6 @@ getErrorMessage,
handleErrorWithDialog,
showErrorDialog
} from '../../errorHandling';
import setupCompany from './setupCompany';
import Slide from './Slide.vue';
export default {
@ -135,11 +134,11 @@ export default {
LanguageSelector,
},
async mounted() {
if (config.get('language') !== undefined) {
if (fyo.config.get('language') !== undefined) {
this.index = 1;
}
this.doc = await frappe.doc.getNewDoc('SetupWizard');
this.doc = await fyo.doc.getNewDoc('SetupWizard');
this.doc.on('change', () => {
this.valuesFilled = this.allValuesFilled();
});
@ -192,11 +191,11 @@ export default {
try {
this.loading = true;
await setupCompany(this.doc);
await setupInstance(this.doc);
this.$emit('setup-complete');
} catch (e) {
this.loading = false;
if (e.type === frappe.errors.DuplicateEntryError) {
if (e.type === fyo.errors.DuplicateEntryError) {
console.log(e);
console.log('retrying');
await this.renameDbFileAndRerunSetup();
@ -206,7 +205,7 @@ export default {
}
},
async renameDbFileAndRerunSetup() {
const filePath = config.get('lastSelectedFilePath');
const filePath = fyo.config.get('lastSelectedFilePath');
renameDbFile(filePath);
await purgeCache();
@ -216,7 +215,7 @@ export default {
);
if (connectionSuccess) {
await setupCompany(this.doc);
await setupInstance(this.doc);
this.$emit('setup-complete');
} else {
const title = this.t`DB Connection Error`;
@ -227,7 +226,7 @@ export default {
},
computed: {
meta() {
return frappe.getMeta('SetupWizard');
return fyo.getMeta('SetupWizard');
},
fields() {
return this.meta.getQuickEditFields();

View File

@ -3,7 +3,7 @@ import { DEFAULT_SERIES_START } from 'fyo/utils/consts';
import { getValueMapFromList } from 'utils';
import { fyo } from './initFyo';
export default async function postStart() {
export async function postStart() {
await createDefaultNumberSeries();
await setSingles();
await setCurrencySymbols();

View File

@ -101,8 +101,6 @@ function setErrorHandlers(app: VueApp) {
function setOnWindow() {
if (process.env.NODE_ENV === 'development') {
// @ts-ignore
window.config = config;
// @ts-ignore
window.router = router;
// @ts-ignore

View File

@ -1,15 +1,15 @@
import { NounEnum, Verb } from 'fyo/telemetry/types';
import ChartOfAccounts from 'src/pages/ChartOfAccounts.vue';
import Dashboard from 'src/pages/Dashboard/Dashboard.vue';
import DataImport from 'src/pages/DataImport.vue';
import GetStarted from 'src/pages/GetStarted.vue';
import InvoiceForm from 'src/pages/InvoiceForm.vue';
import JournalEntryForm from 'src/pages/JournalEntryForm.vue';
import ListView from 'src/pages/ListView/ListView.vue';
import PrintView from 'src/pages/PrintView/PrintView.vue';
import QuickEditForm from 'src/pages/QuickEditForm.vue';
import Report from 'src/pages/Report.vue';
import Settings from 'src/pages/Settings/Settings.vue';
// import GetStarted from 'src/pages/GetStarted.vue';
// import ChartOfAccounts from 'src/pages/ChartOfAccounts.vue';
// import DataImport from 'src/pages/DataImport.vue';
// import InvoiceForm from 'src/pages/InvoiceForm.vue';
// import JournalEntryForm from 'src/pages/JournalEntryForm.vue';
// import ListView from 'src/pages/ListView/ListView.vue';
// import PrintView from 'src/pages/PrintView/PrintView.vue';
// import QuickEditForm from 'src/pages/QuickEditForm.vue';
// import Report from 'src/pages/Report.vue';
// import Settings from 'src/pages/Settings/Settings.vue';
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
import { fyo } from './initFyo';
@ -18,6 +18,7 @@ const routes: RouteRecordRaw[] = [
path: '/',
component: Dashboard,
},
/*
{
path: '/get-started',
component: GetStarted,
@ -113,6 +114,7 @@ const routes: RouteRecordRaw[] = [
component: Settings,
props: true,
},
*/
];
const router = createRouter({ routes, history: createWebHistory() });

View File

@ -1,6 +1,6 @@
import { BrowserWindow } from 'electron';
import { sleep } from 'frappe/utils';
import fs from 'fs/promises';
import { sleep } from 'utils';
const PRINT_OPTIONS = {
marginsType: 1, // no margin

View File

@ -246,7 +246,7 @@ export function getActionsForDocument(doc?: Doc): Action[] {
if (!doc) return [];
const actions: Action[] = [
...getActions(doc, fyo),
...getActions(doc),
getDuplicateAction(doc),
getDeleteAction(doc),
getCancelAction(doc),

View File

@ -12,15 +12,18 @@
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"sourceMap": true,
"baseUrl": ".",
"types": ["webpack-env"],
"baseUrl": ".",
"paths": {
"src/*": ["src/*"],
"schemas/*": ["schemas/*"],
"main/*": ["main/*"],
"backend/*": ["backend/*"],
"regional/*": ["regional/*"],
"fixtures/*": ["fixtures/*"],
"utils/*": ["utils/*"]
"reports/*": ["reports/*"],
"models/*": ["models/*"],
"utils/*": ["utils/*"],
},
"lib": ["esnext", "dom", "dom.iterable", "scripthost"]
},
@ -29,23 +32,20 @@
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"schemas/**/*.ts",
"backend/**/*.ts",
"fyo/**/*.ts",
"models/**/*.ts",
"patches/**/*.ts",
"patches/**/*.js",
"reports/**/*.ts",
"accounting/**/*.ts",
"accounting/**/*.ts",
"scripts/**/*.ts",
"utils/csvParser.ts",
"utils/config.ts"
"main/**/*.ts",
"regional/**/*.ts",
"reports/**/*.ts",
"utils/**/*.ts",
],
"exclude": ["node_modules"]
}

View File

@ -13,10 +13,12 @@ module.exports = {
chainWebpackRendererProcess: (config) => {
config.target('electron-renderer');
config.resolve.alias.set('fyo', path.resolve(__dirname, './fyo'));
config.resolve.alias.set('utils', path.resolve(__dirname, './utils'));
},
chainWebpackMainProcess: (config) => {
config.target('electron-main');
config.resolve.alias.set('fyo', path.resolve(__dirname, './fyo'));
config.resolve.alias.set('utils', path.resolve(__dirname, './utils'));
config.module
.rule('js')
.test(/\.js$/)
@ -43,8 +45,10 @@ module.exports = {
src: path.resolve(__dirname, './src'),
schemas: path.resolve(__dirname, './schemas'),
backend: path.resolve(__dirname, './backend'),
models: path.resolve(__dirname, './models'),
utils: path.resolve(__dirname, './utils'),
regional: path.resolve(__dirname, './regional'),
reports: path.resolve(__dirname, './reports'),
fixtures: path.resolve(__dirname, './fixtures'),
});