mirror of
https://github.com/frappe/books.git
synced 2024-12-22 19:09:01 +00:00
Add Report View and Dynamic Link
This commit is contained in:
parent
441ec973e2
commit
7b9b897f9b
@ -25,6 +25,9 @@ module.exports = {
|
||||
'generator-star-spacing': 'off',
|
||||
// allow debugger during development
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'semi': 'off'
|
||||
'semi': 'on',
|
||||
'indent': 'off',
|
||||
// 'indent': ["error", 4],
|
||||
'space-before-function-paren': 'off'
|
||||
}
|
||||
}
|
||||
|
@ -11,5 +11,5 @@ module.exports = {
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
36
reports/GeneralLedger/viewConfig.js
Normal file
36
reports/GeneralLedger/viewConfig.js
Normal file
@ -0,0 +1,36 @@
|
||||
const title = 'General Ledger';
|
||||
module.exports = {
|
||||
title: title,
|
||||
method: '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', 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' }
|
||||
]
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ module.exports = class RegisterView extends ReportPage {
|
||||
title,
|
||||
filterFields: [
|
||||
{fieldtype: 'Date', fieldname: 'fromDate', label: 'From Date', required: 1},
|
||||
{fieldtype: 'Date', fieldname: 'toDate', label: 'To Date', required: 1}
|
||||
{fieldtype: 'Date', fieldname: 'toDate', label: 'To Date', required: 1}
|
||||
]
|
||||
});
|
||||
|
||||
|
@ -33,7 +33,7 @@ function registerReportMethods() {
|
||||
{
|
||||
method: 'purchase-register',
|
||||
class: PurchaseRegister
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
reports.forEach(report => {
|
||||
|
@ -1,70 +1,3 @@
|
||||
const frappe = require('frappejs');
|
||||
const GeneralLedgerView = require('../reports/GeneralLedger/GeneralLedgerView');
|
||||
const ProfitAndLossView = require('./ProfitAndLoss/ProfitAndLossView');
|
||||
const BalanceSheetView = require('./BalanceSheet/BalanceSheetView');
|
||||
const TrialBalanceView = require('./TrialBalance/TrialBalanceView');
|
||||
const SalesRegisterView = require('./SalesRegister/SalesRegisterView');
|
||||
const PurchaseRegisterView = require('./PurchaseRegister/PurchaseRegisterView');
|
||||
const AccountsReceivableView = require('./AccountsReceivablePayable/AccountsReceivableView');
|
||||
const AccountsPayableView = require('./AccountsReceivablePayable/AccountsPayableView');
|
||||
|
||||
// called on client side
|
||||
function registerReportRoutes() {
|
||||
frappe.router.add('report/general-ledger', async (params) => {
|
||||
if (!frappe.views.GeneralLedger) {
|
||||
frappe.views.GeneralLedger = new GeneralLedgerView();
|
||||
}
|
||||
await frappe.views.GeneralLedger.show(params);
|
||||
});
|
||||
|
||||
frappe.router.add('report/profit-and-loss', async (params) => {
|
||||
if (!frappe.views.ProfitAndLoss) {
|
||||
frappe.views.ProfitAndLoss = new ProfitAndLossView();
|
||||
}
|
||||
await frappe.views.ProfitAndLoss.show(params);
|
||||
});
|
||||
|
||||
frappe.router.add('report/balance-sheet', async (params) => {
|
||||
if (!frappe.views.BalanceSheet) {
|
||||
frappe.views.BalanceSheet = new BalanceSheetView();
|
||||
}
|
||||
await frappe.views.BalanceSheet.show(params);
|
||||
});
|
||||
|
||||
frappe.router.add('report/trial-balance', async (params) => {
|
||||
if (!frappe.views.TrialBalance) {
|
||||
frappe.views.TrialBalance = new TrialBalanceView();
|
||||
}
|
||||
await frappe.views.TrialBalance.show(params);
|
||||
});
|
||||
|
||||
frappe.router.add('report/sales-register', async (params) => {
|
||||
if (!frappe.views.SalesRegister) {
|
||||
frappe.views.SalesRegister = new SalesRegisterView();
|
||||
}
|
||||
await frappe.views.SalesRegister.show(params);
|
||||
});
|
||||
|
||||
frappe.router.add('report/purchase-register', async (params) => {
|
||||
if (!frappe.views.PurchaseRegister) {
|
||||
frappe.views.PurchaseRegister = new PurchaseRegisterView();
|
||||
}
|
||||
await frappe.views.PurchaseRegister.show(params);
|
||||
});
|
||||
|
||||
frappe.router.add('report/accounts-receivable', async (params) => {
|
||||
if (!frappe.views.AccountsReceivable) {
|
||||
frappe.views.AccountsReceivable = new AccountsReceivableView();
|
||||
}
|
||||
await frappe.views.AccountsReceivable.show(params);
|
||||
});
|
||||
|
||||
frappe.router.add('report/accounts-payable', async (params) => {
|
||||
if (!frappe.views.AccountsPayable) {
|
||||
frappe.views.AccountsPayable = new AccountsPayableView();
|
||||
}
|
||||
await frappe.views.AccountsPayable.show(params);
|
||||
});
|
||||
module.exports = {
|
||||
'General Ledger': require('./GeneralLedger/viewConfig')
|
||||
}
|
||||
|
||||
module.exports = registerReportRoutes;
|
||||
|
@ -33,6 +33,7 @@ export default {
|
||||
|
||||
<style lang="scss">
|
||||
@import "~bootstrap/scss/bootstrap";
|
||||
@import '~frappe-datatable/dist/frappe-datatable';
|
||||
|
||||
html {
|
||||
font-size: 14px;
|
||||
|
@ -12,8 +12,7 @@
|
||||
:isActive="doc.name === $route.params.name"
|
||||
:isChecked="isChecked(doc.name)"
|
||||
@clickItem="openForm(doc.name)"
|
||||
@checkItem="toggleCheck(doc.name)"
|
||||
>
|
||||
@checkItem="toggleCheck(doc.name)">
|
||||
{{ doc[meta.titleField || 'name'] }}
|
||||
</list-item>
|
||||
</ul>
|
||||
|
52
src/components/Report.vue
Normal file
52
src/components/Report.vue
Normal file
@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="p-4">
|
||||
<h4 class="pb-2">{{ reportName }}</h4>
|
||||
<report-filters v-if="reportConfig.filterFields.length" :filters="reportConfig.filterFields" @change="getReportData"></report-filters>
|
||||
<div class="pt-2" ref="datatable" v-once></div>
|
||||
</div>
|
||||
<not-found v-if="!reportConfig" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import DataTable from 'frappe-datatable'
|
||||
import frappe from 'frappejs'
|
||||
import FrappeControl from './controls/FrappeControl'
|
||||
import ReportFilters from './ReportFilters'
|
||||
import utils from 'frappejs/client/ui/utils'
|
||||
import getReportViewConfig from '../../reports/view'
|
||||
|
||||
export default {
|
||||
props: ['reportName'],
|
||||
data() {
|
||||
return {
|
||||
'reportConfig': getReportViewConfig[this.reportName]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
reportColumns() {
|
||||
return utils.convertFieldsToDatatableColumns(this.reportConfig.getColumns())
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getReportData(filters) {
|
||||
frappe.methods[this.reportConfig.method](filters).then(data => {
|
||||
if (this.datatable) {
|
||||
this.datatable.refresh(data || [])
|
||||
} else {
|
||||
this.datatable = new DataTable(this.$refs.datatable, {
|
||||
columns: this.reportColumns,
|
||||
data: data || [],
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
components: {
|
||||
FrappeControl,
|
||||
ReportFilters,
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
</style>
|
43
src/components/ReportFilters.vue
Normal file
43
src/components/ReportFilters.vue
Normal file
@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div class="row pb-4">
|
||||
<frappe-control class="col-lg col-md-3 col-sm-6"
|
||||
v-for="docfield in filters"
|
||||
:key="docfield.fieldname"
|
||||
:docfield="docfield"
|
||||
:value="$data[docfield.fieldname]"
|
||||
@change="updateValue(docfield.fieldname, $event)"/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import FrappeControl from './controls/FrappeControl'
|
||||
|
||||
export default {
|
||||
props: ['filters'],
|
||||
data () {
|
||||
const filterValues = {};
|
||||
for (let filter of this.filters) {
|
||||
filterValues[filter.fieldname] = '';
|
||||
}
|
||||
return {filterValues};
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
dynamicLinkTarget: (reference) => {
|
||||
return this.filterValues[reference]
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
updateValue(fieldname, value) {
|
||||
this.filterValues[fieldname] = value;
|
||||
this.$emit('change', this.filterValues)
|
||||
}
|
||||
},
|
||||
components: {
|
||||
FrappeControl
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
|
||||
</style>
|
@ -13,8 +13,7 @@
|
||||
<li class="nav-item">
|
||||
<a v-for="item in sidebarGroup.items" :key="item.route"
|
||||
:href="item.route"
|
||||
:class="['nav-link', isActive(item) ? 'text-light bg-secondary' : 'text-dark']"
|
||||
>
|
||||
:class="['nav-link', isActive(item) ? 'text-light bg-secondary' : 'text-dark']" >
|
||||
{{ item.label }}
|
||||
</a>
|
||||
</li>
|
||||
@ -35,9 +34,11 @@ export default {
|
||||
isActive(item) {
|
||||
if (this.$route.params.doctype) {
|
||||
return this.$route.params.doctype === item.label;
|
||||
} else if(this.$route.params.reportName) {
|
||||
return this.$route.params.reportName === item.label;
|
||||
}
|
||||
const route = item.route.slice(1);
|
||||
return this.$route.params.doctype === route;
|
||||
return this.$route.path === route;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ export default {
|
||||
return li;
|
||||
}
|
||||
});
|
||||
input.addEventListener('awesomplete-select', (e) => { console.log(e);this.$emit('awesomplete-select', e)} )
|
||||
},
|
||||
sort() {
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ export default {
|
||||
},
|
||||
getLabelElement(h) {
|
||||
return h('label', {
|
||||
class: this.labelClass,
|
||||
class: [this.labelClass, 'text-muted'],
|
||||
attrs: {
|
||||
for: this.id
|
||||
},
|
||||
|
@ -4,8 +4,7 @@
|
||||
<flat-pickr
|
||||
:value="value"
|
||||
class="form-control"
|
||||
@on-change="emitChange"
|
||||
>
|
||||
@on-change="emitChange">
|
||||
</flat-pickr>
|
||||
</div>
|
||||
<flat-pickr
|
||||
|
14
src/components/controls/DynamicLink.vue
Normal file
14
src/components/controls/DynamicLink.vue
Normal file
@ -0,0 +1,14 @@
|
||||
<script>
|
||||
import frappe from 'frappejs';
|
||||
import Link from './Link';
|
||||
|
||||
export default {
|
||||
extends: Link,
|
||||
inject: ['dynamicLinkTarget'],
|
||||
methods: {
|
||||
getTarget() {
|
||||
return this.dynamicLinkTarget(this.docfield.references);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -19,6 +19,7 @@ import Link from './Link';
|
||||
import Select from './Select';
|
||||
import Table from './Table';
|
||||
import Text from './Text';
|
||||
import DynamicLink from './DynamicLink';
|
||||
|
||||
export default {
|
||||
props: ['docfield', 'value', 'onlyInput'],
|
||||
@ -37,6 +38,7 @@ export default {
|
||||
Select,
|
||||
Table,
|
||||
Text,
|
||||
DynamicLink,
|
||||
}[this.docfield.fieldtype];
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ export default {
|
||||
methods: {
|
||||
async getList(query) {
|
||||
const list = await frappe.db.getAll({
|
||||
doctype: this.docfield.target,
|
||||
doctype: this.getTarget(),
|
||||
filters: {
|
||||
keywords: ["like", query]
|
||||
},
|
||||
@ -28,10 +28,13 @@ export default {
|
||||
value: d.name
|
||||
}))
|
||||
.concat({
|
||||
label: plusIcon + ' New ' + this.docfield.target,
|
||||
label: plusIcon + ' New ' + this.getTarget(),
|
||||
value: '__newItem'
|
||||
})
|
||||
},
|
||||
getTarget() {
|
||||
return this.docfield.target;
|
||||
},
|
||||
sort() {
|
||||
return (a, b) => {
|
||||
if (a.value === '__newitem' || b.value === '__newitem') {
|
||||
|
@ -21,6 +21,7 @@ import FeatherIcon from './components/FeatherIcon';
|
||||
import FrappeControl from './components/controls/FrappeControl';
|
||||
import Button from './components/Button';
|
||||
import Indicator from './components/Indicator';
|
||||
import registerReportMethods from '../reports';
|
||||
|
||||
frappe.init();
|
||||
frappe.registerLibs(common);
|
||||
@ -34,6 +35,7 @@ frappe.db.bindSocketClient(socket);
|
||||
frappe.registerModels(models);
|
||||
frappe.docs = new Observable();
|
||||
frappe.getSingle('SystemSettings');
|
||||
registerReportMethods()
|
||||
|
||||
frappe.getSingle('AccountingSettings')
|
||||
.then(accountingSettings => {
|
||||
|
@ -2,6 +2,7 @@ import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import ListAndForm from '@/components/ListAndForm'
|
||||
import SetupWizard from '@/pages/SetupWizard/SetupWizard'
|
||||
import Report from '@/components/Report'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
@ -25,13 +26,14 @@ export default new Router({
|
||||
components: {
|
||||
setup: SetupWizard
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/report/:reportName',
|
||||
name: 'Report',
|
||||
component: Report,
|
||||
props: true
|
||||
}
|
||||
// {
|
||||
// path: '/tree/:doctype',
|
||||
// name: '',
|
||||
// component: ''
|
||||
// },
|
||||
// {
|
||||
// path: '/table/:doctype',
|
||||
// name: '',
|
||||
// component: ''
|
||||
|
@ -33,7 +33,7 @@ export default [
|
||||
title: 'Reports',
|
||||
items: [
|
||||
{
|
||||
label: 'General Ledger', route: '#/report/general-ledger'
|
||||
label: 'General Ledger', route: '#/report/General Ledger'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user