2
0
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:
Alan 2021-11-09 16:21:38 +05:30 committed by GitHub
commit 65570d4210
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 173 additions and 107 deletions

View File

@ -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>`;
} }
}, },

View File

@ -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,
},
];
}
}

View File

@ -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,

View File

@ -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(); }
};

View File

@ -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;

View File

@ -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>

View File

@ -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;
}

View File

@ -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;
} }