mirror of
https://github.com/frappe/books.git
synced 2024-11-09 23:30:56 +00:00
Merge branch 'pratu16x7-dev' into electronify
This commit is contained in:
commit
29a666b60e
@ -7,24 +7,24 @@ module.exports = class LedgerPosting {
|
||||
this.entryMap = {};
|
||||
}
|
||||
|
||||
debit(account, amount) {
|
||||
const entry = this.getEntry(account);
|
||||
debit(account, amount, referenceType, referenceName) {
|
||||
const entry = this.getEntry(account, referenceType, referenceName);
|
||||
entry.debit += amount;
|
||||
}
|
||||
|
||||
credit(account, amount) {
|
||||
const entry = this.getEntry(account);
|
||||
credit(account, amount, referenceType, referenceName) {
|
||||
const entry = this.getEntry(account, referenceType, referenceName);
|
||||
entry.credit += amount;
|
||||
}
|
||||
|
||||
getEntry(account) {
|
||||
getEntry(account, referenceType, referenceName) {
|
||||
if (!this.entryMap[account]) {
|
||||
const entry = {
|
||||
account: account,
|
||||
party: this.party,
|
||||
date: this.date || this.reference.date,
|
||||
referenceType: this.reference.doctype,
|
||||
referenceName: this.reference.name,
|
||||
referenceType: referenceType || this.reference.doctype,
|
||||
referenceName: referenceName || this.reference.name,
|
||||
description: this.description,
|
||||
debit: 0,
|
||||
credit: 0
|
||||
|
17
accounting/utils.js
Normal file
17
accounting/utils.js
Normal file
@ -0,0 +1,17 @@
|
||||
module.exports = {
|
||||
ledgerLink: {
|
||||
label: 'Ledger Entries',
|
||||
condition: form => form.doc.submitted,
|
||||
action: form => {
|
||||
return {
|
||||
route: ['report', 'general-ledger'],
|
||||
params: {
|
||||
filters: {
|
||||
referenceType: form.doc.doctype,
|
||||
referenceName: form.doc.name
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
const GeneralLedgerView = require('../reports/GeneralLedgerView');
|
||||
const GeneralLedgerView = require('../reports/generalLedger/GeneralLedgerView');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
module.exports = {
|
||||
@ -9,10 +9,6 @@ module.exports = {
|
||||
frappe.registerView('List', 'ToDo', require('frappejs/models/doctype/ToDo/ToDoList.js'));
|
||||
frappe.registerView('Form', 'FilterSelector', require('frappejs/models/doctype/FilterSelector/FilterSelectorForm.js'));
|
||||
|
||||
frappe.registerView('List', 'Account', require('../models/doctype/Account/AccountList.js'));
|
||||
frappe.registerView('Form', 'Account', require('../models/doctype/Account/AccountForm.js'));
|
||||
|
||||
frappe.registerView('List', 'Invoice', require('../models/doctype/Invoice/InvoiceList.js'));
|
||||
frappe.registerView('List', 'Customer', require('../models/doctype/Party/CustomerList.js'));
|
||||
|
||||
frappe.router.add('report/general-ledger', async (params) => {
|
||||
@ -27,6 +23,8 @@ module.exports = {
|
||||
frappe.desk.menu.addItem('Items', '#list/Item');
|
||||
frappe.desk.menu.addItem('Customers', '#list/Customer');
|
||||
frappe.desk.menu.addItem('Invoice', '#list/Invoice');
|
||||
frappe.desk.menu.addItem('Address', "#list/Address");
|
||||
frappe.desk.menu.addItem('Contact', "#list/Contact");
|
||||
frappe.desk.menu.addItem('Settings', () => frappe.desk.showFormModal('SystemSettings'));
|
||||
|
||||
frappe.router.default = '#list/ToDo';
|
||||
|
@ -18,7 +18,13 @@ module.exports = {
|
||||
"fieldname": "parent_account",
|
||||
"label": "Parent Account",
|
||||
"fieldtype": "Link",
|
||||
"target": "Account"
|
||||
"target": "Account",
|
||||
getFilters: (query, control) => {
|
||||
return {
|
||||
keywords: ["like", query],
|
||||
name: ["!=", control.doc.name]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"fieldname": "account_type",
|
||||
@ -38,5 +44,14 @@ module.exports = {
|
||||
validate: (doc) => {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
listSettings: {
|
||||
getFields(list) {
|
||||
return ['name', 'account_type'];
|
||||
},
|
||||
getRowHTML(list, data) {
|
||||
return `<div class="col-11">${list.getNameHTML(data)} (${data.account_type})</div>`;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
const BaseForm = require('frappejs/client/view/form');
|
||||
|
||||
module.exports = class AccountForm extends BaseForm {
|
||||
make() {
|
||||
super.make();
|
||||
|
||||
// override controller event
|
||||
this.controls['parent_account'].getFilters = (query) => {
|
||||
return {
|
||||
keywords: ["like", query],
|
||||
name: ["!=", this.doc.name]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
const BaseList = require('frappejs/client/view/list');
|
||||
|
||||
module.exports = class AccountList extends BaseList {
|
||||
getFields() {
|
||||
return ['name', 'account_type'];
|
||||
}
|
||||
getRowHTML(data) {
|
||||
return `<div class="col-11">${this.getNameHTML(data)} (${data.account_type})</div>`;
|
||||
}
|
||||
}
|
@ -59,7 +59,7 @@ module.exports = {
|
||||
{
|
||||
fieldname: "referenceName",
|
||||
label: "Reference Name",
|
||||
fieldtype: "Dynamic Link",
|
||||
fieldtype: "DynamicLink",
|
||||
references: "referenceType"
|
||||
},
|
||||
{
|
||||
|
24
models/doctype/AccountingSettings/AccountingSettings.js
Normal file
24
models/doctype/AccountingSettings/AccountingSettings.js
Normal file
@ -0,0 +1,24 @@
|
||||
module.exports = {
|
||||
name: "AccountingSettings",
|
||||
label: "AccountingSettings",
|
||||
naming: "name", // {random|autoincrement}
|
||||
isSingle: 1,
|
||||
isChild: 0,
|
||||
isSubmittable: 0,
|
||||
settings: null,
|
||||
keywordFields: [],
|
||||
fields: [
|
||||
{
|
||||
fieldname: "Company Name",
|
||||
label: "companyName",
|
||||
fieldtype: "Data",
|
||||
required: 1
|
||||
},
|
||||
{
|
||||
fieldname: "Writeoff Account",
|
||||
label: "writeOffAccount",
|
||||
fieldtype: "Account"
|
||||
}
|
||||
|
||||
]
|
||||
}
|
125
models/doctype/Address/Address.js
Normal file
125
models/doctype/Address/Address.js
Normal file
@ -0,0 +1,125 @@
|
||||
module.exports = {
|
||||
"name": "Address",
|
||||
"doctype": "DocType",
|
||||
"isSingle": 0,
|
||||
"titleField": "addressTitle",
|
||||
"keywordFields": [
|
||||
"addressTitle"
|
||||
],
|
||||
pageSettings: {
|
||||
hideTitle: true
|
||||
},
|
||||
"naming": "autoincrement",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "addressTitle",
|
||||
"label": "Address Title",
|
||||
"fieldtype": "Data",
|
||||
"required": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "addressType",
|
||||
"label": "Address Type",
|
||||
"fieldtype": "Select",
|
||||
"options": [
|
||||
"Billing", "Shipping", "Office",
|
||||
"Personal", "Plant", "Postal",
|
||||
"Shop", "Subsidary", "Warehouse",
|
||||
"Current", "Permanent", "Other"
|
||||
]
|
||||
},
|
||||
{
|
||||
"fieldname": "addressLine1",
|
||||
"label": "Address Line 1",
|
||||
"fieldtype": "Data",
|
||||
"required": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "addressLine2",
|
||||
"label": "Address Line 2",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldname": "city",
|
||||
"label": "City / Town",
|
||||
"fieldtype": "Data",
|
||||
"required": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "county",
|
||||
"label": "County",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldname": "state",
|
||||
"label": "State",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldname": "country",
|
||||
"label": "Country",
|
||||
"fieldtype": "Data",
|
||||
"required": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "postalCode",
|
||||
"label": "Postal Code",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldname": "emailAddress",
|
||||
"label": "Email Address",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldname": "phone",
|
||||
"label": "Phone",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldname": "fax",
|
||||
"label": "Fax",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldname": "isPreferredBilling",
|
||||
"label": "Preferred Billing Address",
|
||||
"fieldtype": "Check"
|
||||
},
|
||||
{
|
||||
"fieldname": "isShippingBilling",
|
||||
"label": "Preferred Shipping Address",
|
||||
"fieldtype": "Check"
|
||||
}
|
||||
],
|
||||
|
||||
events: {
|
||||
validate: (doc) => {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
listSettings: {
|
||||
getFields(list) {
|
||||
return ['addressTitle', 'addressType'];
|
||||
},
|
||||
getRowHTML(list, data) {
|
||||
console.log(list, data);
|
||||
return `<div class="col-11">${list.getNameHTML(data)} (${data.addressType})</div>`;
|
||||
}
|
||||
},
|
||||
|
||||
layout: [
|
||||
// section 1
|
||||
{
|
||||
columns: [
|
||||
{
|
||||
fields: [ "addressTitle", "addressType", "addressLine1",
|
||||
"addressLine2", "city", "county", "state", "country",
|
||||
"postalCode"]
|
||||
},
|
||||
{ fields: [ "emailAddress", "phone", "fax", "isPreferredBilling", "isShippingBilling" ] }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
82
models/doctype/Contact/Contact.js
Normal file
82
models/doctype/Contact/Contact.js
Normal file
@ -0,0 +1,82 @@
|
||||
module.exports = {
|
||||
"name": "Contact",
|
||||
"doctype": "DocType",
|
||||
"isSingle": 0,
|
||||
"naming": "autoincrement",
|
||||
"pageSettings": {
|
||||
"hideTitle": true
|
||||
},
|
||||
"titleField": "fullName",
|
||||
"keywordFields": [
|
||||
"fullName"
|
||||
],
|
||||
"titleField": "fullName",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "fullName",
|
||||
"label": "Full Name",
|
||||
"fieldtype": "Data",
|
||||
"required": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "emailAddress",
|
||||
"label": "Email Address",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldname": "userId",
|
||||
"label": "User ID",
|
||||
"fieldtype": "Link",
|
||||
"target": "User",
|
||||
"hidden": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "status",
|
||||
"label": "Status",
|
||||
"fieldtype": "Select",
|
||||
"options": ["Passive", "Open", "Replied"]
|
||||
},
|
||||
{
|
||||
"fieldname": "gender",
|
||||
"label": "Gender",
|
||||
"fieldtype": "Select",
|
||||
"options": ["Male", "Female", "Gender"]
|
||||
},
|
||||
{
|
||||
"fieldname": "mobileNumber",
|
||||
"label": "Mobile Number",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldname": "phone",
|
||||
"label": "Phone",
|
||||
"fieldtype": "Data"
|
||||
}
|
||||
],
|
||||
|
||||
events: {
|
||||
validate: (doc) => {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
listSettings: {
|
||||
getFields(list) {
|
||||
return ['fullName'];
|
||||
},
|
||||
getRowHTML(list, data) {
|
||||
console.log(list, data);
|
||||
return `<div class="col-11">${list.getNameHTML(data)}</div>`;
|
||||
}
|
||||
},
|
||||
|
||||
layout: [
|
||||
// section 1
|
||||
{
|
||||
columns: [
|
||||
{ fields: [ "fullName", "emailAddress", "userId", "status" ] },
|
||||
{ fields: [ "postalCode", "gender", "phone", "mobileNumber" ] }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
const frappe = require('frappejs');
|
||||
const utils = require('../../../accounting/utils');
|
||||
|
||||
module.exports = {
|
||||
"name": "Invoice",
|
||||
@ -100,20 +101,29 @@ module.exports = {
|
||||
],
|
||||
|
||||
links: [
|
||||
utils.ledgerLink,
|
||||
{
|
||||
label: 'Ledger Entries',
|
||||
condition: (form) => form.doc.submitted,
|
||||
action:(form) => {
|
||||
return {
|
||||
route: ['table', 'AccountingLedgerEntry'],
|
||||
params: {
|
||||
filters: {
|
||||
referenceType: 'Invoice',
|
||||
referenceName: form.doc.name
|
||||
}
|
||||
}
|
||||
};
|
||||
label: 'Make Payment',
|
||||
condition: form => form.doc.submitted,
|
||||
action: async form => {
|
||||
const payment = await frappe.getNewDoc('Payment');
|
||||
payment.party = form.doc.customer,
|
||||
payment.account = form.doc.account,
|
||||
payment.for = [{referenceType: form.doc.doctype, referenceName: form.doc.name, amount: form.doc.grandTotal}]
|
||||
const formModal = await frappe.desk.showFormModal('Payment', payment.name);
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
|
||||
listSettings: {
|
||||
getFields(list) {
|
||||
return ['name', 'customer', 'grandTotal', 'submitted'];
|
||||
},
|
||||
|
||||
getRowHTML(list, data) {
|
||||
return `<div class="col-3">${list.getNameHTML(data)}</div>
|
||||
<div class="col-4 text-muted">${data.customer}</div>
|
||||
<div class="col-4 text-muted text-right">${frappe.format(data.grandTotal, "Currency")}</div>`;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
const BaseList = require('frappejs/client/view/list');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
module.exports = class InvoiceList extends BaseList {
|
||||
getFields() {
|
||||
return ['name', 'customer', 'grandTotal', 'submitted'];
|
||||
}
|
||||
getRowHTML(data) {
|
||||
return `<div class="col-3">${this.getNameHTML(data)}</div>
|
||||
<div class="col-4 text-muted">${data.customer}</div>
|
||||
<div class="col-4 text-muted text-right">${frappe.format(data.grandTotal, "Currency")}</div>`;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
const Invoice = require('./invoiceDocument');
|
||||
const Invoice = require('./InvoiceDocument');
|
||||
const frappe = require('frappejs');
|
||||
const LedgerPosting = require.main.require('./accounting/ledgerPosting');
|
||||
|
||||
|
@ -11,7 +11,8 @@ module.exports = {
|
||||
"label": "Number Series",
|
||||
"fieldtype": "Link",
|
||||
"target": "NumberSeries",
|
||||
"required": 1
|
||||
"required": 1,
|
||||
"default": "INV"
|
||||
}
|
||||
]
|
||||
}
|
78
models/doctype/Payment/Payment.js
Normal file
78
models/doctype/Payment/Payment.js
Normal file
@ -0,0 +1,78 @@
|
||||
const utils = require('../../../accounting/utils');
|
||||
|
||||
module.exports = {
|
||||
name: "Payment",
|
||||
label: "Payment",
|
||||
isSingle: 0,
|
||||
isChild: 0,
|
||||
isSubmittable: 1,
|
||||
keywordFields: [],
|
||||
settings: "PaymentSettings",
|
||||
fields: [
|
||||
{
|
||||
"fieldname": "date",
|
||||
"label": "Date",
|
||||
"fieldtype": "Date"
|
||||
},
|
||||
{
|
||||
fieldname: "party",
|
||||
label: "Party",
|
||||
fieldtype: "Link",
|
||||
target: "Party",
|
||||
required: 1
|
||||
},
|
||||
{
|
||||
fieldname: "account",
|
||||
label: "Account",
|
||||
fieldtype: "Link",
|
||||
target: "Account",
|
||||
required: 1
|
||||
},
|
||||
{
|
||||
fieldname: "paymentAccount",
|
||||
label: "Payment Account",
|
||||
fieldtype: "Link",
|
||||
target: "Account",
|
||||
required: 1
|
||||
},
|
||||
{
|
||||
fieldname: "amount",
|
||||
label: "Amount",
|
||||
fieldtype: "Currency",
|
||||
required: 1,
|
||||
disabled: true,
|
||||
formula: (doc) => doc.getSum('for', 'amount')
|
||||
},
|
||||
{
|
||||
fieldname: "writeoff",
|
||||
label: "Write Off / Refund",
|
||||
fieldtype: "Currency",
|
||||
},
|
||||
{
|
||||
fieldname: "for",
|
||||
label: "Payment For",
|
||||
fieldtype: "Table",
|
||||
childtype: "PaymentFor",
|
||||
required: 1
|
||||
}
|
||||
],
|
||||
|
||||
layout: [
|
||||
{
|
||||
columns: [
|
||||
{ fields: ['date', 'party'] },
|
||||
{ fields: ['account', 'paymentAccount'] },
|
||||
]
|
||||
},
|
||||
{
|
||||
fields: ['for']
|
||||
},
|
||||
{
|
||||
fields: ['amount', 'writeoff']
|
||||
}
|
||||
],
|
||||
|
||||
links: [
|
||||
utils.ledgerLink
|
||||
]
|
||||
}
|
25
models/doctype/Payment/PaymentServer.js
Normal file
25
models/doctype/Payment/PaymentServer.js
Normal file
@ -0,0 +1,25 @@
|
||||
const BaseDocument = require('frappejs/model/document');
|
||||
const frappe = require('frappejs');
|
||||
const LedgerPosting = require.main.require('./accounting/ledgerPosting');
|
||||
|
||||
module.exports = class PaymentServer extends BaseDocument {
|
||||
getPosting() {
|
||||
let entries = new LedgerPosting({reference: this, party: this.party});
|
||||
entries.debit(this.paymentAccount, this.amount);
|
||||
|
||||
for (let row of this.for) {
|
||||
entries.credit(this.account, row.amount, row.referenceType, row.referenceName);
|
||||
}
|
||||
|
||||
return entries;
|
||||
|
||||
}
|
||||
|
||||
async afterSubmit() {
|
||||
await this.getPosting().post();
|
||||
}
|
||||
|
||||
async afterRevert() {
|
||||
await this.getPosting().postReverse();
|
||||
}
|
||||
}
|
28
models/doctype/PaymentFor/PaymentFor.js
Normal file
28
models/doctype/PaymentFor/PaymentFor.js
Normal file
@ -0,0 +1,28 @@
|
||||
module.exports = {
|
||||
name: "PaymentFor",
|
||||
label: "Payment For",
|
||||
isSingle: 0,
|
||||
isChild: 1,
|
||||
keywordFields: [],
|
||||
fields: [
|
||||
{
|
||||
fieldname: "referenceType",
|
||||
label: "Reference Type",
|
||||
fieldtype: "Data",
|
||||
required: 1
|
||||
},
|
||||
{
|
||||
fieldname: "referenceName",
|
||||
label: "Reference Name",
|
||||
fieldtype: "DynamicLink",
|
||||
references: "referenceType",
|
||||
required: 1
|
||||
},
|
||||
{
|
||||
fieldname: "amount",
|
||||
label: "Amount",
|
||||
fieldtype: "Currency",
|
||||
required: 1
|
||||
},
|
||||
]
|
||||
}
|
17
models/doctype/PaymentSettings/PaymentSettings.js
Normal file
17
models/doctype/PaymentSettings/PaymentSettings.js
Normal file
@ -0,0 +1,17 @@
|
||||
module.exports = {
|
||||
name: "PaymentSettings",
|
||||
label: "Payment Settings",
|
||||
isSingle: 1,
|
||||
isChild: 0,
|
||||
keywordFields: [],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "numberSeries",
|
||||
"label": "Number Series",
|
||||
"fieldtype": "Link",
|
||||
"target": "NumberSeries",
|
||||
"required": 1,
|
||||
"default": "PAY"
|
||||
}
|
||||
]
|
||||
}
|
@ -3,12 +3,21 @@ module.exports = {
|
||||
Account: require('./doctype/Account/Account.js'),
|
||||
AccountingLedgerEntry: require('./doctype/AccountingLedgerEntry/AccountingLedgerEntry.js'),
|
||||
Party: require('./doctype/Party/Party.js'),
|
||||
|
||||
Payment: require('./doctype/Payment/Payment.js'),
|
||||
PaymentFor: require('./doctype/PaymentFor/PaymentFor.js'),
|
||||
PaymentSettings: require('./doctype/PaymentSettings/PaymentSettings.js'),
|
||||
|
||||
Item: require('./doctype/Item/Item.js'),
|
||||
|
||||
Invoice: require('./doctype/Invoice/Invoice.js'),
|
||||
InvoiceItem: require('./doctype/InvoiceItem/InvoiceItem.js'),
|
||||
InvoiceSettings: require('./doctype/InvoiceSettings/InvoiceSettings.js'),
|
||||
|
||||
Tax: require('./doctype/Tax/Tax.js'),
|
||||
TaxDetail: require('./doctype/TaxDetail/TaxDetail.js'),
|
||||
TaxSummary: require('./doctype/TaxSummary/TaxSummary.js')
|
||||
TaxSummary: require('./doctype/TaxSummary/TaxSummary.js'),
|
||||
Address: require('./doctype/Address/Address.js'),
|
||||
Contact: require('./doctype/Contact/Contact.js')
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
const ReportPage = require('frappejs/client/desk/reportpage');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
module.exports = class GeneralLedgerView extends ReportPage {
|
||||
constructor() {
|
||||
super({title: frappe._('General Ledger')});
|
||||
|
||||
this.addFilter({fieldtype: 'Link', target: 'Account', label: 'Account'});
|
||||
this.addFilter({fieldtype: 'Link', target: 'Party', label: 'Party'});
|
||||
this.addFilter({fieldtype: 'Date', label: 'From Date'});
|
||||
this.addFilter({fieldtype: 'Date', label: 'To Date'});
|
||||
|
||||
this.method = 'general-ledger';
|
||||
}
|
||||
|
||||
getColumns() {
|
||||
return [
|
||||
{label: 'Date', fieldtype: 'Date'},
|
||||
{label: 'Account', fieldtype: 'Link'},
|
||||
{label: 'Party', fieldtype: 'Link'},
|
||||
{label: 'Description', fieldtype: 'Data'},
|
||||
{label: 'Debit', fieldtype: 'Currency'},
|
||||
{label: 'Credit', fieldtype: 'Currency'},
|
||||
{label: 'Balance', fieldtype: 'Currency'}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,18 @@
|
||||
const frappe = require('frappejs');
|
||||
|
||||
module.exports = class GeneralLedger {
|
||||
module.exports = function execute(params) {
|
||||
return new GeneralLedger().run(params);
|
||||
}
|
||||
|
||||
class GeneralLedger {
|
||||
async run(params) {
|
||||
const filters = {};
|
||||
if (params.account) filters.account = params.account;
|
||||
if (params.party) filters.party = params.party;
|
||||
if (params.from_date) filters.date = ('>=', params.from_date);
|
||||
if (params.to_date) filters.date = ('<=', params.to_date);
|
||||
if (params.referenceType) filters.referenceType = params.referenceType;
|
||||
if (params.referenceName) filters.referenceName = params.referenceName;
|
||||
if (params.fromDate) filters.date = ['>=', params.fromDate];
|
||||
if (params.toDate) filters.date = ['<=', params.toDate];
|
||||
|
||||
let data = await frappe.db.getAll({
|
||||
doctype: 'AccountingLedgerEntry',
|
35
reports/generalLedger/GeneralLedgerView.js
Normal file
35
reports/generalLedger/GeneralLedgerView.js
Normal file
@ -0,0 +1,35 @@
|
||||
const ReportPage = require('frappejs/client/desk/reportpage');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
module.exports = class GeneralLedgerView extends ReportPage {
|
||||
constructor() {
|
||||
super({
|
||||
title: frappe._('General Ledger'),
|
||||
filterFields: [
|
||||
{fieldtype: 'Select', options: ['', 'Invoice', 'Payment'],
|
||||
label: 'Reference Type', fieldname: 'referenceType'},
|
||||
{fieldtype: 'DynamicLink', references: 'referenceType',
|
||||
label: 'Reference Name', fieldname: 'referenceName'},
|
||||
{fieldtype: 'Link', target: 'Account', label: 'Account'},
|
||||
{fieldtype: 'Link', target: 'Party', label: 'Party'},
|
||||
{fieldtype: 'Date', label: 'From Date'},
|
||||
{fieldtype: 'Date', label: 'To Date'}
|
||||
]
|
||||
});
|
||||
|
||||
this.method = 'general-ledger';
|
||||
}
|
||||
|
||||
getColumns() {
|
||||
return [
|
||||
{label: 'Date', fieldtype: 'Date'},
|
||||
{label: 'Account', fieldtype: 'Link'},
|
||||
{label: 'Party', fieldtype: 'Link'},
|
||||
{label: 'Description', fieldtype: 'Data'},
|
||||
{label: 'Debit', fieldtype: 'Currency'},
|
||||
{label: 'Credit', fieldtype: 'Currency'},
|
||||
{label: 'Balance', fieldtype: 'Currency'}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
const server = require('frappejs/server');
|
||||
const frappe = require('frappejs');
|
||||
const GeneralLedger = require('../reports/GeneralLedger')
|
||||
const GeneralLedger = require('../reports/generalLedger/GeneralLedger')
|
||||
const naming = require('frappejs/model/naming')
|
||||
|
||||
module.exports = {
|
||||
async start() {
|
||||
@ -13,16 +14,19 @@ module.exports = {
|
||||
|
||||
// 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.metaCache = {};
|
||||
|
||||
frappe.syncDoc(require('../fixtures/invoicePrint'));
|
||||
|
||||
// init naming series if missing
|
||||
await naming.createNumberSeries('INV-', 'InvoiceSettings');
|
||||
await naming.createNumberSeries('PAY-', 'PaymentSettings');
|
||||
|
||||
frappe.registerMethod({
|
||||
method: 'general-ledger',
|
||||
handler: async (args) => {
|
||||
const generalLedger = new GeneralLedger();
|
||||
return await generalLedger.run(args);
|
||||
}
|
||||
handler: args => GeneralLedger(args)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
55
setup/config.js
Normal file
55
setup/config.js
Normal file
@ -0,0 +1,55 @@
|
||||
module.exports = [
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
"fieldname": "country",
|
||||
"label": "Country",
|
||||
"fieldtype": "Data",
|
||||
"required": 1
|
||||
}
|
||||
],
|
||||
title: 'Select Country'
|
||||
},
|
||||
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
"fieldname": "name",
|
||||
"label": "Name",
|
||||
"fieldtype": "Data",
|
||||
"required": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "email",
|
||||
"label": "Email",
|
||||
"fieldtype": "Data",
|
||||
"required": 1
|
||||
}
|
||||
],
|
||||
title: 'Add a Profile'
|
||||
},
|
||||
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
"fieldname": "companyName",
|
||||
"label": "Company Name",
|
||||
"fieldtype": "Data",
|
||||
"required": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "abbreviation",
|
||||
"label": "Abbreviation",
|
||||
"fieldtype": "Data",
|
||||
"required": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "bankName",
|
||||
"label": "Bank Name",
|
||||
"fieldtype": "Data",
|
||||
"required": 1
|
||||
}
|
||||
],
|
||||
title: 'Add your Company'
|
||||
}
|
||||
]
|
135
setup/index.js
Normal file
135
setup/index.js
Normal file
@ -0,0 +1,135 @@
|
||||
const frappe = require('frappejs');
|
||||
const utils = require('frappejs/client/ui/utils');
|
||||
const slideConfigs = require('./config');
|
||||
const Tree = require('frappejs/client/ui/tree');
|
||||
const FormLayout = require('frappejs/client/view/formLayout');
|
||||
|
||||
module.exports = class SetupWizard {
|
||||
constructor({postSetup = () => {}}) {
|
||||
this.slideList = [];
|
||||
this.indicatorList = [];
|
||||
this.footerLinks = {};
|
||||
|
||||
this.currentIndex = 0;
|
||||
this.data = {};
|
||||
|
||||
this.postSetup = postSetup;
|
||||
this.make();
|
||||
|
||||
this.showSlide(this.currentIndex);
|
||||
}
|
||||
|
||||
make() {
|
||||
let body = document.querySelector('body');
|
||||
this.container = frappe.ui.add('form', 'setup-container container', body);
|
||||
this.$indicators = frappe.ui.add('div', 'indicators vertical-margin align-center', this.container);
|
||||
|
||||
this.makeSlides();
|
||||
this.makeLinks();
|
||||
}
|
||||
|
||||
makeSlides() {
|
||||
slideConfigs.forEach(config => {
|
||||
this.formLayout = new FormLayout(config);
|
||||
this.slideList.push(this.formLayout);
|
||||
let form = this.formLayout.form;
|
||||
this.container.appendChild(form);
|
||||
|
||||
let title = frappe.ui.create('h3', {
|
||||
className: 'text-extra-muted',
|
||||
innerHTML: config.title
|
||||
})
|
||||
form.insertBefore(title, form.firstChild);
|
||||
|
||||
let indicator = frappe.ui.create('span', {
|
||||
inside: this.$indicators,
|
||||
className: 'indicator gray'
|
||||
})
|
||||
this.indicatorList.push(indicator);
|
||||
});
|
||||
}
|
||||
|
||||
makeLinks() {
|
||||
this.linkArea = frappe.ui.add('div', 'setup-link-area align-right', this.container);
|
||||
|
||||
// this.formLayout.on('change', () => {
|
||||
// const show = this.doc._dirty && !this.doc.submitted;
|
||||
// this.saveButton.classList.toggle('hide', !show);
|
||||
// });
|
||||
|
||||
this.getFooterLinks().map(link => {
|
||||
let $link = utils.addLink(link.label, this.linkArea, () => {
|
||||
this.buildData();
|
||||
link.action(this.data);
|
||||
});
|
||||
this.footerLinks[link.name] = $link;
|
||||
})
|
||||
}
|
||||
|
||||
buildData() {
|
||||
this.data = {};
|
||||
this.slideList.forEach(slide => {
|
||||
Object.assign(this.data, slide.doc);
|
||||
});
|
||||
}
|
||||
|
||||
showSlide(index) {
|
||||
utils.activate(this.container, this.slideList[index].form, 'form-body', 'active');
|
||||
this.slideList[index].controlList[0].input.blur();
|
||||
this.activateIndicator(index);
|
||||
this.showFooterLinks(index);
|
||||
this.currentIndex = index;
|
||||
}
|
||||
|
||||
prevSlide() {
|
||||
this.showSlide(this.currentIndex - 1);
|
||||
}
|
||||
|
||||
nextSlide() {
|
||||
this.showSlide(this.currentIndex + 1);
|
||||
}
|
||||
|
||||
activateIndicator(index) {
|
||||
this.indicatorList.forEach(indicator => {indicator.classList.add('gray')});
|
||||
let indicator = this.indicatorList[index];
|
||||
utils.activate(this.$indicators, indicator, 'gray', 'blue', index);
|
||||
|
||||
frappe.ui.removeClass(indicator, 'gray');
|
||||
indicator.classList.remove('gray');
|
||||
}
|
||||
|
||||
showFooterLinks(index) {
|
||||
let mat = [1, 1, 0]
|
||||
if(index === 0) {
|
||||
mat = [0, 1, 0];
|
||||
} else if (index === this.slideList.length - 1) {
|
||||
mat = [1, 0, 1];
|
||||
}
|
||||
this.showHideLinks(mat);
|
||||
}
|
||||
|
||||
showHideLinks(matrix = [1, 1, 0]) {
|
||||
let linkNames = this.getFooterLinks().map(link => link.name);
|
||||
matrix.forEach((value, i) => {
|
||||
const fn = value ? 'remove' : 'add';
|
||||
this.footerLinks[linkNames[i]].classList[fn]('hide');
|
||||
});
|
||||
}
|
||||
|
||||
getFooterLinks() {
|
||||
return [
|
||||
{
|
||||
label: 'Prev', name: 'prev',
|
||||
action: this.prevSlide.bind(this)
|
||||
},
|
||||
{
|
||||
label: 'Next', name: 'next',
|
||||
action: this.nextSlide.bind(this)
|
||||
},
|
||||
{
|
||||
label: 'Complete', name: 'complete',
|
||||
action: this.postSetup.bind(this)
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
25
www/dist/css/style.css
vendored
25
www/dist/css/style.css
vendored
@ -7396,7 +7396,8 @@ html {
|
||||
.form-body .alert {
|
||||
margin-top: 1rem; }
|
||||
.form-inline .form-group {
|
||||
margin-right: 0.5rem; }
|
||||
margin-right: 1rem;
|
||||
margin-bottom: 1rem; }
|
||||
.list-search {
|
||||
padding: 1rem 2rem; }
|
||||
.list-body .list-row {
|
||||
@ -7485,3 +7486,25 @@ html {
|
||||
mark {
|
||||
padding: none;
|
||||
background: inherit; }
|
||||
.align-right {
|
||||
text-align: right; }
|
||||
.align-center {
|
||||
text-align: center; }
|
||||
.btn-sm, .btn-group-sm > .btn {
|
||||
margin: 0.25rem; }
|
||||
.vertical-margin {
|
||||
margin: 1rem 0px; }
|
||||
.setup-container {
|
||||
margin: 40px auto;
|
||||
padding: 20px 0px;
|
||||
width: 450px;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 4px; }
|
||||
.setup-container h3 {
|
||||
text-align: center; }
|
||||
.setup-container .form-body {
|
||||
display: none; }
|
||||
.setup-container .form-body.active {
|
||||
display: block; }
|
||||
.setup-container .setup-link-area {
|
||||
margin: 0.25rem 2rem; }
|
||||
|
1721
www/dist/js/bundle.js
vendored
1721
www/dist/js/bundle.js
vendored
File diff suppressed because it is too large
Load Diff
14
www/index.js
14
www/index.js
@ -1,11 +1,21 @@
|
||||
const client = require('frappejs/client');
|
||||
const appClient = require('../client');
|
||||
const SetupWizard = require('../setup');
|
||||
|
||||
// start server
|
||||
client.start({
|
||||
columns: 3,
|
||||
server: 'localhost:8000'
|
||||
server: 'localhost:8000',
|
||||
makeDesk: 0
|
||||
}).then(() => {
|
||||
// new SetupWizard({
|
||||
// postSetup: async (data) => {
|
||||
// client.makeDesk(3);
|
||||
// appClient.start();
|
||||
|
||||
// await frappe.router.setRoute('list', 'ToDo');
|
||||
// }
|
||||
// });
|
||||
client.makeDesk(3);
|
||||
appClient.start();
|
||||
});
|
||||
|
||||
|
17
yarn.lock
17
yarn.lock
@ -3548,7 +3548,7 @@ oauth-sign@~0.8.1, oauth-sign@~0.8.2:
|
||||
version "0.8.2"
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
|
||||
|
||||
object-assign@^4.0.1, object-assign@^4.1.0:
|
||||
object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
|
||||
@ -3587,6 +3587,12 @@ object.pick@^1.3.0:
|
||||
dependencies:
|
||||
isobject "^3.0.1"
|
||||
|
||||
octicons@^7.2.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/octicons/-/octicons-7.2.0.tgz#a721635f73c774d7ffda56a83a29dbde03fc4b53"
|
||||
dependencies:
|
||||
object-assign "^4.1.1"
|
||||
|
||||
on-finished@~2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
|
||||
@ -4836,6 +4842,15 @@ rollup-plugin-sass@^0.5.3:
|
||||
node-sass ">= 3.8.0"
|
||||
rollup-pluginutils ">= 1.3.1"
|
||||
|
||||
rollup-plugin-sass@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-sass/-/rollup-plugin-sass-0.6.0.tgz#7d490827f395db4b5252485c45cc1a39da88901b"
|
||||
dependencies:
|
||||
babel-runtime "^6.23.0"
|
||||
fs-extra "^0.30.0"
|
||||
node-sass ">= 3.8.0"
|
||||
rollup-pluginutils ">= 1.3.1"
|
||||
|
||||
"rollup-pluginutils@>= 1.3.1", rollup-pluginutils@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz#7ec95b3573f6543a46a6461bd9a7c544525d0fc0"
|
||||
|
Loading…
Reference in New Issue
Block a user