mirror of
https://github.com/frappe/books.git
synced 2024-12-23 03:19:01 +00:00
* Dynamic Filters
* Report Actions
This commit is contained in:
parent
0a4e127b79
commit
90411d3ec9
@ -18,7 +18,7 @@ module.exports = {
|
||||
{
|
||||
fieldname: 'date',
|
||||
label: 'Date',
|
||||
fieldtype: 'Date',
|
||||
fieldtype: 'Date'
|
||||
// default: (new Date()).toISOString()
|
||||
},
|
||||
{
|
||||
@ -27,7 +27,13 @@ module.exports = {
|
||||
fieldtype: 'Link',
|
||||
target: 'Party',
|
||||
required: 1,
|
||||
getFilters: (query) => {
|
||||
getFilters: query => {
|
||||
if (query)
|
||||
return {
|
||||
keywords: ['like', query],
|
||||
customer: 1
|
||||
};
|
||||
|
||||
return {
|
||||
customer: 1
|
||||
};
|
||||
@ -38,8 +44,14 @@ module.exports = {
|
||||
label: 'Account',
|
||||
fieldtype: 'Link',
|
||||
target: 'Account',
|
||||
formula: (doc) => doc.getFrom('Party', doc.customer , 'defaultAccount'),
|
||||
formula: doc => doc.getFrom('Party', doc.customer, 'defaultAccount'),
|
||||
getFilters: (query, control) => {
|
||||
if (query)
|
||||
return {
|
||||
keywords: ['like', query],
|
||||
isGroup: 0,
|
||||
accountType: 'Receivable'
|
||||
};
|
||||
return {
|
||||
isGroup: 0,
|
||||
accountType: 'Receivable'
|
||||
@ -57,7 +69,7 @@ module.exports = {
|
||||
fieldname: 'netTotal',
|
||||
label: 'Net Total',
|
||||
fieldtype: 'Currency',
|
||||
formula: (doc) => doc.getSum('items', 'amount'),
|
||||
formula: doc => doc.getSum('items', 'amount'),
|
||||
disabled: true,
|
||||
readOnly: 1
|
||||
},
|
||||
@ -85,7 +97,7 @@ module.exports = {
|
||||
fieldname: 'grandTotal',
|
||||
label: 'Grand Total',
|
||||
fieldtype: 'Currency',
|
||||
formula: (doc) => doc.getGrandTotal(),
|
||||
formula: doc => doc.getGrandTotal(),
|
||||
disabled: true,
|
||||
readOnly: 1
|
||||
},
|
||||
@ -105,31 +117,22 @@ module.exports = {
|
||||
layout: [
|
||||
// section 1
|
||||
{
|
||||
columns: [
|
||||
{ fields: ['customer', 'account'] },
|
||||
{ fields: ['date'] }
|
||||
]
|
||||
columns: [{ fields: ['customer', 'account'] }, { fields: ['date'] }]
|
||||
},
|
||||
|
||||
// section 2
|
||||
{
|
||||
columns: [
|
||||
{ fields: ['items'] }
|
||||
]
|
||||
columns: [{ fields: ['items'] }]
|
||||
},
|
||||
|
||||
// section 3
|
||||
{
|
||||
columns: [
|
||||
{ fields: ['netTotal', 'taxes', 'grandTotal'] }
|
||||
]
|
||||
columns: [{ fields: ['netTotal', 'taxes', 'grandTotal'] }]
|
||||
},
|
||||
|
||||
// section 4
|
||||
{
|
||||
columns: [
|
||||
{ fields: ['terms'] }
|
||||
]
|
||||
columns: [{ fields: ['terms'] }]
|
||||
}
|
||||
],
|
||||
|
||||
@ -137,18 +140,25 @@ module.exports = {
|
||||
utils.ledgerLink,
|
||||
{
|
||||
label: 'Make Payment',
|
||||
condition: form => form.doc.submitted && form.doc.outstandingAmount !== 0.0,
|
||||
condition: form =>
|
||||
form.doc.submitted && form.doc.outstandingAmount !== 0.0,
|
||||
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 }];
|
||||
payment.for = [
|
||||
{
|
||||
referenceType: form.doc.doctype,
|
||||
referenceName: form.doc.name,
|
||||
amount: form.doc.grandTotal
|
||||
}
|
||||
];
|
||||
payment.on('afterInsert', async () => {
|
||||
form.$formModal.close();
|
||||
|
||||
const _payment = await frappe.getDoc('Payment', payment.name);
|
||||
await _payment.submit();
|
||||
})
|
||||
});
|
||||
await form.$formModal.open(payment);
|
||||
}
|
||||
}
|
||||
|
@ -1,54 +1,67 @@
|
||||
module.exports = {
|
||||
"name": "Party",
|
||||
"doctype": "DocType",
|
||||
"isSingle": 0,
|
||||
"istable": 0,
|
||||
"keywordFields": [
|
||||
"name"
|
||||
],
|
||||
"fields": [{
|
||||
"fieldname": "name",
|
||||
"label": "Name",
|
||||
"fieldtype": "Data",
|
||||
"required": 1
|
||||
},
|
||||
{
|
||||
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",
|
||||
"label": "Customer",
|
||||
"fieldtype": "Check"
|
||||
},
|
||||
{
|
||||
"fieldname": "supplier",
|
||||
"label": "Supplier",
|
||||
"fieldtype": "Check"
|
||||
}
|
||||
],
|
||||
name: 'Party',
|
||||
doctype: 'DocType',
|
||||
documentClass: require('./PartyDocument.js'),
|
||||
isSingle: 0,
|
||||
istable: 0,
|
||||
keywordFields: ['name'],
|
||||
fields: [
|
||||
{
|
||||
fieldname: 'name',
|
||||
label: 'Name',
|
||||
fieldtype: 'Data',
|
||||
required: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'address',
|
||||
label: 'Address',
|
||||
fieldtype: 'Link',
|
||||
target: 'Address'
|
||||
},
|
||||
{
|
||||
fieldname: 'defaultAccount',
|
||||
label: 'Default Account',
|
||||
fieldtype: 'Link',
|
||||
target: 'Account',
|
||||
getFilters: (query, doc) => {
|
||||
return {
|
||||
isGroup: 0,
|
||||
accountType: doc.customer === 1 ? 'Receivable' : 'Payable'
|
||||
};
|
||||
}
|
||||
},
|
||||
{
|
||||
fieldname: 'customer',
|
||||
label: 'Customer',
|
||||
fieldtype: 'Check'
|
||||
},
|
||||
{
|
||||
fieldname: 'supplier',
|
||||
label: 'Supplier',
|
||||
fieldtype: 'Check'
|
||||
}
|
||||
],
|
||||
|
||||
links: [{
|
||||
label: 'Invoices',
|
||||
condition: (form) => form.doc.customer,
|
||||
action: form => {
|
||||
form.$router.push({
|
||||
path: `/report/sales-register?&customer=${form.doc.name}`
|
||||
});
|
||||
}
|
||||
}]
|
||||
}
|
||||
links: [
|
||||
{
|
||||
label: 'Invoices',
|
||||
condition: form => form.doc.customer,
|
||||
action: form => {
|
||||
form.$router.push({
|
||||
path: `/report/sales-register?&customer=${form.doc.name}`
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Delete',
|
||||
condition: form => form.doc.customer,
|
||||
action: async form => {
|
||||
const party = await frappe.getDoc('Party', form.doc.name);
|
||||
await party.delete();
|
||||
form.$router.push({
|
||||
path: `/list/Customer`
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
9
models/doctype/Party/PartyDocument.js
Normal file
9
models/doctype/Party/PartyDocument.js
Normal file
@ -0,0 +1,9 @@
|
||||
const BaseDocument = require('frappejs/model/document');
|
||||
|
||||
module.exports = class Party extends BaseDocument {
|
||||
vaildate() {
|
||||
if (this.customer && this.supplier) {
|
||||
frappe.msgDialog('Invalid Party Type');
|
||||
}
|
||||
}
|
||||
};
|
10
models/doctype/Party/SupplierList.js
Normal file
10
models/doctype/Party/SupplierList.js
Normal file
@ -0,0 +1,10 @@
|
||||
import { _ } from 'frappejs/utils';
|
||||
|
||||
export default {
|
||||
doctype: 'Party',
|
||||
title: _('Supplier'),
|
||||
columns: ['name'],
|
||||
filters: {
|
||||
supplier: 1
|
||||
}
|
||||
};
|
@ -14,11 +14,64 @@ class GeneralLedger {
|
||||
}
|
||||
let data = await frappe.db.getAll({
|
||||
doctype: 'AccountingLedgerEntry',
|
||||
fields: ['date', 'account', 'party', 'referenceType', 'referenceName', 'debit', 'credit'],
|
||||
fields: [
|
||||
'date',
|
||||
'account',
|
||||
'party',
|
||||
'referenceType',
|
||||
'referenceName',
|
||||
'debit',
|
||||
'credit'
|
||||
],
|
||||
filters: filters
|
||||
});
|
||||
|
||||
return data;
|
||||
return this.appendOpeningEntry(data);
|
||||
}
|
||||
appendOpeningEntry(data) {
|
||||
let glEntries = [];
|
||||
let balance = 0,
|
||||
debitTotal = 0,
|
||||
creditTotal = 0;
|
||||
|
||||
glEntries.push({
|
||||
date: '',
|
||||
account: 'Opening',
|
||||
party: '',
|
||||
debit: 0,
|
||||
credit: 0,
|
||||
balance: 0,
|
||||
referenceType: '',
|
||||
referenceName: ''
|
||||
});
|
||||
for (let entry of data) {
|
||||
balance += entry.debit > 0 ? entry.debit : -entry.credit;
|
||||
debitTotal += entry.debit;
|
||||
creditTotal += entry.credit;
|
||||
entry.balance = balance;
|
||||
glEntries.push(entry);
|
||||
}
|
||||
glEntries.push({
|
||||
date: '',
|
||||
account: 'Total',
|
||||
party: '',
|
||||
debit: debitTotal,
|
||||
credit: creditTotal,
|
||||
balance: balance,
|
||||
referenceType: '',
|
||||
referenceName: ''
|
||||
});
|
||||
glEntries.push({
|
||||
date: '',
|
||||
account: 'Closing',
|
||||
party: '',
|
||||
debit: debitTotal,
|
||||
credit: creditTotal,
|
||||
balance: balance,
|
||||
referenceType: '',
|
||||
referenceName: ''
|
||||
});
|
||||
return glEntries;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,8 @@ module.exports = class GeneralLedgerView extends ReportPage {
|
||||
constructor() {
|
||||
super({
|
||||
title: frappe._('General Ledger'),
|
||||
filterFields: [{
|
||||
filterFields: [
|
||||
{
|
||||
fieldtype: 'Select',
|
||||
options: ['', 'Invoice', 'Payment'],
|
||||
label: 'Reference Type',
|
||||
@ -42,7 +43,8 @@ module.exports = class GeneralLedgerView extends ReportPage {
|
||||
}
|
||||
|
||||
getColumns() {
|
||||
return [{
|
||||
return [
|
||||
{
|
||||
label: 'Date',
|
||||
fieldtype: 'Date'
|
||||
},
|
||||
|
@ -1,44 +1,78 @@
|
||||
const title = 'General Ledger';
|
||||
module.exports = {
|
||||
title: title,
|
||||
let title = 'General Ledger';
|
||||
let 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'
|
||||
}
|
||||
];
|
||||
|
||||
const viewConfig = {
|
||||
title,
|
||||
filterFields,
|
||||
method: 'general-ledger',
|
||||
filterFields: [{
|
||||
fieldtype: 'Select',
|
||||
options: ['', 'Invoice', 'Payment'],
|
||||
label: 'Reference Type',
|
||||
fieldname: 'referenceType'
|
||||
},
|
||||
linkFields: [
|
||||
{
|
||||
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'
|
||||
label: 'Export',
|
||||
action: async report => {
|
||||
async function getReportDetails() {
|
||||
let [rows, columns] = await report.getReportData(filterFields);
|
||||
let columnData = columns.map(column => {
|
||||
return {
|
||||
id: column.id,
|
||||
content: column.content,
|
||||
checked: true
|
||||
};
|
||||
});
|
||||
return {
|
||||
title: title,
|
||||
rows: rows,
|
||||
columnData: columnData
|
||||
};
|
||||
}
|
||||
report.$modal.show({
|
||||
modalProps: {
|
||||
title: `Export ${title}`,
|
||||
noFooter: true
|
||||
},
|
||||
component: require('../../src/components/ExportWizard').default,
|
||||
props: await getReportDetails()
|
||||
});
|
||||
}
|
||||
}
|
||||
],
|
||||
getColumns() {
|
||||
return [{
|
||||
return [
|
||||
{
|
||||
label: 'Date',
|
||||
fieldtype: 'Date'
|
||||
},
|
||||
@ -77,3 +111,5 @@ module.exports = {
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = viewConfig;
|
||||
|
@ -8,26 +8,28 @@
|
||||
<!-- <transition-group name="slide-fade-group"> -->
|
||||
<div v-for="group in groups" :key="group">
|
||||
<div
|
||||
:class="['sidebar-item px-3 py-2 ', activeGroup === group ? 'active' : '']"
|
||||
:class="['sidebar-item px-1 py-2', activeGroup === group ? 'active' : '']"
|
||||
@click="toggleGroup(group)"
|
||||
style="user-select: none;"
|
||||
>
|
||||
{{
|
||||
group }}
|
||||
<div class="d-flex align-items-center">
|
||||
<feather-icon
|
||||
class="mr-1"
|
||||
:name="openGroup === group ? 'chevron-down' : 'chevron-right'"
|
||||
/>
|
||||
{{group }}
|
||||
</div>
|
||||
</div>
|
||||
<transition name="slide-fade">
|
||||
<div v-if="openGroup === group">
|
||||
<div
|
||||
v-for="item in groupItems"
|
||||
style="user-select: none;"
|
||||
:class="['sidebar-item px-3 py-2 ', isCurrentRoute(item.route) ? 'active' : '']"
|
||||
:class="['sidebar-item pl-4 py-2 ', isCurrentRoute(item.route) ? 'active' : '']"
|
||||
@click="routeTo(item.route)"
|
||||
:key="item.label"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
<feather-icon class="mr-1" name="chevron-right" />
|
||||
{{ item.label }}
|
||||
</div>
|
||||
<div class="d-flex align-items-center">{{ item.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
@ -55,45 +57,45 @@ export default {
|
||||
groups: [],
|
||||
groupItems: [],
|
||||
activeGroup: undefined,
|
||||
openGroup: undefined,
|
||||
items: [
|
||||
{
|
||||
label: 'Chart of Accounts',
|
||||
route: '/chartOfAccounts'
|
||||
},
|
||||
{
|
||||
label: 'Customers',
|
||||
route: '/list/Customer'
|
||||
},
|
||||
{
|
||||
label: 'Items',
|
||||
route: '/list/Item'
|
||||
},
|
||||
{
|
||||
label: 'Tax',
|
||||
route: '/list/Tax'
|
||||
},
|
||||
{
|
||||
label: 'Payments',
|
||||
route: '/list/Payment'
|
||||
},
|
||||
{
|
||||
label: 'Journal Entry',
|
||||
route: '/list/JournalEntry'
|
||||
},
|
||||
{
|
||||
label: 'Invoices',
|
||||
route: '/list/Invoice'
|
||||
},
|
||||
{
|
||||
label: 'Reports',
|
||||
route: '/reportList'
|
||||
},
|
||||
{
|
||||
label: 'Settings',
|
||||
route: '/settings'
|
||||
}
|
||||
]
|
||||
openGroup: undefined
|
||||
// items: [
|
||||
// {
|
||||
// label: 'Chart of Accounts',
|
||||
// route: '/chartOfAccounts'
|
||||
// },
|
||||
// {
|
||||
// label: 'Customers',
|
||||
// route: '/list/Customer'
|
||||
// },
|
||||
// {
|
||||
// label: 'Items',
|
||||
// route: '/list/Item'
|
||||
// },
|
||||
// {
|
||||
// label: 'Tax',
|
||||
// route: '/list/Tax'
|
||||
// },
|
||||
// {
|
||||
// label: 'Payments',
|
||||
// route: '/list/Payment'
|
||||
// },
|
||||
// {
|
||||
// label: 'Journal Entry',
|
||||
// route: '/list/JournalEntry'
|
||||
// },
|
||||
// {
|
||||
// label: 'Invoices',
|
||||
// route: '/list/Invoice'
|
||||
// },
|
||||
// {
|
||||
// label: 'Reports',
|
||||
// route: '/reportList'
|
||||
// },
|
||||
// {
|
||||
// label: 'Settings',
|
||||
// route: '/settings'
|
||||
// }
|
||||
// ]
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
@ -144,7 +146,7 @@ export default {
|
||||
|
||||
&.active {
|
||||
color: $white;
|
||||
background-color: $primary;
|
||||
background-color: $frappe;
|
||||
}
|
||||
}
|
||||
.slide-fade-enter-active {
|
||||
|
@ -89,7 +89,9 @@ export default {
|
||||
this.doc.on('change', this.setLinks);
|
||||
} catch (e) {
|
||||
this.notFound = true;
|
||||
this.$router.push(`/list/${this.doctype}`); //if reloaded while insert new Item,Invoice etc form.
|
||||
this.$router.push(
|
||||
`/list/${this.doctype === 'Party' ? 'Customer' : this.doctype}`
|
||||
); //if reloaded while insert new Item,Invoice etc form.
|
||||
}
|
||||
},
|
||||
async save() {
|
||||
|
@ -5,7 +5,7 @@
|
||||
</list-row>
|
||||
<list-row v-for="doc in data" :key="doc.name" @click.native="openForm(doc.name)">
|
||||
<list-cell v-for="column in columns" :key="column.label" class="d-flex align-items-center">
|
||||
<indicator v-if="column.getIndicator" :color="column.getIndicator(doc)" class="mr-2"/>
|
||||
<indicator v-if="column.getIndicator" :color="column.getIndicator(doc)" class="mr-2" />
|
||||
<span>{{ frappe.format(column.getValue(doc), column.fieldtype || {}) }}</span>
|
||||
</list-cell>
|
||||
</list-row>
|
||||
@ -25,7 +25,11 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
listConfig(oldValue, newValue) {
|
||||
if (oldValue.doctype !== newValue.doctype) {
|
||||
if (
|
||||
oldValue.doctype !== newValue.doctype ||
|
||||
// To differntiate Customer and Supplier List based on same Party Doctype
|
||||
oldValue.title !== newValue.title
|
||||
) {
|
||||
this.setupColumnsAndData();
|
||||
}
|
||||
}
|
||||
@ -36,17 +40,17 @@ export default {
|
||||
data: []
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.setupColumnsAndData();
|
||||
async mounted() {
|
||||
await this.setupColumnsAndData();
|
||||
frappe.listView.on('filterList', this.updateData.bind(this));
|
||||
},
|
||||
methods: {
|
||||
setupColumnsAndData() {
|
||||
async setupColumnsAndData() {
|
||||
this.doctype = this.listConfig.doctype;
|
||||
this.meta = frappe.getMeta(this.doctype);
|
||||
|
||||
this.prepareColumns();
|
||||
this.updateData();
|
||||
await this.prepareColumns();
|
||||
await this.updateData();
|
||||
},
|
||||
openForm(name) {
|
||||
this.$router.push(`/edit/${this.doctype}/${name}`);
|
||||
|
@ -1,5 +1,6 @@
|
||||
import Invoice from '../../../models/doctype/Invoice/InvoiceList';
|
||||
import Customer from '../../../models/doctype/Party/CustomerList';
|
||||
import Supplier from '../../../models/doctype/Party/SupplierList';
|
||||
import Item from '../../../models/doctype/Item/ItemList';
|
||||
import Payment from '../../../models/doctype/Payment/PaymentList';
|
||||
import Tax from '../../../models/doctype/Tax/TaxList';
|
||||
@ -8,6 +9,7 @@ import JournalEntry from '../../../models/doctype/JournalEntry/JournalEntryList'
|
||||
export default {
|
||||
Invoice,
|
||||
Customer,
|
||||
Supplier,
|
||||
Item,
|
||||
Payment,
|
||||
Tax,
|
||||
|
@ -1,27 +1,30 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="p-4">
|
||||
<h4 class="pb-2">{{ reportConfig.title }}</h4>
|
||||
<div class="col-12 text-right mt-4 mb-4">
|
||||
<f-button primary @click="openExportWizard">{{ 'Export' }}</f-button>
|
||||
<div class="row pb-4">
|
||||
<h4 class="col-6 d-flex">{{ reportConfig.title }}</h4>
|
||||
<report-links class="col-6 d-flex pr-0 flex-row-reverse" v-if="linksExists" :links="links"></report-links>
|
||||
</div>
|
||||
<report-filters
|
||||
v-if="filtersExists"
|
||||
:filters="reportConfig.filterFields"
|
||||
:filterDefaults="filters"
|
||||
@change="getReportData"
|
||||
></report-filters>
|
||||
<div class="pt-2" ref="datatable" v-once></div>
|
||||
<div class="row pb-4">
|
||||
<report-filters
|
||||
class="col-12 pr-0"
|
||||
v-if="filtersExists"
|
||||
:filters="reportConfig.filterFields"
|
||||
:filterDefaults="filters"
|
||||
@change="getReportData"
|
||||
></report-filters>
|
||||
</div>
|
||||
<div class="pt-2 pr-3" ref="datatable" v-once></div>
|
||||
</div>
|
||||
<not-found v-if="!reportConfig"/>
|
||||
<not-found v-if="!reportConfig" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import DataTable from 'frappe-datatable';
|
||||
import frappe from 'frappejs';
|
||||
import ReportFilters from 'frappejs/ui/pages/Report/ReportFilters';
|
||||
import ReportLinks from 'frappejs/ui/pages/Report/ReportLinks';
|
||||
import utils from 'frappejs/client/ui/utils';
|
||||
import ExportWizard from '../../components/ExportWizard';
|
||||
|
||||
export default {
|
||||
name: 'Report',
|
||||
@ -29,35 +32,21 @@ export default {
|
||||
computed: {
|
||||
filtersExists() {
|
||||
return (this.reportConfig.filterFields || []).length;
|
||||
},
|
||||
linksExists() {
|
||||
return (this.reportConfig.linkFields || []).length;
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
links: []
|
||||
};
|
||||
},
|
||||
async created() {
|
||||
this.setLinks();
|
||||
// this.doc.on('change', this.setLinks);
|
||||
},
|
||||
methods: {
|
||||
async openExportWizard() {
|
||||
this.$modal.show({
|
||||
modalProps: {
|
||||
title: `Export ${this.reportConfig.title}`,
|
||||
noFooter: true
|
||||
},
|
||||
component: ExportWizard,
|
||||
props: await this.getReportDetails()
|
||||
});
|
||||
},
|
||||
async getReportDetails() {
|
||||
let { title, filterFields } = this.reportConfig;
|
||||
let [rows, columns] = await this.getReportData(filterFields || []);
|
||||
let columnData = columns.map(column => {
|
||||
return {
|
||||
id: column.id,
|
||||
content: column.content,
|
||||
checked: true
|
||||
};
|
||||
});
|
||||
return {
|
||||
title: title,
|
||||
rows: rows,
|
||||
columnData: columnData
|
||||
};
|
||||
},
|
||||
async getReportData(filters) {
|
||||
let data = await frappe.call({
|
||||
method: this.reportConfig.method,
|
||||
@ -97,15 +86,33 @@ export default {
|
||||
}
|
||||
return [rows, columns];
|
||||
},
|
||||
setLinks() {
|
||||
if (this.linksExists) {
|
||||
let links = [];
|
||||
for (let link of this.reportConfig.linkFields) {
|
||||
links.push({
|
||||
label: link.label,
|
||||
handler: () => {
|
||||
link.action(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.links = links;
|
||||
}
|
||||
},
|
||||
getColumns(data) {
|
||||
const columns = this.reportConfig.getColumns(data);
|
||||
return utils.convertFieldsToDatatableColumns(columns);
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ReportFilters
|
||||
ReportFilters,
|
||||
ReportLinks
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.datatable {
|
||||
/* font-size: 12px; */
|
||||
}
|
||||
</style>
|
||||
|
@ -37,6 +37,10 @@ export default {
|
||||
label: _('Customer'),
|
||||
route: '/list/Customer'
|
||||
},
|
||||
{
|
||||
label: _('Supplier'),
|
||||
route: '/list/Supplier'
|
||||
},
|
||||
{
|
||||
label: _('Tax'),
|
||||
route: '/list/Tax'
|
||||
@ -70,6 +74,10 @@ export default {
|
||||
label: _('General Ledger'),
|
||||
route: '/report/general-ledger'
|
||||
},
|
||||
{
|
||||
label: _('Trial Balance'),
|
||||
route: '/report/trial-balance'
|
||||
},
|
||||
{
|
||||
label: _('Sales Register'),
|
||||
route: '/report/sales-register'
|
||||
@ -90,6 +98,10 @@ export default {
|
||||
{
|
||||
label: _('Data Import'),
|
||||
route: '/data-import'
|
||||
},
|
||||
{
|
||||
label: _('Settings'),
|
||||
route: '/settings'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,5 +1,9 @@
|
||||
@import "~bootstrap/scss/functions";
|
||||
@import "~bootstrap/scss/variables";
|
||||
@import '~bootstrap/scss/functions';
|
||||
@import '~bootstrap/scss/variables';
|
||||
|
||||
$dark: #252529;
|
||||
$blue: #1665D8;
|
||||
$blue: #1665d8;
|
||||
$frappe: #5e64ff;
|
||||
$theme-colors: (
|
||||
'primary': #5e64ff
|
||||
);
|
||||
|
22
yarn.lock
22
yarn.lock
@ -49,9 +49,9 @@
|
||||
integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
|
||||
|
||||
"@types/node@*":
|
||||
version "12.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.3.tgz#44d507c5634f85e7164707ca36bba21b5213d487"
|
||||
integrity sha512-7TEYTQT1/6PP53NftXXabIZDaZfaoBdeBm8Md/i7zsWRoBe0YwOXguyK8vhHs8ehgB/w9U4K/6EWuTyp0W6nIA==
|
||||
version "12.6.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.6.tgz#831587377c35bb28fa33b6fe5f849a26a3f4a412"
|
||||
integrity sha512-SMgj3x28MkJyHdWaMv/g/ca3LYDi5gR7O8mX0VKazvFOnmlDXctSEdd/8jfSqozjKFK1R9If1QZWkafX7yQTpA==
|
||||
|
||||
"@types/node@^10.12.18":
|
||||
version "10.14.12"
|
||||
@ -2802,7 +2802,7 @@ frappe-datatable@^1.13.5:
|
||||
|
||||
"frappejs@github:thefalconx33/frappejs#test":
|
||||
version "0.0.10"
|
||||
resolved "https://codeload.github.com/thefalconx33/frappejs/tar.gz/6d6e904a2982de061d87f80d1b7e6a989fe5eae3"
|
||||
resolved "https://codeload.github.com/thefalconx33/frappejs/tar.gz/8fb509d3c1a2db7eca95a1269d8bbf1096a65428"
|
||||
dependencies:
|
||||
awesomplete "^1.1.2"
|
||||
babel-core "^6.26.3"
|
||||
@ -2825,6 +2825,7 @@ frappe-datatable@^1.13.5:
|
||||
express "^4.16.2"
|
||||
feather-icons "^4.7.3"
|
||||
file-loader "^1.1.11"
|
||||
file-saver "^2.0.2"
|
||||
flatpickr "^4.3.2"
|
||||
frappe-datatable "^1.13.5"
|
||||
friendly-errors-webpack-plugin "^1.7.0"
|
||||
@ -3551,11 +3552,16 @@ ip@^1.1.0, ip@^1.1.5:
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
|
||||
integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
|
||||
|
||||
ipaddr.js@1.9.0, ipaddr.js@^1.9.0:
|
||||
ipaddr.js@1.9.0:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65"
|
||||
integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==
|
||||
|
||||
ipaddr.js@^1.9.0:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
||||
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
|
||||
|
||||
is-accessor-descriptor@^0.1.6:
|
||||
version "0.1.6"
|
||||
resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
|
||||
@ -4537,9 +4543,9 @@ ms@^2.1.1:
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
multer@^1.3.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.1.tgz#24b12a416a22fec2ade810539184bf138720159e"
|
||||
integrity sha512-zzOLNRxzszwd+61JFuAo0fxdQfvku12aNJgnla0AQ+hHxFmfc/B7jBVuPr5Rmvu46Jze/iJrFpSOsD7afO8SDw==
|
||||
version "1.4.2"
|
||||
resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.2.tgz#2f1f4d12dbaeeba74cb37e623f234bf4d3d2057a"
|
||||
integrity sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==
|
||||
dependencies:
|
||||
append-field "^1.0.0"
|
||||
busboy "^0.2.11"
|
||||
|
Loading…
Reference in New Issue
Block a user