From 72c6d7f6c79686c98bce5decbcedd9b4ec099142 Mon Sep 17 00:00:00 2001 From: Nishchith K Date: Mon, 18 Feb 2019 11:12:04 +0530 Subject: [PATCH] Winter Sprint: Work (#79) * init() * Country-wise Chart of accounts on setup * Add a sample invoice template * Some error fixes * [fix] missing COA - move importCOA.js from models/doctype/account to models/doctype/Account * All Account initial balance zero * setup Bank Reconciliation * New chart of accounts tree component * GST taxes added. initialized gst reports. * [chore] add *.db to .gitignore * [fix] importCOA path error * fix error + bank reconciliation fields * [feat] add gst taxes * GST report initialized * GST report finalized * GST report finalized * Complete min. reconciliation * [feat] auto select tax in invoice based on states * [chore] fix merge changes * Fix date issue - Make Payment * Add invoice templates and invoice customizer panel * Restructure invoice vue components * update file with fiscal year * Fix issues in invoice designs * Add company settings. Dynamic addresses in invoice * Move invoice styles to different file and add separate components for addresses * [feat] add export-filtered-data-to-csv to reports * [feat] add Export Wizard component for customizing export * Fix invoice customizer position while scrolling. Fix address displayed as undefined in invoice if not found in db * [chore] change markup for select all chkbox * Setup config as doctype * GSTIN bug fix * Add custom google fonts * Add Send email footer * Fix DateTime * Complete Merge + Resolve * Complete Merge + Resolve * [chore] change layout of Export Wizard * [enh] optimize checkNoneSelected, style export modal footer divider * Add Tax to SideBar * Remove extra logs * [fix] db name section in sidebar showing absolute path instead of dbname in windows i.e. platform=win32 * Country-wise Chart of accounts on setup (#78) * Country-wise Chart of accounts on setup * Some error fixes * All Account initial balance zero * Update README.md - updated installation instructions with more detail * Merge #79 Winter Sprint: Work https://github.com/frappe/accounting/pull/79 * Revert "Merge #79 Winter Sprint: Work" This reverts commit 171511666817caa430af672791c8d452e3b4b680. --- .gitignore | 4 +- electron/settings.js | 1 + email/getConfig.js | 5 + email/sender.js | 46 + email/validator.js | 11 + fixtures/countryInfo.json | 68 +- fixtures/verified/in.json | 176 +++ models/doctype/Account/importCOA.js | 69 + .../AccountingLedgerEntry.js | 4 +- .../AccountingSettings/AccountingSettings.js | 5 +- models/doctype/Address/Address.js | 27 +- .../CompanySettings/CompanySettings.js | 27 + models/doctype/Email/Email.js | 72 + models/doctype/EmailAccount/EmailAccount.js | 59 + models/doctype/Invoice/Invoice.js | 3 +- models/doctype/Invoice/InvoicePrint.vue | 124 +- .../Invoice/Templates/AddressDetails.js | 28 + .../Invoice/Templates/CompanyAddress.vue | 38 + .../Invoice/Templates/CustomerAddress.vue | 37 + .../Invoice/Templates/InvoiceStyles.js | 54 + .../Invoice/Templates/InvoiceTemplate1.vue | 108 ++ .../Invoice/Templates/InvoiceTemplate2.vue | 117 ++ .../Invoice/Templates/InvoiceTemplate3.vue | 113 ++ models/doctype/InvoiceItem/InvoiceItem.js | 3 +- .../InvoiceSettings/InvoiceSettings.js | 50 +- models/doctype/Item/Item.js | 27 +- models/doctype/Party/Party.js | 47 +- models/doctype/Party/RegionalChanges.js | 12 + models/doctype/Payment/Payment.js | 62 +- models/doctype/Payment/PaymentList.js | 17 + models/doctype/SetupWizard/SetupWizard.js | 102 ++ models/doctype/Tax/Tax.js | 1 + models/doctype/Tax/TaxList.js | 10 + models/doctype/account/importCOA.js | 2 +- models/index.js | 9 +- package-lock.json | 271 ++-- package.json | 9 +- .../AccountsReceivablePayable.js | 1 - .../BankReconciliation/BankReconciliation.js | 42 + .../BankReconciliationView.js | 80 ++ reports/BankReconciliation/viewConfig.js | 76 ++ reports/GeneralLedger/GeneralLedger.js | 1 - reports/GeneralLedger/GeneralLedgerView.js | 49 +- reports/GeneralLedger/viewConfig.js | 75 +- .../GoodsAndServiceTax/GoodsAndServiceTax.js | 59 + .../GoodsAndServiceTaxView.js | 74 ++ reports/GoodsAndServiceTax/viewConfig.js | 69 + reports/index.js | 15 +- reports/view.js | 4 +- server/registerServerMethods.js | 8 +- src-electron/main.js | 10 +- src/components/ExportWizard.vue | 113 ++ src/components/InvoiceCustomizer.vue | 71 + src/components/PageHeader.vue | 2 +- src/components/Sidebar.vue | 33 +- src/index.html | 1 + src/main-electron.js | 97 +- src/pages/ChartOfAccounts/Branch.vue | 96 ++ src/pages/ChartOfAccounts/index.vue | 50 + src/pages/Email/EmailSend.vue | 47 + src/pages/Email/EmailSendActions.vue | 25 + src/pages/FormView/FormView.vue | 11 +- src/pages/ListView/List.vue | 36 +- src/pages/ListView/listConfig.js | 4 +- src/pages/PrintView/index.vue | 88 +- src/pages/Report/index.vue | 111 ++ src/pages/{Report.vue => ReportList.vue} | 27 +- src/pages/Settings/Settings.vue | 12 +- src/pages/SetupWizard/SetupWizard.vue | 45 +- src/pages/SetupWizard/config.js | 83 -- src/router/index.js | 11 +- src/sidebarConfig.js | 6 + yarn.lock | 1155 +---------------- 73 files changed, 2905 insertions(+), 1600 deletions(-) create mode 100644 email/getConfig.js create mode 100644 email/sender.js create mode 100644 email/validator.js create mode 100644 fixtures/verified/in.json create mode 100644 models/doctype/Account/importCOA.js create mode 100644 models/doctype/CompanySettings/CompanySettings.js create mode 100644 models/doctype/Email/Email.js create mode 100644 models/doctype/EmailAccount/EmailAccount.js create mode 100644 models/doctype/Invoice/Templates/AddressDetails.js create mode 100644 models/doctype/Invoice/Templates/CompanyAddress.vue create mode 100644 models/doctype/Invoice/Templates/CustomerAddress.vue create mode 100644 models/doctype/Invoice/Templates/InvoiceStyles.js create mode 100644 models/doctype/Invoice/Templates/InvoiceTemplate1.vue create mode 100644 models/doctype/Invoice/Templates/InvoiceTemplate2.vue create mode 100644 models/doctype/Invoice/Templates/InvoiceTemplate3.vue create mode 100644 models/doctype/Party/RegionalChanges.js create mode 100644 models/doctype/SetupWizard/SetupWizard.js create mode 100644 models/doctype/Tax/TaxList.js create mode 100644 reports/BankReconciliation/BankReconciliation.js create mode 100644 reports/BankReconciliation/BankReconciliationView.js create mode 100644 reports/BankReconciliation/viewConfig.js create mode 100644 reports/GoodsAndServiceTax/GoodsAndServiceTax.js create mode 100644 reports/GoodsAndServiceTax/GoodsAndServiceTaxView.js create mode 100644 reports/GoodsAndServiceTax/viewConfig.js create mode 100644 src/components/ExportWizard.vue create mode 100644 src/components/InvoiceCustomizer.vue create mode 100644 src/pages/ChartOfAccounts/Branch.vue create mode 100644 src/pages/ChartOfAccounts/index.vue create mode 100644 src/pages/Email/EmailSend.vue create mode 100644 src/pages/Email/EmailSendActions.vue create mode 100644 src/pages/Report/index.vue rename src/pages/{Report.vue => ReportList.vue} (64%) delete mode 100644 src/pages/SetupWizard/config.js diff --git a/.gitignore b/.gitignore index 2ded444e..a0b9ea76 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ node_modules .DS_Store +*.db Thumbs.db -*test.db *.log .cache /temp @@ -11,4 +11,4 @@ Frappe Accounting* build !build/icons !.gitkeep -*.db \ No newline at end of file +*.db diff --git a/electron/settings.js b/electron/settings.js index 8049239f..d11dbb64 100644 --- a/electron/settings.js +++ b/electron/settings.js @@ -20,6 +20,7 @@ function getSettings() { async function saveSettings(settings) { await writeFile(configFilePath, JSON.stringify(settings)); } +console.log(getSettings()); module.exports = { getSettings, diff --git a/email/getConfig.js b/email/getConfig.js new file mode 100644 index 00000000..9b7d66a4 --- /dev/null +++ b/email/getConfig.js @@ -0,0 +1,5 @@ +const frappe = require('frappejs'); +module.exports = async function getData() { + account = await frappe.getDoc('EmailAccount'); + return account; +} \ No newline at end of file diff --git a/email/sender.js b/email/sender.js new file mode 100644 index 00000000..87fcd34e --- /dev/null +++ b/email/sender.js @@ -0,0 +1,46 @@ +const nodemailer = require('nodemailer'); +const getConfig = require("./getConfig"); +const validator = require('./validator'); + +module.exports = { + 'sendMail': async function (mailDetails) { + if (!validator.validate(mailDetails.fromEmailAddress)) { + console.log("INVALID EMAIL"); + return false; + } + + let account = await getConfig(); + if (mailDetails.fromEmailAddress == account.email) { + if (validator.validate(mailDetails.toEmailAddress)) { + mailDetails = { + from: mailDetails.fromEmailAddress, + to: mailDetails.toEmailAddress, + replyTo: mailDetails.toEmailAddress, + inReplyTo: mailDetails.replyId, + references: [mailDetails.replyId], + cc: mailDetails.ccEmailAddress, + bcc: mailDetails.bccEmailAddress, + subject: mailDetails.subject, + text: mailDetails.bodyText, + attachments: [{ + filename: 'Invoice.pdf', + path: mailDetails.filePath, + contentType: 'application/pdf' + }], + }; + let transporter = nodemailer.createTransport({ + service: 'gmail', + auth: { + user: account.email, + pass: account.password, + } + }); + transporter.sendMail(mailDetails); + return true; + } else { + console.log("Sender Email Invalid"); + return false; + } + } + } +}; diff --git a/email/validator.js b/email/validator.js new file mode 100644 index 00000000..f1d390dc --- /dev/null +++ b/email/validator.js @@ -0,0 +1,11 @@ +// + Check Confirm Password == Password + +module.exports = { + validate: function (email) { + var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/; + if (reg.test(email) == false) { + return false; + } + return true; + } +} \ No newline at end of file diff --git a/fixtures/countryInfo.json b/fixtures/countryInfo.json index 2f2cb426..8679cc71 100644 --- a/fixtures/countryInfo.json +++ b/fixtures/countryInfo.json @@ -8,7 +8,9 @@ "number_format": "#,###.##", "timezones": [ "Asia/Kabul" - ] + ], + "fiscal_year_start": "12-20", + "fiscal_year_end": "12-21" }, "Albania": { "code": "al", @@ -169,7 +171,9 @@ "Australia/Melbourne", "Australia/Perth", "Australia/Sydney" - ] + ], + "fiscal_year_start": "07-01", + "fiscal_year_end": "06-30" }, "Austria": { "code": "at", @@ -223,7 +227,9 @@ "number_format": "#,###.##", "timezones": [ "Asia/Dhaka" - ] + ], + "fiscal_year_start": "07-01", + "fiscal_year_end": "06-30" }, "Barbados": { "code": "bb", @@ -488,7 +494,9 @@ "America/Whitehorse", "America/Winnipeg", "America/Yellowknife" - ] + ], + "fiscal_year_start": "04-01", + "fiscal_year_end": "03-31" }, "Cape Verde": { "code": "cv", @@ -639,7 +647,9 @@ "number_format": "#.###,##", "timezones": [ "America/Costa_Rica" - ] + ], + "fiscal_year_start": "10-01", + "fiscal_year_end": "09-30" }, "Croatia": { "code": "hr", @@ -765,7 +775,9 @@ "number_format": "#,###.##", "timezones": [ "Africa/Cairo" - ] + ], + "fiscal_year_start": "07-01", + "fiscal_year_end": "06-30" }, "El Salvador": { "code": "sv", @@ -1113,7 +1125,9 @@ "number_format": "#,###.##", "timezones": [ "Asia/Hong_Kong" - ] + ], + "fiscal_year_start": "04-01", + "fiscal_year_end": "03-31" }, "Hungary": { "code": "hu", @@ -1150,7 +1164,9 @@ "number_format": "#,##,###.##", "timezones": [ "Asia/Kolkata" - ] + ], + "fiscal_year_start": "04-01", + "fiscal_year_end": "03-31" }, "Indonesia": { "code": "id", @@ -1175,7 +1191,9 @@ "number_format": "#,###.##", "timezones": [ "Asia/Tehran" - ] + ], + "fiscal_year_start": "06-23", + "fiscal_year_end": "06-22" }, "Iraq": { "code": "iq", @@ -1232,7 +1250,9 @@ "date_format": "dd/mm/yyyy", "timezones": [ "Europe/Rome" - ] + ], + "fiscal_year_start": "07-01", + "fiscal_year_end": "06-30" }, "Ivory Coast": { "code": "ci", @@ -1714,7 +1734,9 @@ "number_format": "#,###.##", "timezones": [ "Asia/Rangoon" - ] + ], + "fiscal_year_start": "04-01", + "fiscal_year_end": "03-31" }, "Namibia": { "code": "na", @@ -1782,7 +1804,9 @@ "timezones": [ "Pacific/Auckland", "Pacific/Chatham" - ] + ], + "fiscal_year_start": "04-01", + "fiscal_year_end": "03-31" }, "Nicaragua": { "code": "ni", @@ -1878,7 +1902,9 @@ "number_format": "#,###.##", "timezones": [ "Asia/Karachi" - ] + ], + "fiscal_year_start": "07-01", + "fiscal_year_end": "06-30" }, "Palau": { "code": "pw", @@ -2191,7 +2217,9 @@ "number_format": "#,###.##", "timezones": [ "Asia/Singapore" - ] + ], + "fiscal_year_start": "04-01", + "fiscal_year_end": "03-31" }, "Sint Maarten (Dutch part)": { "code": "sx", @@ -2254,7 +2282,9 @@ "number_format": "# ###.##", "timezones": [ "Africa/Johannesburg" - ] + ], + "fiscal_year_start": "03-01", + "fiscal_year_end": "02-28" }, "South Georgia and the South Sandwich Islands": { "code": "gs", @@ -2397,7 +2427,9 @@ "number_format": "#,###.##", "timezones": [ "Asia/Bangkok" - ] + ], + "fiscal_year_start": "10-01", + "fiscal_year_end": "09-30" }, "Timor-Leste": { "code": "tl", @@ -2547,7 +2579,9 @@ "number_format": "#,###.##", "timezones": [ "Europe/London" - ] + ], + "fiscal_year_start": "04-01", + "fiscal_year_end": "03-31" }, "United States": { "code": "us", diff --git a/fixtures/verified/in.json b/fixtures/verified/in.json new file mode 100644 index 00000000..88703e95 --- /dev/null +++ b/fixtures/verified/in.json @@ -0,0 +1,176 @@ +{ + "country_code": "in", + "name": "India - Chart of Accounts", + "tree": { + "Application of Funds (Assets)": { + "Current Assets": { + "Accounts Receivable": { + "Debtors": { + "is_group": 0, + "account_type": "Receivable" + } + }, + "Bank Accounts": { + "account_type": "Bank", + "is_group": 1 + }, + "Cash In Hand": { + "Cash": { + "account_type": "Cash" + }, + "account_type": "Cash" + }, + "Loans and Advances (Assets)": { + "is_group": 1 + }, + "Securities and Deposits": { + "Earnest Money": {} + }, + "Stock Assets": { + "Stock In Hand": { + "account_type": "Stock" + }, + "account_type": "Stock" + }, + "Tax Assets": { + "is_group": 1 + } + }, + "Fixed Assets": { + "Capital Equipments": { + "account_type": "Fixed Asset" + }, + "Electronic Equipments": { + "account_type": "Fixed Asset" + }, + "Furnitures and Fixtures": { + "account_type": "Fixed Asset" + }, + "Office Equipments": { + "account_type": "Fixed Asset" + }, + "Plants and Machineries": { + "account_type": "Fixed Asset" + }, + "Buildings": { + "account_type": "Fixed Asset" + }, + "Accumulated Depreciations": { + "account_type": "Accumulated Depreciation" + } + }, + "Investments": { + "is_group": 1 + }, + "Temporary Accounts": { + "Temporary Opening": { + "account_type": "Temporary" + } + }, + "root_type": "Asset" + }, + "Expenses": { + "Direct Expenses": { + "Stock Expenses": { + "Cost of Goods Sold": { + "account_type": "Cost of Goods Sold" + }, + "Expenses Included In Valuation": { + "account_type": "Expenses Included In Valuation" + }, + "Stock Adjustment": { + "account_type": "Stock Adjustment" + } + } + }, + "Indirect Expenses": { + "Administrative Expenses": {}, + "Commission on Sales": {}, + "Depreciation": { + "account_type": "Depreciation" + }, + "Entertainment Expenses": {}, + "Freight and Forwarding Charges": { + "account_type": "Chargeable" + }, + "Legal Expenses": {}, + "Marketing Expenses": {}, + "Miscellaneous Expenses": {}, + "Office Maintenance Expenses": {}, + "Office Rent": {}, + "Postal Expenses": {}, + "Print and Stationary": {}, + "Rounded Off": { + "account_type": "Round Off" + }, + "Salary": {}, + "Sales Expenses": {}, + "Telephone Expenses": {}, + "Travel Expenses": {}, + "Utility Expenses": {}, + "Write Off": {}, + "Exchange Gain/Loss": {}, + "Gain/Loss on Asset Disposal": {} + }, + "root_type": "Expense" + }, + "Income": { + "Direct Income": { + "Sales": { + "account_type": "Income Account" + }, + "Service": { + "account_type": "Income Account" + }, + "account_type": "Income Account" + }, + "Indirect Income": { + "account_type": "Income Account", + "is_group": 1 + }, + "root_type": "Income" + }, + "Source of Funds (Liabilities)": { + "Capital Account": { + "Reserves and Surplus": {}, + "Shareholders Funds": {} + }, + "Current Liabilities": { + "Accounts Payable": { + "Creditors": { + "account_type": "Payable" + }, + "Payroll Payable": {} + }, + "Stock Liabilities": { + "Stock Received But Not Billed": { + "account_type": "Stock Received But Not Billed" + } + }, + "Duties and Taxes": { + "TDS": { + "account_type": "Tax" + }, + "IGST": { + "accountType": "Tax" + }, + "CGST": { + "accountType": "Tax" + }, + "SGST": { + "accountType": "Tax" + }, + "Exempt": { + "accountType": "Tax" + } + }, + "Loans (Liabilities)": { + "Secured Loans": {}, + "Unsecured Loans": {}, + "Bank Overdraft Account": {} + } + }, + "root_type": "Liability" + } + } +} \ No newline at end of file diff --git a/models/doctype/Account/importCOA.js b/models/doctype/Account/importCOA.js new file mode 100644 index 00000000..50a1b4c2 --- /dev/null +++ b/models/doctype/Account/importCOA.js @@ -0,0 +1,69 @@ +const frappe = require('frappejs'); +const path = require('path'); +const fs = require('fs'); +const countries = require('../../../fixtures/countryInfo.json'); +const standardCOA = require('../../../fixtures/verified/standardCOA.json'); +const accountFields = ['accountType', 'rootType', 'isGroup', 'account_type', 'root_type', 'is_group']; + +async function importAccounts(children, parent, rootType, rootAccount) { + for (let accountName in children) { + const child = children[accountName]; + + if (rootAccount) { + rootType = child.rootType || child.root_type; + } + + if (!accountFields.includes(accountName)) { + let isGroup = identifyIsGroup(child); + const doc = frappe.newDoc({ + doctype: 'Account', + name: accountName, + parentAccount: parent, + isGroup, + rootType, + balance: 0, + accountType: child.accountType + }) + + await doc.insert() + + await importAccounts(child, accountName, rootType) + } + } +} + +function identifyIsGroup(child) { + if (child.isGroup || child.is_group) { + return child.isGroup || child.is_group; + } + + const keys = Object.keys(child); + const children = keys.filter(key => !accountFields.includes(key)) + + if (children.length) { + return 1; + } + + return 0; +} + +async function getCountryCOA(){ + const doc = await frappe.getDoc('AccountingSettings'); + const conCode = countries[doc.country].code; + + const countryCOA = path.resolve(path.join('./fixtures/verified/', conCode + '.json')); + + if(fs.existsSync(countryCOA)){ + const jsonText = fs.readFileSync(countryCOA, 'utf-8'); + const json = JSON.parse(jsonText); + return json.tree; + } else { + return standardCOA; + } +} + +module.exports = async function importCharts() { + const chart = await getCountryCOA(); + await importAccounts(chart, '', '', true) +} + diff --git a/models/doctype/AccountingLedgerEntry/AccountingLedgerEntry.js b/models/doctype/AccountingLedgerEntry/AccountingLedgerEntry.js index 278e4105..98a1e4c1 100644 --- a/models/doctype/AccountingLedgerEntry/AccountingLedgerEntry.js +++ b/models/doctype/AccountingLedgerEntry/AccountingLedgerEntry.js @@ -51,12 +51,12 @@ module.exports = { }, { fieldname: "referenceType", - label: "Reference Type", + label: "Ref. Type", fieldtype: "Data", }, { fieldname: "referenceName", - label: "Reference Name", + label: "Ref. Name", fieldtype: "DynamicLink", references: "referenceType" }, diff --git a/models/doctype/AccountingSettings/AccountingSettings.js b/models/doctype/AccountingSettings/AccountingSettings.js index 96ac53f3..32354316 100644 --- a/models/doctype/AccountingSettings/AccountingSettings.js +++ b/models/doctype/AccountingSettings/AccountingSettings.js @@ -9,13 +9,12 @@ module.exports = { isSubmittable: 0, settings: null, keywordFields: [], - fields: [ - { + fields: [{ label: "Company Name", fieldname: "companyName", fieldtype: "Data", required: 1, - disabled: 1 + disabled: 0 }, { diff --git a/models/doctype/Address/Address.js b/models/doctype/Address/Address.js index b6191f8c..f1225c74 100644 --- a/models/doctype/Address/Address.js +++ b/models/doctype/Address/Address.js @@ -45,11 +45,6 @@ module.exports = { "fieldtype": "Data", "required": 1 }, - { - "fieldname": "county", - "label": "County", - "fieldtype": "Data" - }, { "fieldname": "state", "label": "State", @@ -93,11 +88,11 @@ module.exports = { } ], - events: { - validate: (doc) => { + // events: { + // validate: (doc) => { - } - }, + // } + // }, listSettings: { getFields(list) { @@ -113,11 +108,17 @@ module.exports = { { columns: [ { - fields: [ "addressTitle", "addressType", "addressLine1", - "addressLine2", "city", "county", "state", "country", - "postalCode"] + fields: [ + "addressTitle", "addressType", "addressLine1", + "addressLine2", "city", "country", "state", + "postalCode" + ] }, - { fields: [ "emailAddress", "phone", "fax", "isPreferredBilling", "isShippingBilling" ] } + { + fields: [ + "emailAddress", "phone", "fax", "isPreferredBilling", "isShippingBilling" + ] + } ] } ] diff --git a/models/doctype/CompanySettings/CompanySettings.js b/models/doctype/CompanySettings/CompanySettings.js new file mode 100644 index 00000000..74308bef --- /dev/null +++ b/models/doctype/CompanySettings/CompanySettings.js @@ -0,0 +1,27 @@ +module.exports = { + "name": "CompanySettings", + "label": "Company Settings", + "naming": "autoincrement", + "isSingle": true, + "isChild": false, + "keywordFields": [ + "companyName" + ], + "fields": [ + { + "fieldname": "companyName", + "label": "Company Name", + "fieldtype": "Data", + "disabled": false, + "required": true + }, + { + "fieldname": "companyAddress", + "label": "Company Address", + "fieldtype": "Link", + "disabled": false, + "required": true, + "target": "Address" + } + ] +} \ No newline at end of file diff --git a/models/doctype/Email/Email.js b/models/doctype/Email/Email.js new file mode 100644 index 00000000..8f8f2389 --- /dev/null +++ b/models/doctype/Email/Email.js @@ -0,0 +1,72 @@ +const frappe = require('frappejs'); + +module.exports = { + "name": "Email", + "doctype": "DocType", + "pageSettings": { + hideTitle: true + }, + "isSingle": 0, + "isChild": 0, + "keywordFields": ["name"], + "fields": [{ + "fieldname": "name", + "label": "name", + "fieldtype": "Data", + "required": 0, + "hidden": 1, + "disabled": 0 + }, + { + "fieldname": "fromEmailAddress", + "label": "From", + "fieldtype": "Data", + "required": 1, + "hidden": 0, + formula: async () => { + const accountingSettings = await frappe.getDoc('AccountingSettings'); + return accountingSettings.email; + }, + "disabled": 1 + }, + { + "fieldname": "toEmailAddress", + "label": "To", + "fieldtype": "Data", + "required": 1, + "hidden": 0, + "disabled": 0 + }, + { + "fieldname": "date", + "label": "Date", + "fieldtype": "Datetime", + "required": 0, + "hidden": 0, + "disabled": 1 + }, + { + "fieldname": "subject", + "label": "Subject", + "fieldtype": "Data", + "required": 0, + "hidden": 0, + "disabled": 0 + }, + { + "fieldname": "bodyText", + "label": "Body", + "fieldtype": "Text", + "required": 0, + "hidden": 0, + "disabled": 0 + }, + { + "fieldname": "filePath", + "label": "File Path", + "fieldtype": "Text", + "required": 0, + "hidden": 1, + } + ] +} \ No newline at end of file diff --git a/models/doctype/EmailAccount/EmailAccount.js b/models/doctype/EmailAccount/EmailAccount.js new file mode 100644 index 00000000..e3d93972 --- /dev/null +++ b/models/doctype/EmailAccount/EmailAccount.js @@ -0,0 +1,59 @@ +const frappe = require('frappejs'); + +module.exports = { + "name": "EmailAccount", + "label": "Email Account", + "doctype": "DocType", + "isSingle": true, + "isChild": false, + "keywordFields": [ + "email" + ], + "fields": [ + { + "fieldname": "email", + "label": "Email", + "fieldtype": "Data", + "required": 1, + formula: async () => { + const accountingSettings = await frappe.getDoc('AccountingSettings'); + return accountingSettings.email; + }, + }, + { + "fieldname": "password", + "label": "Password", + "fieldtype": "Password", + "required": 1 + }, + { + "fieldname": "confirmPassword", + "label": "Confirm Password", + "fieldtype": "Password", + "required": 1 + }, + { + "fieldname": "smtpHost", + "label": "SMTP Host", + "fieldtype": "Select", + "options": [ + "smtp.gmail.com", + "smtp.mail.yahoo.com", + "smtp-mail.outlook.com", + "smtp.mail.me.com", + "smtp.aol.com" + ], + "default": "smtp.gmail.com" + }, + { + "fieldname": "smtpPort", + "label": "SMTP Port", + "fieldtype": "Select", + "options": [ + "465", + "587" + ], + "default": "465" + } + ] +} \ No newline at end of file diff --git a/models/doctype/Invoice/Invoice.js b/models/doctype/Invoice/Invoice.js index 4dbe9e35..3cafe8d0 100644 --- a/models/doctype/Invoice/Invoice.js +++ b/models/doctype/Invoice/Invoice.js @@ -18,7 +18,8 @@ module.exports = { { fieldname: 'date', label: 'Date', - fieldtype: 'Date' + fieldtype: 'Date', + // default: (new Date()).toISOString() }, { fieldname: 'customer', diff --git a/models/doctype/Invoice/InvoicePrint.vue b/models/doctype/Invoice/InvoicePrint.vue index 72b3caa6..442cf2fa 100644 --- a/models/doctype/Invoice/InvoicePrint.vue +++ b/models/doctype/Invoice/InvoicePrint.vue @@ -1,73 +1,61 @@ + props: ['doc', 'themeColor', 'template', 'font'], + data() { + return { + color: undefined, + fontFamily: undefined, + invoiceTemplate: undefined + }; + }, + watch: { + themeColor: async function() { + await this.loadInvoice(); + }, + font: async function() { + await this.loadInvoice(); + }, + template: async function() { + await this.loadInvoice(); + } + }, + async created() { + await this.loadInvoice(); + }, + methods: { + async loadInvoice() { + this.color = this.themeColor !== undefined ? this.themeColor : await this.getColor(); + this.fontFamily = this.font !== undefined ? this.font : await this.getFont(); + let template = this.template !== undefined ? this.template : await this.getTemplate(); + let templateFile = invoiceTemplates[template]; + this.invoiceTemplate = templateFile; + }, + async getTemplate() { + let invoiceSettings = await frappe.getDoc('InvoiceSettings'); + return invoiceSettings.template; + }, + async getColor() { + let invoiceSettings = await frappe.getDoc('InvoiceSettings'); + return invoiceSettings.themeColor; + }, + async getFont() { + let invoiceSettings = await frappe.getDoc('InvoiceSettings'); + return invoiceSettings.font; + } + } +}; + \ No newline at end of file diff --git a/models/doctype/Invoice/Templates/AddressDetails.js b/models/doctype/Invoice/Templates/AddressDetails.js new file mode 100644 index 00000000..6e1c8f07 --- /dev/null +++ b/models/doctype/Invoice/Templates/AddressDetails.js @@ -0,0 +1,28 @@ +async function getCompanyDetails() { + let companyDetails = { + name: null, + address: {} + }; + + let companySettings = await frappe.getDoc('CompanySettings'); + companyDetails.name = companySettings.companyName; + + let companyAddress = await getAddress(companySettings.companyAddress); + companyDetails.address = companyAddress; + return companyDetails; +} + +async function getCustomerAddress(customer) { + let customers = await frappe.db.getAll({ doctype: 'Party', fields:['name, address'], filters: { name: customer }}); + let customerDetails = await frappe.getDoc('Party', customers[0].name); + return await getAddress(customerDetails.address); +} + +async function getAddress(addressName) { + return await frappe.getDoc('Address', addressName); +} + +module.exports = { + getCompanyDetails, + getCustomerAddress +} \ No newline at end of file diff --git a/models/doctype/Invoice/Templates/CompanyAddress.vue b/models/doctype/Invoice/Templates/CompanyAddress.vue new file mode 100644 index 00000000..382e8ea1 --- /dev/null +++ b/models/doctype/Invoice/Templates/CompanyAddress.vue @@ -0,0 +1,38 @@ + + \ No newline at end of file diff --git a/models/doctype/Invoice/Templates/CustomerAddress.vue b/models/doctype/Invoice/Templates/CustomerAddress.vue new file mode 100644 index 00000000..3fa08858 --- /dev/null +++ b/models/doctype/Invoice/Templates/CustomerAddress.vue @@ -0,0 +1,37 @@ + + \ No newline at end of file diff --git a/models/doctype/Invoice/Templates/InvoiceStyles.js b/models/doctype/Invoice/Templates/InvoiceStyles.js new file mode 100644 index 00000000..49f3b5f6 --- /dev/null +++ b/models/doctype/Invoice/Templates/InvoiceStyles.js @@ -0,0 +1,54 @@ +module.exports = { + bold: { + fontWeight: 'bold' + }, + font: { + fontFamily: null + }, + regularFontSize: { + fontSize: '0.8rem' + }, + mediumFontSize: { + fontSize: '1rem' + }, + paraStyle: { + margin: '0.5rem', + marginLeft: 0, + marginRight: 0 + }, + bgColor: { + backgroundColor: null + }, + showBorderBottom: { + borderBottom: null + }, + hideBorderTop: { + borderTop: '0px solid black' + }, + showBorderRight: { + borderRight: '1px solid #e0e0d1' + }, + tablePadding: { + paddingTop: '3%', + paddingBottom: '3%' + }, + fontColor: { + color: null + }, + headerColor: { + backgroundColor: null, + color: 'white' + }, + showNoticeBorderBottom: { + borderBottom: null + }, + showBorderTop: { + borderTop: null + }, + headerFontColor: { + color: null + }, + showBorderTop: { + borderTop: null + } +} \ No newline at end of file diff --git a/models/doctype/Invoice/Templates/InvoiceTemplate1.vue b/models/doctype/Invoice/Templates/InvoiceTemplate1.vue new file mode 100644 index 00000000..34bc58dd --- /dev/null +++ b/models/doctype/Invoice/Templates/InvoiceTemplate1.vue @@ -0,0 +1,108 @@ + + diff --git a/models/doctype/Invoice/Templates/InvoiceTemplate2.vue b/models/doctype/Invoice/Templates/InvoiceTemplate2.vue new file mode 100644 index 00000000..cc4c4cc5 --- /dev/null +++ b/models/doctype/Invoice/Templates/InvoiceTemplate2.vue @@ -0,0 +1,117 @@ + + \ No newline at end of file diff --git a/models/doctype/Invoice/Templates/InvoiceTemplate3.vue b/models/doctype/Invoice/Templates/InvoiceTemplate3.vue new file mode 100644 index 00000000..dff84267 --- /dev/null +++ b/models/doctype/Invoice/Templates/InvoiceTemplate3.vue @@ -0,0 +1,113 @@ + + \ No newline at end of file diff --git a/models/doctype/InvoiceItem/InvoiceItem.js b/models/doctype/InvoiceItem/InvoiceItem.js index e5033e52..a5a840a9 100644 --- a/models/doctype/InvoiceItem/InvoiceItem.js +++ b/models/doctype/InvoiceItem/InvoiceItem.js @@ -5,8 +5,7 @@ module.exports = { isChild: 1, keywordFields: [], layout: 'ratio', - fields: [ - { + fields: [{ fieldname: 'item', label: 'Item', fieldtype: 'Link', diff --git a/models/doctype/InvoiceSettings/InvoiceSettings.js b/models/doctype/InvoiceSettings/InvoiceSettings.js index 9feeb779..b7607f40 100644 --- a/models/doctype/InvoiceSettings/InvoiceSettings.js +++ b/models/doctype/InvoiceSettings/InvoiceSettings.js @@ -1,18 +1,42 @@ module.exports = { - "name": "InvoiceSettings", - "label": "Invoice Settings", - "doctype": "DocType", - "isSingle": 1, - "isChild": 0, - "keywordFields": [], - "fields": [ + name: "InvoiceSettings", + label: "Invoice Settings", + doctype: "DocType", + isSingle: 1, + isChild: 0, + keywordFields: [], + fields: [ { - "fieldname": "numberSeries", - "label": "Number Series", - "fieldtype": "Link", - "target": "NumberSeries", - "required": 1, - "default": "INV" + fieldname: "numberSeries", + label: "Number Series", + fieldtype: "Link", + target: "NumberSeries", + required: 1, + default: "INV" + }, + { + fieldname: "template", + label: "Template", + fieldtype: "Select", + options: ["Basic I", "Basic II", "Modern"], + required: 1, + default: "Basic I" + }, + { + fieldname: "font", + label: "Font", + fieldtype: "Select", + options: ["Montserrat", "Open Sans", "Oxygen", "Merriweather"], + required: 1, + default: "Montserrat" + }, + { + fieldname: "themeColor", + label: "Theme Color", + fieldtype: "Data", + required: 1, + default: "#000000", + hidden: 1 } ] } \ No newline at end of file diff --git a/models/doctype/Item/Item.js b/models/doctype/Item/Item.js index b018e589..4e718576 100644 --- a/models/doctype/Item/Item.js +++ b/models/doctype/Item/Item.js @@ -6,8 +6,7 @@ module.exports = { 'name', 'description' ], - fields: [ - { + fields: [{ fieldname: 'name', label: 'Item Name', fieldtype: 'Data', @@ -59,25 +58,31 @@ module.exports = { layout: [ // section 1 { - columns: [ - { fields: ['name', 'unit'] }, - { fields: ['rate'] } + columns: [{ + fields: ['name', 'unit'] + }, + { + fields: ['rate'] + } ] }, // section 2 { - columns: [ - { fields: ['description'] } - ] + columns: [{ + fields: ['description'] + }] }, // section 3 { title: 'Accounting', - columns: [ - { fields: ['incomeAccount', 'expenseAccount'] }, - { fields: ['tax'] } + columns: [{ + fields: ['incomeAccount', 'expenseAccount'] + }, + { + fields: ['tax'] + } ] } ] diff --git a/models/doctype/Party/Party.js b/models/doctype/Party/Party.js index 27f5ab93..e12e15d2 100644 --- a/models/doctype/Party/Party.js +++ b/models/doctype/Party/Party.js @@ -6,24 +6,29 @@ module.exports = { "keywordFields": [ "name" ], - "fields": [ - { + "fields": [{ "fieldname": "name", "label": "Name", "fieldtype": "Data", "required": 1 }, { - fieldname: 'defaultAccount', - label: 'Default Account', - fieldtype: 'Link', - target: 'Account', - getFilters: (query, control) => { - return { - isGroup: 0, - accountType: 'Receivable' - }; - } + fieldname: "address", + label: "Address", + fieldtype: "Link", + target: "Address" + }, + { + fieldname: 'defaultAccount', + label: 'Default Account', + fieldtype: 'Link', + target: 'Account', + getFilters: (query, control) => { + return { + isGroup: 0, + accountType: 'Receivable' + }; + } }, { "fieldname": "customer", @@ -37,15 +42,13 @@ module.exports = { } ], - links: [ - { - label: 'Invoices', - condition: (form) => form.doc.customer, - action: form => { - form.$router.push({ + links: [{ + label: 'Invoices', + condition: (form) => form.doc.customer, + action: form => { + form.$router.push({ path: `/report/sales-register?&customer=${form.doc.name}` - }); - } + }); } - ] -} + }] +} \ No newline at end of file diff --git a/models/doctype/Party/RegionalChanges.js b/models/doctype/Party/RegionalChanges.js new file mode 100644 index 00000000..95cb7350 --- /dev/null +++ b/models/doctype/Party/RegionalChanges.js @@ -0,0 +1,12 @@ +const party = require('./Party') + +party.fields.splice(3, 0, { //insert at 3rd position + fieldname: 'gstin', + label: 'GSTIN No.', + fieldtype: 'Data', + hidden: 0 +}) +party.fields.join() +const newParty = party + +module.exports = newParty \ No newline at end of file diff --git a/models/doctype/Payment/Payment.js b/models/doctype/Payment/Payment.js index 9d04e259..69504524 100644 --- a/models/doctype/Payment/Payment.js +++ b/models/doctype/Payment/Payment.js @@ -8,11 +8,11 @@ module.exports = { isSubmittable: 1, keywordFields: [], settings: "PaymentSettings", - fields: [ - { + fields: [{ "fieldname": "date", - "label": "Date", - "fieldtype": "Date" + "label": "Posting Date", + "fieldtype": "Date", + // default: (new Date()).toISOString() }, { fieldname: "party", @@ -35,6 +35,23 @@ module.exports = { target: "Account", required: 1 }, + { + fieldname: "referenceId", + label: "Ref. / Cheque No.", + fieldtype: "Data", + default: "ABC", + required: 1 // TODO: UNIQUE + }, + { + fieldname: "referenceDate", + label: "Ref. Date", + fieldtype: "Date", + }, + { + fieldname: "clearanceDate", + label: "Clearance Date", + fieldtype: "Date", + }, { fieldname: "amount", label: "Amount", @@ -57,26 +74,33 @@ module.exports = { } ], - layout: [ - { - columns: [ - { fields: ['date', 'party'] }, - { fields: ['account', 'paymentAccount'] }, + layout: [{ + columns: [{ + fields: ['date', 'party'] + }, + { + fields: ['account', 'paymentAccount'] + }, ] }, { - columns: [ - { - fields: ['for'] - } - ] + columns: [{ + fields: ['referenceId'] + }, { + fields: ['referenceDate'] + },{ + fields: ['clearanceDate'] + }] }, { - columns: [ - { - fields: ['amount', 'writeoff'] - } - ] + columns: [{ + fields: ['for'] + }] + }, + { + columns: [{ + fields: ['amount', 'writeoff'] + }] } ], diff --git a/models/doctype/Payment/PaymentList.js b/models/doctype/Payment/PaymentList.js index 38451218..1f9b048c 100644 --- a/models/doctype/Payment/PaymentList.js +++ b/models/doctype/Payment/PaymentList.js @@ -1,13 +1,30 @@ import { _ } from 'frappejs/utils'; +import indicators from 'frappejs/ui/constants/indicators'; export default { doctype: 'Payment', title: _('Payment'), columns: [ 'party', + { + label: 'Payment', + getValue(doc) { + if (doc.submitted === 1 && doc.clearanceDate !== null) { + return 'Reconciled'; + } + return 'Not Reconciled'; + }, + getIndicator(doc) { + if (doc.submitted === 1 && doc.clearanceDate !== null) { + return indicators.GREEN; + } + return indicators.ORANGE; + } + }, 'account', 'amount', 'date', + 'clearanceDate', 'name' ] } \ No newline at end of file diff --git a/models/doctype/SetupWizard/SetupWizard.js b/models/doctype/SetupWizard/SetupWizard.js new file mode 100644 index 00000000..547e26e9 --- /dev/null +++ b/models/doctype/SetupWizard/SetupWizard.js @@ -0,0 +1,102 @@ +const countryList = require('../../../fixtures/countryInfo.json'); + +module.exports = { + name: "SetupWizard", + label: "Setup Wizard", + naming: "name", + isSingle: 1, + isChild: 0, + isSubmittable: 0, + settings: null, + keywordFields: [], + fields: [{ + fieldname: 'country', + label: 'Country', + fieldtype: 'Autocomplete', + required: 1, + getList: () => Object.keys(countryList).sort() + }, + + { + fieldname: 'fullname', + label: 'Name', + fieldtype: 'Data', + required: 1 + }, + + { + fieldname: 'email', + label: 'Email', + fieldtype: 'Data', + required: 1, + inputType: 'email' + }, + + { + fieldname: 'companyName', + label: 'Company Name', + fieldtype: 'Data', + required: 1 + }, + + { + fieldname: 'bankName', + label: 'Bank Name', + fieldtype: 'Data', + required: 1 + }, + + { + fieldname: 'fiscalYearStart', + label: 'Fiscal Year Start Date', + fieldtype: 'Date', + formula: (doc) => { + let date = countryList[doc.country]["fiscal_year_start"].split("-"); + var currentYear = (new Date).getFullYear(); + let currentMonth = date[0] - 1 ; + let currentDate = date[1]; + return new Date(currentYear,currentMonth,currentDate).toISOString().substr(0, 10);; + }, + required: 1 + }, + + { + fieldname: 'fiscalYearEnd', + label: 'Fiscal Year End Date', + fieldtype: 'Date', + formula: (doc) => { + let date = countryList[doc.country]["fiscal_year_end"].split("-"); + var currentYear = (new Date).getFullYear() + 1 ; + let currentMonth = date[0] - 1 ; + let currentDate = date[1]; + return new Date(currentYear,currentMonth,currentDate).toISOString().substr(0, 10);; + }, + required: 1 + } + ], + + layout: { + paginated: true, + sections: [{ + title: 'Select Country', + columns: [{ + fields: ['country'] + }] + }, + + { + title: 'Add a Profile', + columns: [{ + fields: ['fullname', 'email'] + }] + }, + + { + title: 'Add your Company', + columns: [{ + fields: ['companyName', 'bankName', 'fiscalYearStart', 'fiscalYearEnd'] + }] + } + ].filter(Boolean) + } +} diff --git a/models/doctype/Tax/Tax.js b/models/doctype/Tax/Tax.js index 6d7d8af9..2bb02ac9 100644 --- a/models/doctype/Tax/Tax.js +++ b/models/doctype/Tax/Tax.js @@ -1,5 +1,6 @@ module.exports = { "name": "Tax", + "label": "Tax", "doctype": "DocType", "isSingle": 0, "isChild": 0, diff --git a/models/doctype/Tax/TaxList.js b/models/doctype/Tax/TaxList.js new file mode 100644 index 00000000..2bf95864 --- /dev/null +++ b/models/doctype/Tax/TaxList.js @@ -0,0 +1,10 @@ +import { _ } from 'frappejs/utils'; +import indicators from 'frappejs/ui/constants/indicators'; + +export default { + doctype: 'Tax', + title: _('Tax'), + columns: [ + 'name' + ] +} \ No newline at end of file diff --git a/models/doctype/account/importCOA.js b/models/doctype/account/importCOA.js index 4e3359a2..50a1b4c2 100644 --- a/models/doctype/account/importCOA.js +++ b/models/doctype/account/importCOA.js @@ -52,7 +52,7 @@ async function getCountryCOA(){ const conCode = countries[doc.country].code; const countryCOA = path.resolve(path.join('./fixtures/verified/', conCode + '.json')); - + if(fs.existsSync(countryCOA)){ const jsonText = fs.readFileSync(countryCOA, 'utf-8'); const json = JSON.parse(jsonText); diff --git a/models/index.js b/models/index.js index 29ba5d94..ef08d1dd 100644 --- a/models/index.js +++ b/models/index.js @@ -1,9 +1,11 @@ module.exports = { models: { + SetupWizard: require('./doctype/SetupWizard/SetupWizard'), Account: require('./doctype/Account/Account.js'), AccountingSettings: require('./doctype/AccountingSettings/AccountingSettings'), + CompanySettings: require('./doctype/CompanySettings/CompanySettings'), AccountingLedgerEntry: require('./doctype/AccountingLedgerEntry/AccountingLedgerEntry.js'), - Party: require('./doctype/Party/Party.js'), + // Party: require('./doctype/Party/Party.js'), Payment: require('./doctype/Payment/Payment.js'), PaymentFor: require('./doctype/PaymentFor/PaymentFor.js'), @@ -53,5 +55,8 @@ module.exports = { Event: require('./doctype/Event/Event'), EventSchedule: require('./doctype/EventSchedule/EventSchedule'), EventSettings: require('./doctype/EventSettings/EventSettings'), + + Email: require('./doctype/Email/Email'), + EmailAccount: require('./doctype/EmailAccount/EmailAccount'), } -} +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0eb75f01..10d973fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,9 +15,9 @@ "integrity": "sha512-XtGk+IF57pr852UK1AhQJXqmm1WmSgS5uISL+LPs0z/iAxXouMvdlLJrHPeukP6gd7yR2rDTMSMkHNODgwIq7A==" }, "@types/node": { - "version": "8.10.36", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.36.tgz", - "integrity": "sha512-SL6KhfM7PTqiFmbCW3eVNwVBZ+88Mrzbuvn9olPsfv43mbiWaFY+nRcz/TGGku0/lc2FepdMbImdMY1JrQ+zbw==" + "version": "8.10.38", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.38.tgz", + "integrity": "sha512-EibsnbJerd0hBFaDjJStFrVbVBAtOy4dgL8zZFw0uOvPqzBAX59Ci8cgjg3+RgJIWhsB5A4c+pi+D4P9tQQh/A==" }, "@vue/component-compiler-utils": { "version": "2.2.0", @@ -1867,6 +1867,11 @@ "safe-buffer": "^5.0.1" } }, + "clamp": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz", + "integrity": "sha1-ZqDmQBGBbjcZaCj9yMjBRzEshjQ=" + }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -2824,12 +2829,12 @@ "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==" }, "electron": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/electron/-/electron-2.0.12.tgz", - "integrity": "sha512-mw8hoM/GPtFPP8FGiJcVNe8Rx63YJ7O8bf7McQj21HAvrXGAwReGFrpIe5xN6ec10fDXNSNyfzRucjFXtOtLcg==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/electron/-/electron-3.0.12.tgz", + "integrity": "sha512-stvGbqYzWv5qHHtjZZgA7gET3NPGLuxs68IHTrJqsqujQfXGkhMOh8tstpXl86kBdRpzZn7GaDlTWcgeFSmsPw==", "requires": { "@types/node": "^8.0.24", - "electron-download": "^3.0.1", + "electron-download": "^4.1.0", "extract-zip": "^1.0.3" } }, @@ -2902,33 +2907,38 @@ } }, "electron-download": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-3.3.0.tgz", - "integrity": "sha1-LP1U1pZsAZxNSa1l++Zcyc3vaMg=", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-4.1.1.tgz", + "integrity": "sha512-FjEWG9Jb/ppK/2zToP+U5dds114fM1ZOJqMAR4aXXL5CvyPE9fiqBK/9YcwC9poIFQTEJk/EM/zyRwziziRZrg==", "requires": { - "debug": "^2.2.0", - "fs-extra": "^0.30.0", - "home-path": "^1.0.1", + "debug": "^3.0.0", + "env-paths": "^1.0.0", + "fs-extra": "^4.0.1", "minimist": "^1.2.0", - "nugget": "^2.0.0", - "path-exists": "^2.1.0", - "rc": "^1.1.2", - "semver": "^5.3.0", - "sumchecker": "^1.2.0" + "nugget": "^2.0.1", + "path-exists": "^3.0.0", + "rc": "^1.2.1", + "semver": "^5.4.1", + "sumchecker": "^2.0.2" }, "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, "minimist": { "version": "1.2.0", "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "requires": { - "pinkie-promise": "^2.0.0" - } + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" } } }, @@ -3163,6 +3173,11 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" }, + "env-paths": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz", + "integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=" + }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -3539,6 +3554,11 @@ "schema-utils": "^0.4.5" } }, + "file-saver": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.0.tgz", + "integrity": "sha512-cYM1ic5DAkg25pHKgi5f10ziAM7RJU37gaH1XQlyNDrtUnzhC/dfoV9zf2OmF0RMKi42jG5B0JWBnPQqyj/G6g==" + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -3720,13 +3740,13 @@ "mysql": "^2.15.0", "node-fetch": "^1.7.3", "node-sass": "^4.7.2", + "nodemailer": "^4.7.0", "nunjucks": "^3.1.0", "octicons": "^7.2.0", "passport": "^0.4.0", "passport-jwt": "^4.0.0", "puppeteer": "^1.2.0", "sass-loader": "^7.0.3", - "sharp": "^0.20.8", "showdown": "^1.8.6", "socket.io": "^2.0.4", "sqlite3": "^4.0.2", @@ -3738,6 +3758,78 @@ "webpack": "^4.16.1", "webpack-dev-server": "^3.1.4", "webpack-hot-middleware": "^2.22.3" + }, + "dependencies": { + "electron": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/electron/-/electron-2.0.12.tgz", + "integrity": "sha512-mw8hoM/GPtFPP8FGiJcVNe8Rx63YJ7O8bf7McQj21HAvrXGAwReGFrpIe5xN6ec10fDXNSNyfzRucjFXtOtLcg==", + "requires": { + "@types/node": "^8.0.24", + "electron-download": "^3.0.1", + "extract-zip": "^1.0.3" + }, + "dependencies": { + "electron-download": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-3.3.0.tgz", + "integrity": "sha1-LP1U1pZsAZxNSa1l++Zcyc3vaMg=", + "requires": { + "debug": "^2.2.0", + "fs-extra": "^0.30.0", + "home-path": "^1.0.1", + "minimist": "^1.2.0", + "nugget": "^2.0.0", + "path-exists": "^2.1.0", + "rc": "^1.1.2", + "semver": "^5.3.0", + "sumchecker": "^1.2.0" + } + } + } + }, + "fs-extra": { + "version": "0.30.0", + "resolved": "http://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "sumchecker": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-1.3.1.tgz", + "integrity": "sha1-ebs7RFbdBPGOvbwNcDodHa7FEF0=", + "requires": { + "debug": "^2.2.0", + "es6-promise": "^4.0.5" + } + } } }, "fresh": { @@ -3804,15 +3896,13 @@ "integrity": "sha512-2QY5eeqVv4m2PfyMiEuy9adxNP+ajf+8AR05cEi+OAzPcOj90hvFImeZhTmKLBgSd9EvG33jsD7ZRxsx9dThkQ==" }, "fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", "requires": { "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } }, "fs-extra-p": { @@ -5372,9 +5462,9 @@ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" }, "jsonfile": { - "version": "2.4.0", - "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "requires": { "graceful-fs": "^4.1.6" } @@ -5599,6 +5689,11 @@ "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=" }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" + }, "loglevel": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", @@ -5679,6 +5774,11 @@ "object-visit": "^1.0.0" } }, + "material-colors": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", + "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -6157,23 +6257,23 @@ } }, "tar": { - "version": "4.4.6", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.6.tgz", - "integrity": "sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg==", + "version": "4.4.8", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz", + "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "requires": { - "chownr": "^1.0.1", + "chownr": "^1.1.1", "fs-minipass": "^1.2.5", - "minipass": "^2.3.3", - "minizlib": "^1.1.0", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", "mkdirp": "^0.5.0", "safe-buffer": "^5.1.2", "yallist": "^3.0.2" } }, "yallist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" } } }, @@ -6214,6 +6314,11 @@ } } }, + "nodemailer": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.7.0.tgz", + "integrity": "sha512-IludxDypFpYw4xpzKdMAozBSkzKHmNBvGanUREjJItgJ2NYcK/s8+PggVhj7c2yGFQykKsnnmv1+Aqo0ZfjHmw==" + }, "noop-logger": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", @@ -7923,49 +8028,6 @@ } } }, - "sharp": { - "version": "0.20.8", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.20.8.tgz", - "integrity": "sha512-A8NaPGWRDKpmHTi8sl2xzozYXhTQWBb/GaJ8ZPU7L/vKW8wVvd4Yq+isJ0c7p9sX5gnjPQcM3eOfHuvvnZ2fOQ==", - "requires": { - "color": "^3.0.0", - "detect-libc": "^1.0.3", - "fs-copy-file-sync": "^1.1.1", - "nan": "^2.11.0", - "npmlog": "^4.1.2", - "prebuild-install": "^4.0.0", - "semver": "^5.5.1", - "simple-get": "^2.8.1", - "tar": "^4.4.6", - "tunnel-agent": "^0.6.0" - }, - "dependencies": { - "nan": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", - "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==" - }, - "tar": { - "version": "4.4.6", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.6.tgz", - "integrity": "sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg==", - "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.3", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "yallist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" - } - } - }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -8459,9 +8521,9 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sqlite3": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.0.2.tgz", - "integrity": "sha512-51ferIRwYOhzUEtogqOa/y9supADlAht98bF/gbIi6WkzRJX6Yioldxbzj1MV4yV+LgdKD/kkHwFTeFXOG4htA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.0.4.tgz", + "integrity": "sha512-CO8vZMyUXBPC+E3iXOCc7Tz2pAdq5BWfLcQmOokCOZW5S5sZ/paijiPOCdvzpdP83RroWHYa5xYlVqCxSqpnQg==", "requires": { "nan": "~2.10.0", "node-pre-gyp": "^0.10.3", @@ -8632,12 +8694,11 @@ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "sumchecker": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-1.3.1.tgz", - "integrity": "sha1-ebs7RFbdBPGOvbwNcDodHa7FEF0=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-2.0.2.tgz", + "integrity": "sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4=", "requires": { - "debug": "^2.2.0", - "es6-promise": "^4.0.5" + "debug": "^2.2.0" } }, "supports-color": { @@ -8747,6 +8808,11 @@ "setimmediate": "^1.0.4" } }, + "tinycolor2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", + "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" + }, "to-array": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", @@ -9248,6 +9314,17 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-2.5.17.tgz", "integrity": "sha512-mFbcWoDIJi0w0Za4emyLiW72Jae0yjANHbCVquMKijcavBGypqlF7zHRgMa5k4sesdv7hv2rB4JPdZfR+TPfhQ==" }, + "vue-color": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/vue-color/-/vue-color-2.7.0.tgz", + "integrity": "sha512-fak9oPRL3BsYtakTGmWIS2yNRppRYNlMgGGq78CMH34ipU8fLgi/bT9JiSPcscpdTNLGracuOFuZ8OFeml+SQQ==", + "requires": { + "clamp": "^1.0.1", + "lodash.throttle": "^4.0.0", + "material-colors": "^1.0.0", + "tinycolor2": "^1.1.2" + } + }, "vue-flatpickr-component": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/vue-flatpickr-component/-/vue-flatpickr-component-7.0.6.tgz", @@ -9799,4 +9876,4 @@ "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index 64dac8f0..adcc6128 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,7 @@ "dist/electron" ], "dmg": { - "contents": [ - { + "contents": [{ "x": 410, "y": 150, "type": "link", @@ -52,7 +51,7 @@ "scripts": { "test": "mocha tests", "start": "frappe start", - "electron": "cross-env ELECTRON=true frappe start electron", + "electron": "ELECTRON=true frappe start electron", "pack-electron": "cross-env NODE_ENV=production ELECTRON=true frappe build electron", "build-electron": "npm run pack-electron && electron-builder", "postinstall": "electron-builder install-app-deps" @@ -60,7 +59,9 @@ "dependencies": { "cross-env": "^5.2.0", "frappejs": "github:frappe/frappejs", + "nodemailer": "^4.7.0", "popper.js": "^1.14.4", + "vue-color": "^2.7.0", "vue-toasted": "^1.1.25" } -} +} \ No newline at end of file diff --git a/reports/AccountsReceivablePayable/AccountsReceivablePayable.js b/reports/AccountsReceivablePayable/AccountsReceivablePayable.js index 4c0b7ce6..fa628931 100644 --- a/reports/AccountsReceivablePayable/AccountsReceivablePayable.js +++ b/reports/AccountsReceivablePayable/AccountsReceivablePayable.js @@ -29,7 +29,6 @@ async function getReceivablePayable({ reportType = 'Receivable', date }) { let data = []; for (let entry of validEntries) { - // console.log(entry); const { outStandingAmount, creditNoteAmount } = getOutstandingAmount(entry); diff --git a/reports/BankReconciliation/BankReconciliation.js b/reports/BankReconciliation/BankReconciliation.js new file mode 100644 index 00000000..f87e2c41 --- /dev/null +++ b/reports/BankReconciliation/BankReconciliation.js @@ -0,0 +1,42 @@ +const frappe = require('frappejs'); + +class BankReconciliation { + async run(params) { + const filters = {}; + if (params.paymentAccount) filters.paymentAccount = params.paymentAccount; + if (params.party) filters.party = params.party; + // if (params.referenceType) filters.referenceType = params.referenceType; + // if (params.referenceName) filters.referenceName = params.referenceName; + if (params.toDate || params.fromDate) { + filters.date = []; + if (params.toDate) filters.date.push('<=', params.toDate); + if (params.fromDate) filters.date.push('>=', params.fromDate); + } + + let data = await frappe.db.getAll({ + doctype: 'Payment', + fields: ['date', 'account', 'paymentAccount', 'party', 'name', 'referenceDate','clearanceDate'], + filters: filters, + }); + + for (var i = 0; i < data.length; i++) { + let ledger = await frappe.db.getAll({ + doctype: 'AccountingLedgerEntry', + fields: ['date', 'referenceType', 'referenceName', 'debit', 'credit'], + filters: { + referenceType: 'Payment', + account: data[i].paymentAccount, + referenceName: data[i].name + } + }) + data[i].credit = ledger[0].credit; + data[i].debit = ledger[0].debit; + data[i].referenceName = ledger[0].referenceName; + data[i].referenceType = ledger[0].referenceType; + } + + return data; + } +} + +module.exports = BankReconciliation; diff --git a/reports/BankReconciliation/BankReconciliationView.js b/reports/BankReconciliation/BankReconciliationView.js new file mode 100644 index 00000000..6c0ec972 --- /dev/null +++ b/reports/BankReconciliation/BankReconciliationView.js @@ -0,0 +1,80 @@ +const ReportPage = require('frappejs/client/desk/reportpage'); +const frappe = require('frappejs'); + +module.exports = class BankReconciliationView extends ReportPage { + constructor() { + super({ + title: frappe._('Bank Reconciliation'), + filterFields: [{ + fieldtype: 'Link', + target: 'Account', + label: 'Payment Account' + }, + { + fieldtype: 'Link', + target: 'Party', + label: 'Party' + }, + { + fieldtype: 'Date', + label: 'From Date' + }, + { + fieldtype: 'Date', + label: 'To Date' + } + ] + }); + + this.method = 'bank-reconciliation'; + } + + getColumns() { + return [{ + label: 'Posting Date', + fieldtype: 'Date', + fieldname: 'date' + }, + { + label: 'Payment Account', + fieldtype: 'Link' + }, + { + label: 'Debit', + fieldtype: 'Currency' + }, + { + label: 'Credit', + fieldtype: 'Currency' + }, + { + label: 'Balance', + fieldtype: 'Currency' + }, + { + label: 'Ref. Type', + fieldtype: 'Data', + fieldname: 'referenceType' + }, + { + label: 'Ref. Name', + fieldtype: 'Data', + fieldname: 'referenceName' + }, + { + label: 'Ref. Date', + fieldtype: 'Date', + fieldname: 'referenceDate' + }, + { + label: 'Clearance Date', + fieldtype: 'Date', + fieldname: 'clearanceDate' + }, + { + label: 'Party', + fieldtype: 'Link' + } + ]; + } +}; diff --git a/reports/BankReconciliation/viewConfig.js b/reports/BankReconciliation/viewConfig.js new file mode 100644 index 00000000..6fc88d23 --- /dev/null +++ b/reports/BankReconciliation/viewConfig.js @@ -0,0 +1,76 @@ +const title = 'Bank Reconciliation'; +module.exports = { + title: title, + method: 'bank-reconciliation', + filterFields: [{ + fieldtype: 'Link', + target: 'Account', + label: 'Payement Account', + fieldname: 'paymentAccount' + }, + { + fieldtype: 'Link', + target: 'Party', + label: 'Party', + fieldname: 'party' + }, + { + fieldtype: 'Date', + label: 'From Date', + fieldname: 'fromDate' + }, + { + fieldtype: 'Date', + label: 'To Date', + fieldname: 'toDate' + } + ], + getColumns() { + return [{ + label: 'Posting Date', + fieldtype: 'Date', + fieldname: 'date' + }, + { + label: 'Payment Account', + fieldtype: 'Link' + }, + { + label: 'Debit', + fieldtype: 'Currency' + }, + { + label: 'Credit', + fieldtype: 'Currency' + }, + { + label: 'Balance', + fieldtype: 'Currency' + }, + { + label: 'Ref. Type', + fieldtype: 'Data', + fieldname: 'referenceType' + }, + { + label: 'Ref. Name', + fieldtype: 'Data', + fieldname: 'referenceName' + }, + { + label: 'Ref. Date', + fieldtype: 'Date', + fieldname: 'referenceDate' + }, + { + label: 'Clearance Date', + fieldtype: 'Date', + fieldname: 'clearanceDate' + }, + { + label: 'Party', + fieldtype: 'Link' + } + ]; + } +}; diff --git a/reports/GeneralLedger/GeneralLedger.js b/reports/GeneralLedger/GeneralLedger.js index 722d7045..b203f4d6 100644 --- a/reports/GeneralLedger/GeneralLedger.js +++ b/reports/GeneralLedger/GeneralLedger.js @@ -12,7 +12,6 @@ class GeneralLedger { if (params.toDate) filters.date.push('<=', params.toDate); if (params.fromDate) filters.date.push('>=', params.fromDate); } - let data = await frappe.db.getAll({ doctype: 'AccountingLedgerEntry', fields: ['date', 'account', 'party', 'referenceType', 'referenceName', 'debit', 'credit'], diff --git a/reports/GeneralLedger/GeneralLedgerView.js b/reports/GeneralLedger/GeneralLedgerView.js index 0fd85946..6338112b 100644 --- a/reports/GeneralLedger/GeneralLedgerView.js +++ b/reports/GeneralLedger/GeneralLedgerView.js @@ -5,8 +5,7 @@ module.exports = class GeneralLedgerView extends ReportPage { constructor() { super({ title: frappe._('General Ledger'), - filterFields: [ - { + filterFields: [{ fieldtype: 'Select', options: ['', 'Invoice', 'Payment'], label: 'Reference Type', @@ -43,16 +42,42 @@ module.exports = class GeneralLedgerView extends ReportPage { } getColumns() { - return [ - {label: 'Date', fieldtype: 'Date'}, - {label: 'Account', fieldtype: 'Link'}, - {label: 'Debit', fieldtype: 'Currency'}, - {label: 'Credit', fieldtype: 'Currency'}, - {label: 'Balance', fieldtype: 'Currency'}, - {label: 'Reference Type', fieldtype: 'Data'}, - {label: 'Reference Name', fieldtype: 'Data'}, - {label: 'Party', fieldtype: 'Link'}, - {label: 'Description', fieldtype: 'Data'} + return [{ + label: 'Date', + fieldtype: 'Date' + }, + { + label: 'Account', + fieldtype: 'Link' + }, + { + label: 'Debit', + fieldtype: 'Currency' + }, + { + label: 'Credit', + fieldtype: 'Currency' + }, + { + label: 'Balance', + fieldtype: 'Currency' + }, + { + label: 'Reference Type', + fieldtype: 'Data' + }, + { + label: 'Reference Name', + fieldtype: 'Data' + }, + { + label: 'Party', + fieldtype: 'Link' + }, + { + label: 'Description', + fieldtype: 'Data' + } ]; } }; diff --git a/reports/GeneralLedger/viewConfig.js b/reports/GeneralLedger/viewConfig.js index 38c41764..bec82bba 100644 --- a/reports/GeneralLedger/viewConfig.js +++ b/reports/GeneralLedger/viewConfig.js @@ -2,8 +2,7 @@ const title = 'General Ledger'; module.exports = { title: title, method: 'general-ledger', - filterFields: [ - { + filterFields: [{ fieldtype: 'Select', options: ['', 'Invoice', 'Payment'], label: 'Reference Type', @@ -15,22 +14,66 @@ module.exports = { label: 'Reference Name', fieldname: 'referenceName' }, - { fieldtype: 'Link', target: 'Account', label: 'Account', fieldname: 'account' }, - { fieldtype: 'Link', target: 'Party', label: 'Party', fieldname: 'party' }, - { fieldtype: 'Date', label: 'From Date', fieldname: 'fromDate' }, - { fieldtype: 'Date', label: 'To Date', fieldname: 'toDate' } + { + fieldtype: 'Link', + target: 'Account', + label: 'Account', + fieldname: 'account' + }, + { + fieldtype: 'Link', + target: 'Party', + label: 'Party', + fieldname: 'party' + }, + { + fieldtype: 'Date', + label: 'From Date', + fieldname: 'fromDate' + }, + { + fieldtype: 'Date', + label: 'To Date', + fieldname: 'toDate' + } ], getColumns() { - return [ - { label: 'Date', fieldtype: 'Date' }, - { label: 'Account', fieldtype: 'Link' }, - { label: 'Debit', fieldtype: 'Currency' }, - { label: 'Credit', fieldtype: 'Currency' }, - { label: 'Balance', fieldtype: 'Currency' }, - { label: 'Reference Type', fieldtype: 'Data' }, - { label: 'Reference Name', fieldtype: 'Data' }, - { label: 'Party', fieldtype: 'Link' }, - { label: 'Description', fieldtype: 'Data' } + return [{ + label: 'Date', + fieldtype: 'Date' + }, + { + label: 'Account', + fieldtype: 'Link' + }, + { + label: 'Debit', + fieldtype: 'Currency' + }, + { + label: 'Credit', + fieldtype: 'Currency' + }, + { + label: 'Balance', + fieldtype: 'Currency' + }, + { + label: 'Reference Type', + fieldtype: 'Data' + }, + { + label: 'Reference Name', + fieldtype: 'Data' + }, + { + label: 'Party', + fieldtype: 'Link' + }, + { + label: 'Description', + fieldtype: 'Data' + } ]; } }; diff --git a/reports/GoodsAndServiceTax/GoodsAndServiceTax.js b/reports/GoodsAndServiceTax/GoodsAndServiceTax.js new file mode 100644 index 00000000..88bbff61 --- /dev/null +++ b/reports/GoodsAndServiceTax/GoodsAndServiceTax.js @@ -0,0 +1,59 @@ +const frappe = require('frappejs'); + +class GoodsAndServiceTax { + async run(params) { + let filters = {}; + if (params.toDate || params.fromDate) { + filters.date = []; + if (params.toDate) filters.date.push('<=', params.toDate); + if (params.fromDate) filters.date.push('>=', params.fromDate); + } + if (params.transferType) filters.transferType = params.transferType; + + let invoiceNames = await frappe.db.getAll({ + doctype: 'Invoice', + filter: filters + }); + + let tableData = []; + for (let invoice of invoiceNames) { + const row = await this.getRow(invoice.name) + tableData.push(row) + } + + if(Object.keys(filters).length != 0){ + tableData = tableData.filter((row) => { + if(filters.account) return row.account === filters.account + if(filters.transferType) return row.transferType === filters.transferType + if(filters.place) return row.place === filters.place + return true + }) + } + + return tableData; + } + + async getRow(name) { + let row = {} + let invoiceDetails = await frappe.getDoc('Invoice', name); + let customerDetails = await frappe.getDoc('Party', invoiceDetails.customer); + let addressDetails = await frappe.getDoc('Address', customerDetails.address); + row.gstin = customerDetails.gstin + row.cusName = invoiceDetails.customer + row.invNo = invoiceDetails.name + row.invDate = invoiceDetails.date + row.place = addressDetails.state + row.rate = 0 + row.transferType = 'In State'; + invoiceDetails.taxes.forEach(tax => { + row.rate += tax.rate + if (tax.account === 'IGST') row.transferType = 'Out of State'; + }); + row.invAmt = invoiceDetails.grandTotal + row.taxAmt = invoiceDetails.netTotal + return row + } + +} + +module.exports = GoodsAndServiceTax; diff --git a/reports/GoodsAndServiceTax/GoodsAndServiceTaxView.js b/reports/GoodsAndServiceTax/GoodsAndServiceTaxView.js new file mode 100644 index 00000000..1d705096 --- /dev/null +++ b/reports/GoodsAndServiceTax/GoodsAndServiceTaxView.js @@ -0,0 +1,74 @@ +const ReportPage = require('frappejs/client/desk/reportpage'); +const frappe = require('frappejs'); + +module.exports = class GoodsAndServiceTaxView extends ReportPage { + constructor() { + super({ + title: frappe._('Goods and Service Tax'), + filterFields: [ + { + fieldtype: 'Data', + label: 'Transfer Type' + }, + { + fieldtype: 'Data', + label: 'Place' + }, + { + fieldtype: 'Date', + label: 'From Date' + }, + { + fieldtype: 'Date', + label: 'To Date' + } + ] + }); + + this.method = 'gst-taxes'; + } + + getColumns() { + return [{ + label: 'GSTIN No.', + fieldname: 'gstin', + fieldtype: 'Data' + }, + { + fieldtype: 'Data', + fieldname: 'cusName', + label: 'Customer Name' + }, + { + label: 'Invoice No.', + fieldname: 'invNo', + fieldtype: 'Data' + }, + { + label: 'Invoice Value', + fieldname: 'invAmt', + fieldtype: 'Data' + }, + { + label: 'Invoice Date', + fieldname: 'invDate', + fieldtype: 'Date' + }, + { + label: 'Place of supply', + fieldname: 'place', + fieldtype: 'Data' + }, + { + label: 'Rate', + fieldname: 'rate', + fieldtype: 'Data' + }, + { + label: 'Taxable Amount', + fieldname: 'taxAmt', + fieldtype: 'Data' + } + ]; + } +}; diff --git a/reports/GoodsAndServiceTax/viewConfig.js b/reports/GoodsAndServiceTax/viewConfig.js new file mode 100644 index 00000000..924aca9a --- /dev/null +++ b/reports/GoodsAndServiceTax/viewConfig.js @@ -0,0 +1,69 @@ +const title = 'Goods and Service Tax'; +module.exports = { + title: title, + method: 'gst-taxes', + filterFields: [{ + fieldtype: 'Data', + label: 'Transfer Type', + fieldname: 'transferType' + }, + { + fieldtype: 'Data', + label: 'Place', + fieldname: 'place' + }, + { + fieldtype: 'Date', + label: 'From Date', + fieldname: 'fromDate' + }, + { + fieldtype: 'Date', + label: 'To Date', + fieldname: 'toDate' + }], + + getColumns() { + return [{ + label: 'GSTIN No.', + fieldname: 'gstin', + fieldtype: 'Data' + }, + { + fieldtype: 'Data', + fieldname: 'cusName', + label: 'Customer Name' + }, + { + label: 'Invoice No.', + fieldname: 'invNo', + fieldtype: 'Data' + }, + { + label: 'Invoice Value', + fieldname: 'invAmt', + fieldtype: 'Data' + }, + { + label: 'Invoice Date', + fieldname: 'invDate', + fieldtype: 'Date' + }, + { + label: 'Place of supply', + fieldname: 'place', + fieldtype: 'Data' + }, + { + label: 'Rate', + fieldname: 'rate', + fieldtype: 'Data' + }, + { + label: 'Taxable Amount', + fieldname: 'taxAmt', + fieldtype: 'Data' + } + ]; + } +}; \ No newline at end of file diff --git a/reports/index.js b/reports/index.js index 385b8551..b4718eaa 100644 --- a/reports/index.js +++ b/reports/index.js @@ -5,12 +5,13 @@ const BalanceSheet = require('./BalanceSheet/BalanceSheet'); const TrialBalance = require('./TrialBalance/TrialBalance'); const SalesRegister = require('./SalesRegister/SalesRegister'); const PurchaseRegister = require('./PurchaseRegister/PurchaseRegister'); +const BankReconciliation = require('./BankReconciliation/BankReconciliation'); +const GoodsAndServiceTax = require('./GoodsAndServiceTax/GoodsAndServiceTax'); const AccountsReceivablePayable = require('./AccountsReceivablePayable/AccountsReceivablePayable'); // called on server side function registerReportMethods() { - const reports = [ - { + const reports = [{ method: 'general-ledger', class: GeneralLedger }, @@ -33,7 +34,15 @@ function registerReportMethods() { { method: 'purchase-register', class: PurchaseRegister - } + }, + { + method: 'bank-reconciliation', + class: BankReconciliation + }, + { + method: 'gst-taxes', + class: GoodsAndServiceTax + }, ]; reports.forEach(report => { diff --git a/reports/view.js b/reports/view.js index fed283d4..e70cbcaf 100644 --- a/reports/view.js +++ b/reports/view.js @@ -2,5 +2,7 @@ module.exports = { 'general-ledger': require('./GeneralLedger/viewConfig'), 'sales-register': require('./SalesRegister/viewConfig'), 'profit-and-loss': require('./ProfitAndLoss/viewConfig'), - 'trial-balance': require('./TrialBalance/viewConfig') + 'trial-balance': require('./TrialBalance/viewConfig'), + 'bank-reconciliation': require('./BankReconciliation/viewConfig'), + 'gst-taxes': require('./GoodsAndServiceTax/viewConfig'), } diff --git a/server/registerServerMethods.js b/server/registerServerMethods.js index 436f6589..5eed5ec1 100644 --- a/server/registerServerMethods.js +++ b/server/registerServerMethods.js @@ -1,9 +1,15 @@ const frappe = require('frappejs'); const registerReportMethods = require('../reports'); +const sender = require('../email/sender'); module.exports = function registerServerMethods() { registerReportMethods(); + frappe.registerMethod({ + method: 'send-mail', + handler: sender.sendMail + }); + frappe.registerMethod({ method: 'import-coa', async handler() { @@ -19,7 +25,7 @@ module.exports = function registerServerMethods() { const path = require('path'); const { getPDFForElectron } = require('frappejs/server/pdf'); const { getSettings } = require('../electron/settings'); - const destination = path.resolve(getSettings().dbPath, '..') + const destination = path.resolve('.') getPDFForElectron(doctype, name, destination, html); } } diff --git a/src-electron/main.js b/src-electron/main.js index 6fb75ba9..7e0d0dca 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -1,4 +1,7 @@ -const { app, BrowserWindow } = require('electron'); +const { + app, + BrowserWindow +} = require('electron'); const setupMenu = require('./menu'); let mainWindow @@ -9,7 +12,9 @@ if (process.env.NODE_ENV !== 'development') { } if (process.env.NODE_ENV === 'development') { - const { getAppConfig } = require('frappejs/webpack/utils'); + const { + getAppConfig + } = require('frappejs/webpack/utils'); const appConfig = getAppConfig(); winURL = `http://localhost:${appConfig.dev.devServerPort}`; } else { @@ -20,6 +25,7 @@ function createWindow() { /** * Initial window options */ + mainWindow = new BrowserWindow({ width: 1024, height: 768, diff --git a/src/components/ExportWizard.vue b/src/components/ExportWizard.vue new file mode 100644 index 00000000..e104028a --- /dev/null +++ b/src/components/ExportWizard.vue @@ -0,0 +1,113 @@ + + + diff --git a/src/components/InvoiceCustomizer.vue b/src/components/InvoiceCustomizer.vue new file mode 100644 index 00000000..81fc40e5 --- /dev/null +++ b/src/components/InvoiceCustomizer.vue @@ -0,0 +1,71 @@ + + diff --git a/src/components/PageHeader.vue b/src/components/PageHeader.vue index fe51f1b6..a149bee1 100644 --- a/src/components/PageHeader.vue +++ b/src/components/PageHeader.vue @@ -6,7 +6,7 @@ diff --git a/src/pages/ChartOfAccounts/index.vue b/src/pages/ChartOfAccounts/index.vue new file mode 100644 index 00000000..4f6820b9 --- /dev/null +++ b/src/pages/ChartOfAccounts/index.vue @@ -0,0 +1,50 @@ + + diff --git a/src/pages/Email/EmailSend.vue b/src/pages/Email/EmailSend.vue new file mode 100644 index 00000000..bb70a7e8 --- /dev/null +++ b/src/pages/Email/EmailSend.vue @@ -0,0 +1,47 @@ + + + \ No newline at end of file diff --git a/src/pages/Email/EmailSendActions.vue b/src/pages/Email/EmailSendActions.vue new file mode 100644 index 00000000..0a9f3ae0 --- /dev/null +++ b/src/pages/Email/EmailSendActions.vue @@ -0,0 +1,25 @@ + + \ No newline at end of file diff --git a/src/pages/FormView/FormView.vue b/src/pages/FormView/FormView.vue index 2e851635..b9315905 100644 --- a/src/pages/FormView/FormView.vue +++ b/src/pages/FormView/FormView.vue @@ -1,6 +1,5 @@