diff --git a/electron/settings.js b/electron/settings.js index 18f8e654..8049239f 100644 --- a/electron/settings.js +++ b/electron/settings.js @@ -1,5 +1,6 @@ const os = require('os'); const path = require('path'); +const fs = require('fs'); const { writeFile } = require('frappejs/server/utils'); const homedir = os.homedir(); @@ -8,7 +9,7 @@ const configFilePath = path.join(homedir, '.config', 'frappe-accounting', 'setti function getSettings() { let settings; try { - settings = require(configFilePath); + settings = JSON.parse(fs.readFileSync(configFilePath) || '{}'); } catch (e) { settings = {}; } diff --git a/fixtures/invoicePrint.js b/fixtures/invoicePrint.js index 398b2511..790dc5e6 100644 --- a/fixtures/invoicePrint.js +++ b/fixtures/invoicePrint.js @@ -1,6 +1,74 @@ module.exports = { - doctype: "PrintFormat", - name: "Standard Invoice Format", - for: "Invoice", - template: require('./invoice.html') -} \ No newline at end of file + doctype: "PrintFormat", + name: "Standard Invoice Format", + for: "Invoice", + template: ` +

{{ doc.name }}

+
+
+
{{ frappe._("Customer") }}
+
{{ doc.customer }}
+
+
+
{{ frappe._("Date") }}
+
{{ frappe.format(doc.date, 'Date') }}
+
+
+ + + + + + + + + + + + {% for row in doc.items %} + + + + + + + + {% endfor %} + +
{{ frappe._("Item") }}{{ frappe._("Qty") }}{{ frappe._("Rate") }}{{ frappe._("Amount") }}
{{ row.idx + 1 }}{{ row.item }}
{{ frappe.format(row.description, 'Text') }}
{{ row.quantity }}{{ frappe.format(row.rate, 'Currency') }}{{ frappe.format(row.amount, 'Currency') }}
+
+
+
+
+
+ {{ frappe._("Total") }} +
+
+ {{ frappe.format(doc.netTotal, 'Currency')}} +
+
+ {% for tax in doc.taxes %} +
+
+ {{ tax.account }} ({{ tax.rate }}%) +
+
+ {{ frappe.format(tax.amount, 'Currency')}} +
+
+ {% endfor %} +
+
+
{{ frappe._("Grand Total") }}
+
+
+
{{ frappe.format(doc.grandTotal, 'Currency')}}
+
+
+
+
+
+ {{ frappe.format(doc.terms, 'Text') }} +
+ ` +} diff --git a/server/index.js b/server/index.js index dec7984a..77b6272f 100644 --- a/server/index.js +++ b/server/index.js @@ -1,8 +1,6 @@ -const path = require('path'); + const server = require('frappejs/server'); -const frappe = require('frappejs'); -const naming = require('frappejs/model/naming'); -const registerServerMethods = require('./registerServerMethods'); +const postStart = require('./postStart'); async function start() { await server.start({ @@ -14,34 +12,8 @@ async function start() { await postStart(); } -async function postStart() { - // set server-side modules - frappe.models.Invoice.documentClass = require('../models/doctype/Invoice/InvoiceServer.js'); - frappe.models.Payment.documentClass = require('../models/doctype/Payment/PaymentServer.js'); - frappe.models.Bill.documentClass = require('../models/doctype/Bill/BillServer.js'); - frappe.models.JournalEntry.documentClass = require('../models/doctype/JournalEntry/JournalEntryServer.js'); - - frappe.metaCache = {}; - - frappe.syncDoc(require('../fixtures/invoicePrint')); - - // init naming series if missing - await naming.createNumberSeries('INV-', 'InvoiceSettings'); - await naming.createNumberSeries('BILL-', 'BillSettings'); - await naming.createNumberSeries('PAY-', 'PaymentSettings'); - await naming.createNumberSeries('JV-', 'JournalEntrySettings'); - await naming.createNumberSeries('QTN-', 'QuotationSettings'); - await naming.createNumberSeries('SO-', 'SalesOrderSettings'); - await naming.createNumberSeries('OF-', 'FulfillmentSettings'); - await naming.createNumberSeries('PO-', 'PurchaseOrderSettings'); - await naming.createNumberSeries('PREC-', 'PurchaseReceiptSettings'); - - registerServerMethods(); -} - start(); module.exports = { - start, - postStart + start } \ No newline at end of file diff --git a/server/postStart.js b/server/postStart.js new file mode 100644 index 00000000..5cd8690c --- /dev/null +++ b/server/postStart.js @@ -0,0 +1,28 @@ +const frappe = require('frappejs'); +const naming = require('frappejs/model/naming'); +const registerServerMethods = require('./registerServerMethods'); + +module.exports = async function postStart() { + // set server-side modules + frappe.models.Invoice.documentClass = require('../models/doctype/Invoice/InvoiceServer.js'); + frappe.models.Payment.documentClass = require('../models/doctype/Payment/PaymentServer.js'); + frappe.models.Bill.documentClass = require('../models/doctype/Bill/BillServer.js'); + frappe.models.JournalEntry.documentClass = require('../models/doctype/JournalEntry/JournalEntryServer.js'); + + frappe.metaCache = {}; + + frappe.syncDoc(require('../fixtures/invoicePrint')); + + // init naming series if missing + await naming.createNumberSeries('INV-', 'InvoiceSettings'); + await naming.createNumberSeries('BILL-', 'BillSettings'); + await naming.createNumberSeries('PAY-', 'PaymentSettings'); + await naming.createNumberSeries('JV-', 'JournalEntrySettings'); + await naming.createNumberSeries('QTN-', 'QuotationSettings'); + await naming.createNumberSeries('SO-', 'SalesOrderSettings'); + await naming.createNumberSeries('OF-', 'FulfillmentSettings'); + await naming.createNumberSeries('PO-', 'PurchaseOrderSettings'); + await naming.createNumberSeries('PREC-', 'PurchaseReceiptSettings'); + + registerServerMethods(); +} \ No newline at end of file diff --git a/server/registerServerMethods.js b/server/registerServerMethods.js index 96f6b911..0e18e922 100644 --- a/server/registerServerMethods.js +++ b/server/registerServerMethods.js @@ -12,4 +12,17 @@ module.exports = function registerServerMethods() { await importCOA(standardCOA); } }); + + frappe.registerMethod({ + method: 'print-pdf', + handler({doctype, name}) { + if (frappe.isElectron) { + const path = require('path'); + const { getPDFForElectron } = require('frappejs/server/pdf'); + const { getSettings } = require('../electron/settings'); + const destination = path.resolve(getSettings().dbPath, '..') + getPDFForElectron(doctype, name, destination); + } + } + }) } \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index 3b4fccd1..216b650d 100644 --- a/src/App.vue +++ b/src/App.vue @@ -8,6 +8,7 @@ diff --git a/src/main-electron.js b/src/main-electron.js index ba9156dc..e0e27a0d 100644 --- a/src/main-electron.js +++ b/src/main-electron.js @@ -1,43 +1,80 @@ +// frappejs imports +import frappe from 'frappejs'; +import path from 'path'; +import SQLite from 'frappejs/backends/sqlite'; +import common from 'frappejs/common'; +import coreModels from 'frappejs/models'; +import models from '../models'; +import postStart from '../server/postStart'; +import { getSettings, saveSettings } from '../electron/settings'; + // vue imports import Vue from 'vue'; import App from './App'; import router from './router'; import frappeVue from 'frappejs/ui/plugins/frappeVue'; -// frappejs imports -import frappe from 'frappejs'; -import SQLite from 'frappejs/backends/sqlite'; -import common from 'frappejs/common'; -import coreModels from 'frappejs/models'; -import models from '../models'; -import registerServerMethods from '../server/registerServerMethods'; - (async () => { frappe.isServer = true; + frappe.isElectron = true; frappe.init(); frappe.registerLibs(common); frappe.registerModels(coreModels); frappe.registerModels(models); frappe.fetch = window.fetch.bind(); - frappe.login('Administrator'); - frappe.db = new SQLite({ dbPath: 'test.db' }); - await frappe.db.connect(); - await frappe.db.migrate(); - frappe.getSingle('SystemSettings'); - registerServerMethods(); + const electronSettings = getSettings(); + if (!electronSettings.dbPath) { + localStorage.showDesk = false; + } else { + await connectToLocalDatabase(); + localStorage.showDesk = true; + } - frappe.getSingle('AccountingSettings') - .then(accountingSettings => { - if (router.currentRoute.fullPath !== '/') return; + frappe.events.on('SetupWizard:setup-complete', async ({ setupWizardValues }) => { + const { + file, + companyName, + country, + name, + email, + bankName, + fiscalYearStart, + fiscalYearEnd + } = setupWizardValues; - if (accountingSettings.companyName) { - router.push('/tree/Account'); - } else { - router.push('/setup-wizard'); - } + // db init + const dbPath = path.join(file[0].path, 'frappe-accounting.db'); + await saveSettings({ dbPath }); + await connectToLocalDatabase(); + + const doc = await frappe.getSingle('AccountingSettings'); + await doc.set({ + companyName, + country, + fullname: name, + email, + bankName, + fiscalYearStart, + fiscalYearEnd }); + await doc.update(); + await frappe.call({ method: 'import-coa' }); + + frappe.events.trigger('show-desk'); + }); + + async function connectToLocalDatabase() { + const electronSettings = getSettings(); + frappe.login('Administrator'); + frappe.db = new SQLite({ dbPath: electronSettings.dbPath }); + await frappe.db.connect(); + await frappe.db.migrate(); + frappe.getSingle('SystemSettings'); + await postStart(); + } + window.frappe = frappe; Vue.config.productionTip = false; diff --git a/src/main.js b/src/main.js index 68dba453..eeb671cb 100644 --- a/src/main.js +++ b/src/main.js @@ -31,12 +31,41 @@ frappe.getSingle('AccountingSettings') if (router.currentRoute.fullPath !== '/') return; if (accountingSettings.companyName) { - router.push('/tree/Account'); + frappe.events.trigger('show-desk'); } else { - router.push('/setup-wizard'); + frappe.events.trigger('show-setup-wizard'); } }); +frappe.events.on('SetupWizard:setup-complete', async ({ setupWizardValues }) => { + const { + companyName, + country, + name, + email, + abbreviation, + bankName, + fiscalYearStart, + fiscalYearEnd + } = setupWizardValues; + + const doc = await frappe.getSingle('AccountingSettings'); + await doc.set({ + companyName, + country, + fullname: name, + email, + bankName, + fiscalYearStart, + fiscalYearEnd + }); + + await doc.update(); + await frappe.call({ method: 'import-coa' }); + + frappe.events.trigger('show-desk'); +}); + window.frappe = frappe; Vue.config.productionTip = false; diff --git a/src/pages/SetupWizard/SetupWizard.vue b/src/pages/SetupWizard/SetupWizard.vue index 4617d614..4abfb4f5 100644 --- a/src/pages/SetupWizard/SetupWizard.vue +++ b/src/pages/SetupWizard/SetupWizard.vue @@ -55,31 +55,7 @@ export default { methods: { async submit() { try { - const { - companyName, - country, - name, - email, - abbreviation, - bankName, - fiscalYearStart, - fiscalYearEnd - } = this.doc; - - const doc = await frappe.getSingle('AccountingSettings'); - await doc.set({ - companyName, - country, - fullname: name, - email, - bankName, - fiscalYearStart, - fiscalYearEnd - }); - - await doc.update(); - await frappe.call({ method: 'import-coa'}); - frappe.events.trigger('setup-complete'); + frappe.events.trigger('SetupWizard:setup-complete', { setupWizardValues: this.doc }); } catch (e) { console.error(e); } diff --git a/src/pages/SetupWizard/config.js b/src/pages/SetupWizard/config.js index b8662f00..fb4ebf76 100644 --- a/src/pages/SetupWizard/config.js +++ b/src/pages/SetupWizard/config.js @@ -66,7 +66,7 @@ export default { layout: { paginated: true, sections: [ - frappe.isElectron ? { + process.env.ELECTRON === 'true' ? { title: 'Select File location', columns: [ { fields: ['file'] }