mirror of
https://github.com/frappe/books.git
synced 2024-11-10 07:40:55 +00:00
Merge pull request #239 from 18alantom/fix-db-creation
fix: db creation flow, don't show annoying messages when not required
This commit is contained in:
commit
65570d4210
@ -64,7 +64,6 @@ export default {
|
|||||||
return ['fullName'];
|
return ['fullName'];
|
||||||
},
|
},
|
||||||
getRowHTML(list, data) {
|
getRowHTML(list, data) {
|
||||||
console.log(list, data);
|
|
||||||
return `<div class="col-11">${list.getNameHTML(data)}</div>`;
|
return `<div class="col-11">${list.getNameHTML(data)}</div>`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,41 +1,49 @@
|
|||||||
|
import frappe from 'frappejs';
|
||||||
|
|
||||||
export default async function generateTaxes(country) {
|
export default async function generateTaxes(country) {
|
||||||
if (country === 'India') {
|
if (country === 'India') {
|
||||||
const GSTs = {
|
const GSTs = {
|
||||||
GST: [28, 18, 12, 6, 5, 3, 0.25, 0],
|
GST: [28, 18, 12, 6, 5, 3, 0.25, 0],
|
||||||
IGST: [28, 18, 12, 6, 5, 3, 0.25, 0],
|
IGST: [28, 18, 12, 6, 5, 3, 0.25, 0],
|
||||||
'Exempt-GST': [0],
|
'Exempt-GST': [0],
|
||||||
'Exempt-IGST': [0]
|
'Exempt-IGST': [0],
|
||||||
};
|
};
|
||||||
let newTax = await frappe.getNewDoc('Tax');
|
let newTax = await frappe.getNewDoc('Tax');
|
||||||
|
|
||||||
for (const type of Object.keys(GSTs)) {
|
for (const type of Object.keys(GSTs)) {
|
||||||
for (const percent of GSTs[type]) {
|
for (const percent of GSTs[type]) {
|
||||||
if (type === 'GST') {
|
const name = `${type}-${percent}`;
|
||||||
await newTax.set({
|
|
||||||
name: `${type}-${percent}`,
|
// Not cross checking cause hardcoded values.
|
||||||
details: [
|
await frappe.db.knex('Tax').where({ name }).del();
|
||||||
{
|
await frappe.db.knex('TaxDetail').where({ parent: name }).del();
|
||||||
account: 'CGST',
|
|
||||||
rate: percent / 2
|
const details = getTaxDetails(type, percent);
|
||||||
},
|
await newTax.set({ name, details });
|
||||||
{
|
|
||||||
account: 'SGST',
|
|
||||||
rate: percent / 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await newTax.set({
|
|
||||||
name: `${type}-${percent}`,
|
|
||||||
details: [
|
|
||||||
{
|
|
||||||
account: type.toString().split('-')[0],
|
|
||||||
rate: percent
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
await newTax.insert();
|
await newTax.insert();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
function getTaxDetails(type, percent) {
|
||||||
|
if (type === 'GST') {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
account: 'CGST',
|
||||||
|
rate: percent / 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
account: 'SGST',
|
||||||
|
rate: percent / 2,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
account: type.toString().split('-')[0],
|
||||||
|
rate: percent,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -31,8 +31,6 @@ async function getReceivablePayable({ reportType = 'Receivable', date }) {
|
|||||||
for (let entry of validEntries) {
|
for (let entry of validEntries) {
|
||||||
const { outStandingAmount, creditNoteAmount } = getOutstandingAmount(entry);
|
const { outStandingAmount, creditNoteAmount } = getOutstandingAmount(entry);
|
||||||
|
|
||||||
console.log(outStandingAmount);
|
|
||||||
|
|
||||||
if (outStandingAmount > 0.1 / 10) {
|
if (outStandingAmount > 0.1 / 10) {
|
||||||
const row = {
|
const row = {
|
||||||
date: entry.date,
|
date: entry.date,
|
||||||
|
@ -1,11 +1,28 @@
|
|||||||
import frappe from 'frappejs';
|
import frappe from 'frappejs';
|
||||||
import migrate from 'frappejs/model/migrate';
|
import runPatches from 'frappejs/model/runPatches';
|
||||||
import patchesTxt from '../patches/patches.txt';
|
import patchesTxt from '../patches/patches.txt';
|
||||||
const requirePatch = require.context('../patches', true, /\w+\.(js)$/);
|
const requirePatch = require.context('../patches', true, /\w+\.(js)$/);
|
||||||
|
|
||||||
export default async function runMigrate() {
|
export default async function runMigrate() {
|
||||||
let patchOrder = patchesTxt.split('\n');
|
if (await canRunPatches()) {
|
||||||
let allPatches = {};
|
const patchOrder = patchesTxt.split('\n');
|
||||||
|
const allPatches = getAllPatches();
|
||||||
|
await runPatches(allPatches, patchOrder);
|
||||||
|
}
|
||||||
|
await frappe.db.migrate();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function canRunPatches() {
|
||||||
|
return (
|
||||||
|
(await frappe.db
|
||||||
|
.knex('sqlite_master')
|
||||||
|
.where({ type: 'table', name: 'PatchRun' })
|
||||||
|
.select('name').length) > 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAllPatches() {
|
||||||
|
const allPatches = {};
|
||||||
requirePatch.keys().forEach((fileName) => {
|
requirePatch.keys().forEach((fileName) => {
|
||||||
if (fileName === './index.js') return;
|
if (fileName === './index.js') return;
|
||||||
let method;
|
let method;
|
||||||
@ -20,6 +37,5 @@ export default async function runMigrate() {
|
|||||||
allPatches[fileName] = method;
|
allPatches[fileName] = method;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await migrate(allPatches, patchOrder);
|
return allPatches;
|
||||||
await frappe.db.migrate();
|
}
|
||||||
};
|
|
||||||
|
@ -139,7 +139,7 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.files = config.get('files', []).filter(({filepath}) => fs.existsSync(filepath));
|
this.files = config.get('files', []).filter(({filePath}) => fs.existsSync(filePath));
|
||||||
this.showFiles = this.files.length > 0;
|
this.showFiles = this.files.length > 0;
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -158,6 +158,10 @@ export default {
|
|||||||
await this.connectToDatabase(file.filePath);
|
await this.connectToDatabase(file.filePath);
|
||||||
},
|
},
|
||||||
async connectToDatabase(filePath) {
|
async connectToDatabase(filePath) {
|
||||||
|
if (!filePath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.loadingDatabase = true;
|
this.loadingDatabase = true;
|
||||||
const connectionSuccess = await connectToLocalDatabase(filePath);
|
const connectionSuccess = await connectToLocalDatabase(filePath);
|
||||||
this.loadingDatabase = false;
|
this.loadingDatabase = false;
|
||||||
|
@ -65,6 +65,10 @@ import FormControl from '@/components/Controls/FormControl';
|
|||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import setupCompany from './setupCompany';
|
import setupCompany from './setupCompany';
|
||||||
import Popover from '@/components/Popover';
|
import Popover from '@/components/Popover';
|
||||||
|
import config from '@/config';
|
||||||
|
import path from 'path';
|
||||||
|
import fs from 'fs';
|
||||||
|
import { connectToLocalDatabase } from '@/utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getErrorMessage,
|
getErrorMessage,
|
||||||
@ -121,24 +125,31 @@ export default {
|
|||||||
showMessageDialog({ message: this._('Please fill all values') });
|
showMessageDialog({ message: this._('Please fill all values') });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
await setupCompany(this.doc);
|
await setupCompany(this.doc);
|
||||||
this.$emit('setup-complete');
|
this.$emit('setup-complete');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
console.log(e, this.doc);
|
|
||||||
if (e.type === frappe.errors.DuplicateEntryError) {
|
if (e.type === frappe.errors.DuplicateEntryError) {
|
||||||
// TODO: Add option to overwrite file from here.
|
await this.renameDbFileAndRerunSetup();
|
||||||
const message = this._(
|
|
||||||
'Records already exist in the db. Please create a new database file and try again.'
|
|
||||||
);
|
|
||||||
showMessageDialog({ message });
|
|
||||||
} else {
|
} else {
|
||||||
handleErrorWithDialog(e, this.doc);
|
handleErrorWithDialog(e, this.doc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async renameDbFileAndRerunSetup() {
|
||||||
|
const filePath = config.get('lastSelectedFilePath');
|
||||||
|
renameDbFile(filePath);
|
||||||
|
frappe.removeFromCache('AccountingSettings', 'AccountingSettings');
|
||||||
|
delete frappe.AccountingSettings;
|
||||||
|
const connectionSuccess = await connectToLocalDatabase(filePath);
|
||||||
|
if (connectionSuccess) {
|
||||||
|
await setupCompany(this.doc);
|
||||||
|
this.$emit('setup-complete');
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
meta() {
|
meta() {
|
||||||
@ -152,4 +163,14 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function renameDbFile(filePath) {
|
||||||
|
const dirname = path.dirname(filePath);
|
||||||
|
const basename = path.basename(filePath);
|
||||||
|
const backupPath = path.join(dirname, `_${basename}`);
|
||||||
|
if (fs.existsSync(backupPath)) {
|
||||||
|
fs.unlinkSync(backupPath);
|
||||||
|
}
|
||||||
|
fs.renameSync(filePath, backupPath);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -12,7 +12,7 @@ export default async function setupCompany(setupWizardValues) {
|
|||||||
email,
|
email,
|
||||||
bankName,
|
bankName,
|
||||||
fiscalYearStart,
|
fiscalYearStart,
|
||||||
fiscalYearEnd
|
fiscalYearEnd,
|
||||||
} = setupWizardValues;
|
} = setupWizardValues;
|
||||||
|
|
||||||
const accountingSettings = frappe.AccountingSettings;
|
const accountingSettings = frappe.AccountingSettings;
|
||||||
@ -24,7 +24,7 @@ export default async function setupCompany(setupWizardValues) {
|
|||||||
bankName,
|
bankName,
|
||||||
fiscalYearStart,
|
fiscalYearStart,
|
||||||
fiscalYearEnd,
|
fiscalYearEnd,
|
||||||
currency: countryList[country]['currency']
|
currency: countryList[country]['currency'],
|
||||||
});
|
});
|
||||||
|
|
||||||
const printSettings = await frappe.getSingle('PrintSettings');
|
const printSettings = await frappe.getSingle('PrintSettings');
|
||||||
@ -32,7 +32,7 @@ export default async function setupCompany(setupWizardValues) {
|
|||||||
logo: companyLogo,
|
logo: companyLogo,
|
||||||
companyName,
|
companyName,
|
||||||
email,
|
email,
|
||||||
displayLogo: companyLogo ? 1 : 0
|
displayLogo: companyLogo ? 1 : 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
await setupGlobalCurrencies(countryList);
|
await setupGlobalCurrencies(countryList);
|
||||||
@ -55,24 +55,28 @@ async function setupGlobalCurrencies(countries) {
|
|||||||
currency_fraction_units: fractionUnits,
|
currency_fraction_units: fractionUnits,
|
||||||
smallest_currency_fraction_value: smallestValue,
|
smallest_currency_fraction_value: smallestValue,
|
||||||
currency_symbol: symbol,
|
currency_symbol: symbol,
|
||||||
number_format: numberFormat
|
number_format: numberFormat,
|
||||||
} = country;
|
} = country;
|
||||||
|
|
||||||
if (currency) {
|
if (!currency || queue.includes(currency)) {
|
||||||
const exists = queue.includes(currency);
|
continue;
|
||||||
if (!exists) {
|
}
|
||||||
const doc = await frappe.newDoc({
|
|
||||||
doctype: 'Currency',
|
const docObject = {
|
||||||
name: currency,
|
doctype: 'Currency',
|
||||||
fraction,
|
name: currency,
|
||||||
fractionUnits,
|
fraction,
|
||||||
smallestValue,
|
fractionUnits,
|
||||||
symbol,
|
smallestValue,
|
||||||
numberFormat: numberFormat || '#,###.##'
|
symbol,
|
||||||
});
|
numberFormat: numberFormat || '#,###.##',
|
||||||
promises.push(doc.insert());
|
};
|
||||||
queue.push(currency);
|
|
||||||
}
|
const canCreate = await checkIfExactRecordAbsent(docObject);
|
||||||
|
if (canCreate) {
|
||||||
|
const doc = await frappe.newDoc(docObject);
|
||||||
|
promises.push(doc.insert());
|
||||||
|
queue.push(currency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
@ -80,26 +84,30 @@ async function setupGlobalCurrencies(countries) {
|
|||||||
|
|
||||||
async function setupChartOfAccounts(bankName) {
|
async function setupChartOfAccounts(bankName) {
|
||||||
await frappe.call({
|
await frappe.call({
|
||||||
method: 'import-coa'
|
method: 'import-coa',
|
||||||
});
|
});
|
||||||
|
|
||||||
const accountDoc = await frappe.newDoc({
|
const docObject = {
|
||||||
doctype: 'Account'
|
doctype: 'Account',
|
||||||
});
|
|
||||||
Object.assign(accountDoc, {
|
|
||||||
name: bankName,
|
name: bankName,
|
||||||
rootType: 'Asset',
|
rootType: 'Asset',
|
||||||
parentAccount: 'Bank Accounts',
|
parentAccount: 'Bank Accounts',
|
||||||
accountType: 'Bank',
|
accountType: 'Bank',
|
||||||
isGroup: 0
|
isGroup: 0,
|
||||||
});
|
};
|
||||||
accountDoc.insert();
|
|
||||||
|
if (await checkIfExactRecordAbsent(docObject)) {
|
||||||
|
const accountDoc = await frappe.newDoc(docObject);
|
||||||
|
accountDoc.insert();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setupRegionalChanges(country) {
|
async function setupRegionalChanges(country) {
|
||||||
await generateTaxes(country);
|
await generateTaxes(country);
|
||||||
if (country === 'India') {
|
if (country === 'India') {
|
||||||
frappe.models.Party = await import('../../../models/doctype/Party/RegionalChanges');
|
frappe.models.Party = await import(
|
||||||
|
'../../../models/doctype/Party/RegionalChanges'
|
||||||
|
);
|
||||||
await frappe.db.migrate();
|
await frappe.db.migrate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,10 +115,35 @@ async function setupRegionalChanges(country) {
|
|||||||
function updateCompanyNameInConfig() {
|
function updateCompanyNameInConfig() {
|
||||||
let filePath = frappe.db.dbPath;
|
let filePath = frappe.db.dbPath;
|
||||||
let files = config.get('files', []);
|
let files = config.get('files', []);
|
||||||
files.forEach(file => {
|
files.forEach((file) => {
|
||||||
if (file.filePath === filePath) {
|
if (file.filePath === filePath) {
|
||||||
file.companyName = frappe.AccountingSettings.companyName;
|
file.companyName = frappe.AccountingSettings.companyName;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
config.set('files', files);
|
config.set('files', files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function checkIfExactRecordAbsent(docObject) {
|
||||||
|
const { doctype, name } = docObject;
|
||||||
|
const newDocObject = Object.assign({}, docObject);
|
||||||
|
delete newDocObject.doctype;
|
||||||
|
const rows = await frappe.db.knex(doctype).where({ name });
|
||||||
|
|
||||||
|
if (rows.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const storedDocObject = rows[0];
|
||||||
|
const matchList = Object.keys(newDocObject).map((key) => {
|
||||||
|
const newValue = newDocObject[key];
|
||||||
|
const storedValue = storedDocObject[key];
|
||||||
|
return newValue == storedValue; // Should not be type sensitive.
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!matchList.every(Boolean)) {
|
||||||
|
await frappe.db.knex(doctype).where({ name }).del();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
57
src/utils.js
57
src/utils.js
@ -16,38 +16,24 @@ export async function createNewDatabase() {
|
|||||||
defaultPath: 'frappe-books.db',
|
defaultPath: 'frappe-books.db',
|
||||||
};
|
};
|
||||||
|
|
||||||
let { filePath } = await ipcRenderer.invoke(
|
let { canceled, filePath } = await ipcRenderer.invoke(
|
||||||
IPC_ACTIONS.GET_SAVE_FILEPATH,
|
IPC_ACTIONS.GET_SAVE_FILEPATH,
|
||||||
options
|
options
|
||||||
);
|
);
|
||||||
if (filePath) {
|
|
||||||
if (!filePath.endsWith('.db')) {
|
if (canceled || filePath.length === 0) {
|
||||||
filePath = filePath + '.db';
|
return '';
|
||||||
}
|
|
||||||
if (fs.existsSync(filePath)) {
|
|
||||||
showMessageDialog({
|
|
||||||
// prettier-ignore
|
|
||||||
message: _('A file exists with the same name and it will be overwritten. Are you sure you want to continue?'),
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
label: _('Overwrite'),
|
|
||||||
action() {
|
|
||||||
fs.unlinkSync(filePath);
|
|
||||||
return filePath;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: _('Cancel'),
|
|
||||||
action() {
|
|
||||||
return '';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return filePath;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!filePath.endsWith('.db')) {
|
||||||
|
filePath = filePath + '.db';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fs.existsSync(filePath)) {
|
||||||
|
fs.unlinkSync(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadExistingDatabase() {
|
export async function loadExistingDatabase() {
|
||||||
@ -67,30 +53,31 @@ export async function loadExistingDatabase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function connectToLocalDatabase(filepath) {
|
export async function connectToLocalDatabase(filePath) {
|
||||||
if (!filepath) {
|
if (!filePath) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
frappe.login('Administrator');
|
frappe.login('Administrator');
|
||||||
try {
|
try {
|
||||||
frappe.db = new SQLite({
|
frappe.db = new SQLite({
|
||||||
dbPath: filepath,
|
dbPath: filePath,
|
||||||
});
|
});
|
||||||
await frappe.db.connect();
|
await frappe.db.connect();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await migrate();
|
await migrate();
|
||||||
await postStart();
|
await postStart();
|
||||||
|
|
||||||
// set file info in config
|
// set file info in config
|
||||||
let files = config.get('files') || [];
|
let files = config.get('files') || [];
|
||||||
if (!files.find((file) => file.filePath === filepath)) {
|
if (!files.find((file) => file.filePath === filePath)) {
|
||||||
files = [
|
files = [
|
||||||
{
|
{
|
||||||
companyName: frappe.AccountingSettings.companyName,
|
companyName: frappe.AccountingSettings.companyName,
|
||||||
filePath: filepath,
|
filePath: filePath,
|
||||||
},
|
},
|
||||||
...files,
|
...files,
|
||||||
];
|
];
|
||||||
@ -98,7 +85,7 @@ export async function connectToLocalDatabase(filepath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set last selected file
|
// set last selected file
|
||||||
config.set('lastSelectedFilePath', filepath);
|
config.set('lastSelectedFilePath', filePath);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,4 +261,4 @@ export async function runWindowAction(name) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user