2
0
mirror of https://github.com/frappe/books.git synced 2025-01-22 22:58:28 +00:00

[Fixes] #98 UI Issues 05-08-2019

This commit is contained in:
thefalconx33 2019-08-14 13:13:49 +05:30
parent 88021193fc
commit 54e115b030
49 changed files with 868 additions and 402 deletions

View File

@ -271,7 +271,7 @@
"currency_fraction_units": 100, "currency_fraction_units": 100,
"currency_name": "Belize Dollar", "currency_name": "Belize Dollar",
"currency_symbol": "$", "currency_symbol": "$",
"date_format": "mm-dd-yyyy", "date_format": "MM-dd-yyyy",
"number_format": "#,###.##", "number_format": "#,###.##",
"timezones": [ "timezones": [
"America/Belize" "America/Belize"
@ -356,7 +356,7 @@
"currency_fraction": "Centavo", "currency_fraction": "Centavo",
"currency_fraction_units": 100, "currency_fraction_units": 100,
"currency_symbol": "R$", "currency_symbol": "R$",
"date_format": "dd/mm/yyyy", "date_format": "dd/MM/yyyy",
"number_format": "#.###,##", "number_format": "#.###,##",
"timezones": [ "timezones": [
"America/Araguaina", "America/Araguaina",
@ -463,7 +463,7 @@
"currency_fraction_units": 100, "currency_fraction_units": 100,
"currency_name": "Canadian Dollar", "currency_name": "Canadian Dollar",
"currency_symbol": "$", "currency_symbol": "$",
"date_format": "mm-dd-yyyy", "date_format": "MM-dd-yyyy",
"number_format": "#,###.##", "number_format": "#,###.##",
"timezones": [ "timezones": [
"America/Atikokan", "America/Atikokan",
@ -563,7 +563,7 @@
"code": "cn", "code": "cn",
"currency": "CNY", "currency": "CNY",
"currency_name": "Yuan Renminbi", "currency_name": "Yuan Renminbi",
"date_format": "yyyy-mm-dd", "date_format": "yyyy-MM-dd",
"number_format": "#,###.##", "number_format": "#,###.##",
"timezones": [ "timezones": [
"Asia/Chongqing", "Asia/Chongqing",
@ -884,7 +884,7 @@
"currency_fraction_units": 100, "currency_fraction_units": 100,
"currency_symbol": "\u20ac", "currency_symbol": "\u20ac",
"number_format": "# ###,##", "number_format": "# ###,##",
"date_format": "dd/mm/yyyy", "date_format": "dd/MM/yyyy",
"timezones": [ "timezones": [
"Europe/Paris" "Europe/Paris"
] ]
@ -1136,7 +1136,7 @@
"currency_fraction_units": 100, "currency_fraction_units": 100,
"currency_name": "Forint", "currency_name": "Forint",
"currency_symbol": "Ft", "currency_symbol": "Ft",
"date_format": "yyyy-mm-dd", "date_format": "yyyy-MM-dd",
"number_format": "#.###", "number_format": "#.###",
"timezones": [ "timezones": [
"Europe/Budapest" "Europe/Budapest"
@ -1161,6 +1161,7 @@
"currency_fraction_units": 100, "currency_fraction_units": 100,
"currency_name": "Indian Rupee", "currency_name": "Indian Rupee",
"currency_symbol": "\u20b9", "currency_symbol": "\u20b9",
"date_format": "dd/MM/yyyy",
"number_format": "#,##,###.##", "number_format": "#,##,###.##",
"timezones": [ "timezones": [
"Asia/Kolkata" "Asia/Kolkata"
@ -1247,7 +1248,7 @@
"currency_fraction_units": 100, "currency_fraction_units": 100,
"currency_symbol": "\u20ac", "currency_symbol": "\u20ac",
"number_format": "#.###,##", "number_format": "#.###,##",
"date_format": "dd/mm/yyyy", "date_format": "dd/MM/yyyy",
"timezones": [ "timezones": [
"Europe/Rome" "Europe/Rome"
], ],
@ -1471,7 +1472,7 @@
"currency_fraction_units": 100, "currency_fraction_units": 100,
"currency_name": "Lithuanian Litas", "currency_name": "Lithuanian Litas",
"currency_symbol": "Lt", "currency_symbol": "Lt",
"date_format": "yyyy-mm-dd", "date_format": "yyyy-MM-dd",
"number_format": "# ###,##", "number_format": "# ###,##",
"timezones": [ "timezones": [
"Europe/Vilnius" "Europe/Vilnius"
@ -1674,7 +1675,7 @@
"currency_fraction_units": 100, "currency_fraction_units": 100,
"currency_name": "Tugrik", "currency_name": "Tugrik",
"currency_symbol": "\u20ae", "currency_symbol": "\u20ae",
"date_format": "yyyy-mm-dd", "date_format": "yyyy-MM-dd",
"number_format": "#,###.##", "number_format": "#,###.##",
"timezones": [ "timezones": [
"Asia/Choibalsan", "Asia/Choibalsan",
@ -1911,7 +1912,7 @@
"currency_fraction": "Cent", "currency_fraction": "Cent",
"currency_fraction_units": 100, "currency_fraction_units": 100,
"currency_symbol": "$", "currency_symbol": "$",
"date_format": "mm-dd-yyyy", "date_format": "MM-dd-yyyy",
"number_format": "#,###.##", "number_format": "#,###.##",
"timezones": [ "timezones": [
"Pacific/Palau" "Pacific/Palau"
@ -1974,7 +1975,7 @@
"currency_fraction_units": 100, "currency_fraction_units": 100,
"currency_name": "Philippine Peso", "currency_name": "Philippine Peso",
"currency_symbol": "\u20b1", "currency_symbol": "\u20b1",
"date_format": "mm-dd-yyyy", "date_format": "MM-dd-yyyy",
"number_format": "#,###.##", "number_format": "#,###.##",
"timezones": [ "timezones": [
"Asia/Manila" "Asia/Manila"
@ -2278,7 +2279,7 @@
"currency_fraction_units": 100, "currency_fraction_units": 100,
"currency_name": "Rand", "currency_name": "Rand",
"currency_symbol": "R", "currency_symbol": "R",
"date_format": "yyyy-mm-dd", "date_format": "yyyy-MM-dd",
"number_format": "# ###.##", "number_format": "# ###.##",
"timezones": [ "timezones": [
"Africa/Johannesburg" "Africa/Johannesburg"
@ -2398,7 +2399,7 @@
"Taiwan": { "Taiwan": {
"code": "tw", "code": "tw",
"currency": "TWD", "currency": "TWD",
"date_format": "yyyy-mm-dd", "date_format": "yyyy-MM-dd",
"number_format": "#,###.##" "number_format": "#,###.##"
}, },
"Tajikistan": { "Tajikistan": {
@ -2591,7 +2592,7 @@
"smallest_currency_fraction_value": 0.05, "smallest_currency_fraction_value": 0.05,
"currency_name": "US Dollar", "currency_name": "US Dollar",
"currency_symbol": "$", "currency_symbol": "$",
"date_format": "mm-dd-yyyy", "date_format": "MM-dd-yyyy",
"number_format": "#,###.##", "number_format": "#,###.##",
"timezones": [ "timezones": [
"America/Adak", "America/Adak",

View File

@ -13,26 +13,33 @@ module.exports = {
fieldtype: 'Data', fieldtype: 'Data',
required: 1 required: 1
}, },
{
fieldname: 'rootType',
label: 'Root Type',
fieldtype: 'Select',
options: [
'Select...',
'Asset',
'Liability',
'Equity',
'Income',
'Expense'
],
required: 1
},
{ {
fieldname: 'parentAccount', fieldname: 'parentAccount',
label: 'Parent Account', label: 'Parent Account',
fieldtype: 'Link', fieldtype: 'Link',
target: 'Account', target: 'Account',
getFilters: (query, doc) => { getFilters: (query, doc) => {
console.log(doc); const filter = {
return { isGroup: 1
isGroup: 1,
rootType: doc.rootType
}; };
doc.rootType ? (filter.rootType = doc.rootType) : '';
return filter;
} }
}, },
{
fieldname: 'rootType',
label: 'Root Type',
fieldtype: 'Select',
options: ['', 'Asset', 'Liability', 'Equity', 'Income', 'Expense'],
required: 1
},
{ {
fieldname: 'accountType', fieldname: 'accountType',
label: 'Account Type', label: 'Account Type',

View File

@ -1,124 +1,141 @@
module.exports = { module.exports = {
"name": "Address", name: 'Address',
"doctype": "DocType", doctype: 'DocType',
"isSingle": 0, isSingle: 0,
"keywordFields": [ keywordFields: ['name'],
"name" pageSettings: {
], hideTitle: true
pageSettings: { },
hideTitle: true fields: [
{
fieldname: 'name',
label: 'Address Title',
fieldtype: 'Data',
defaultValue: 'Work',
required: 1
}, },
// "naming": "autoincrement", {
"fields": [ fieldname: 'addressType',
{ label: 'Address Type',
"fieldname": "name", fieldtype: 'Select',
"label": "Address Title", options: [
"fieldtype": "Data", 'Billing',
"required": 1 'Shipping',
}, 'Office',
{ 'Personal',
"fieldname": "addressType", 'Plant',
"label": "Address Type", 'Postal',
"fieldtype": "Select", 'Shop',
"options": [ 'Subsidary',
"Billing", "Shipping", "Office", 'Warehouse',
"Personal", "Plant", "Postal", 'Current',
"Shop", "Subsidary", "Warehouse", 'Permanent',
"Current", "Permanent", "Other" '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": "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 ['name', 'addressType'];
},
getRowHTML(list, data) {
return `<div class="col-11">${list.getNameHTML(data)} (${data.addressType})</div>`;
}
}, },
{
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: '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'
}
],
layout: [ // events: {
// section 1 // validate: (doc) => {
// }
// },
listSettings: {
getFields(list) {
return ['name', 'addressType'];
},
getRowHTML(list, data) {
return `<div class="col-11">${list.getNameHTML(data)} (${
data.addressType
})</div>`;
}
},
layout: [
// section 1
{
columns: [
{ {
columns: [ fields: [
{ 'name',
fields: [ 'addressType',
"name", "addressType", "addressLine1", 'addressLine1',
"addressLine2", "city", "country", "state", 'addressLine2',
"postalCode" 'city',
] 'country',
}, 'state',
{ 'postalCode'
fields: [ ]
"emailAddress", "phone", "fax", "isPreferredBilling", "isShippingBilling" },
] {
} fields: [
] 'emailAddress',
'phone',
'fax',
'isPreferredBilling',
'isShippingBilling'
]
} }
] ]
} }
]
};

View File

@ -0,0 +1,16 @@
module.exports = {
name: 'Color',
doctype: 'DocType',
fields: [
{
fieldname: 'name',
fieldtype: 'Data',
label: 'Color'
},
{
fieldname: 'hexvalue',
fieldtype: 'Data',
label: 'Hex Value'
}
]
};

View File

@ -12,13 +12,15 @@ module.exports = {
{ {
fieldname: 'type', fieldname: 'type',
fieldtype: 'Select', fieldtype: 'Select',
options: ['', 'Bar', 'Line', 'Percentage'], options: ['Bar', 'Line', 'Percentage'],
label: 'Chart Type' label: 'Chart Type',
defaultValue: 'Bar'
}, },
{ {
fieldname: 'color', fieldname: 'color',
fieldtype: 'Data', fieldtype: 'Link',
label: 'Color' label: 'Color',
target: 'Color'
} }
] ]
}; };

View File

@ -4,11 +4,6 @@ module.exports = {
doctype: 'DocType', doctype: 'DocType',
isSingle: 1, isSingle: 1,
fields: [ fields: [
{
fieldname: 'name',
fieldtype: 'Data',
label: 'Dashboard Name'
},
{ {
fieldname: 'charts', fieldname: 'charts',
fieldtype: 'Table', fieldtype: 'Table',

View File

@ -6,7 +6,7 @@
</div> </div>
</div> </div>
<div ref="printComponent" class="col-8 bg-white mt-4 mx-auto border shadow"> <div ref="printComponent" class="col-8 bg-white mt-4 mx-auto border shadow">
<div class="print-format" style="padding: 3.5rem;"> <div class="print-format" style="padding: 3.5rem; font-size: 8pt !important;">
<div> <div>
<h3 class="text-center">GSTR3B-Form</h3> <h3 class="text-center">GSTR3B-Form</h3>
<h5>GSTIN: &nbsp; {{ jsonData.gstin }}</h5> <h5>GSTIN: &nbsp; {{ jsonData.gstin }}</h5>
@ -292,7 +292,6 @@ export default {
<style> <style>
.print-format { .print-format {
font-size: 8pt !important;
} }
.disabled { .disabled {
background-color: #d9d9d9; background-color: #d9d9d9;

View File

@ -101,5 +101,49 @@ module.exports = {
} }
] ]
} }
],
links: [
{
label: 'New Sales Invoice',
condition: form => !form.doc._notInserted,
action: async form => {
const invoice = await frappe.getNewDoc('SalesInvoice');
invoice.items = [
{
item: form.doc.name,
rate: form.doc.rate,
tax: form.doc.tax
}
];
invoice.on('afterInsert', async () => {
form.$formModal.close();
form.$router.push({
path: `/edit/PurchaseInvoice/${invoice.name}`
});
});
await form.$formModal.open(invoice);
}
},
{
label: 'New Purchase Invoice',
condition: form => !form.doc._notInserted,
action: async form => {
const invoice = await frappe.getNewDoc('PurchaseInvoice');
invoice.items = [
{
item: form.doc.name,
rate: form.doc.rate,
tax: form.doc.tax
}
];
invoice.on('afterInsert', async () => {
form.$formModal.close();
form.$router.push({
path: `/edit/PurchaseInvoice/${invoice.name}`
});
});
await form.$formModal.open(invoice);
}
}
] ]
}; };

View File

@ -2,88 +2,79 @@ const frappe = require('frappejs');
const utils = require('../../../accounting/utils'); const utils = require('../../../accounting/utils');
module.exports = { module.exports = {
name: "JournalEntry", label: 'Journal Entry',
doctype: "DocType", name: 'JournalEntry',
isSingle: 0, doctype: 'DocType',
isChild: 0, isSingle: 0,
isSubmittable: 1, isChild: 0,
keywordFields: ["name"], isSubmittable: 1,
showTitle: true, keywordFields: ['name'],
settings: "JournalEntrySettings", showTitle: true,
fields: [ settings: 'JournalEntrySettings',
{ fields: [
fieldname: "date", {
label: "Date", fieldname: 'entryType',
fieldtype: "Date" label: 'Entry Type',
}, fieldtype: 'Select',
{ options: [
fieldname: "entryType", 'Journal Entry',
label: "Entry Type", 'Bank Entry',
fieldtype: "Select", 'Cash Entry',
options: [ 'Credit Card Entry',
"Journal Entry", 'Debit Note',
"Bank Entry", 'Credit Note',
"Cash Entry", 'Contra Entry',
"Credit Card Entry", 'Excise Entry',
"Debit Note", 'Write Off Entry',
"Credit Note", 'Opening Entry',
"Contra Entry", 'Depreciation Entry'
"Excise Entry", ],
"Write Off Entry", required: 1
"Opening Entry", },
"Depreciation Entry" {
], fieldname: 'date',
required: 1 label: 'Date',
}, fieldtype: 'Date'
{ },
fieldname: "accounts", {
label: "Account Entries", fieldname: 'accounts',
fieldtype: "Table", label: 'Account Entries',
childtype: "JournalEntryAccount", fieldtype: 'Table',
required: true childtype: 'JournalEntryAccount',
}, required: true
{ },
fieldname: "referenceNumber", {
label: "Reference Number", fieldname: 'referenceNumber',
fieldtype: "Data", label: 'Reference Number',
}, fieldtype: 'Data'
{ },
fieldname: "referenceDate", {
label: "Reference Date", fieldname: 'referenceDate',
fieldtype: "Date", label: 'Reference Date',
}, fieldtype: 'Date'
{ },
fieldname: "userRemark", {
label: "User Remark", fieldname: 'userRemark',
fieldtype: "Text", label: 'User Remark',
} fieldtype: 'Text'
], }
layout: [ ],
// section 1 layout: [
{ // section 1
columns: [ {
{ fields: [ "date" ] }, columns: [{ fields: ['entryType'] }, { fields: ['date'] }]
{ fields: [ "entryType" ] }, },
] // section 2
{
}, columns: [{ fields: ['accounts'] }]
// section 2 },
{ // section 3
columns: [ {
{ fields: ["accounts"]}, columns: [{ fields: ['referenceNumber'] }, { fields: ['referenceDate'] }]
] },
}, // section 4
// section 3 {
{ columns: [{ fields: ['userRemark'] }]
columns: [ }
{ fields: [ "referenceNumber"] }, ]
{ fields: [ "referenceDate"] } };
]
},
// section 4
{
columns: [{ fields: [ "userRemark" ] }],
}
]
}

View File

@ -3,7 +3,6 @@ module.exports = {
label: 'Party', label: 'Party',
doctype: 'DocType', doctype: 'DocType',
isSingle: 0, isSingle: 0,
istable: 0,
keywordFields: ['name'], keywordFields: ['name'],
fields: [ fields: [
{ {
@ -42,22 +41,64 @@ module.exports = {
} }
], ],
getFormTitle(doc) {
if (doc.customer) return 'Customer';
return 'Supplier';
},
getListTitle(doc) {
if (doc.customer) return 'Customer';
return 'Supplier';
},
links: [ links: [
{
label: 'New Sales Invoice',
condition: form => form.doc.customer,
action: async form => {
const invoice = await frappe.getNewDoc('SalesInvoice');
invoice.customer = form.doc.name;
invoice.account = form.doc.defaultAccount;
invoice.on('afterInsert', async () => {
form.$formModal.close();
form.$router.push({
path: `/edit/SalesInvoice/${invoice.name}`
});
});
await form.$formModal.open(invoice);
}
},
{ {
label: 'Sales Invoices', label: 'Sales Invoices',
condition: form => form.doc.customer, condition: form => form.doc.customer,
action: form => { action: form => {
form.$router.push({ form.$router.push({
path: `/report/sales-register?&customer=${form.doc.name}` path: `/list/SalesInvoice?customer=${form.doc.name}`
}); });
} }
}, },
{
label: 'New Purchase Invoice',
condition: form => form.doc.supplier,
action: async form => {
const invoice = await frappe.getNewDoc('PurchaseInvoice');
invoice.supplier = form.doc.name;
invoice.account = form.doc.defaultAccount;
invoice.on('afterInsert', async () => {
form.$formModal.close();
form.$router.push({
path: `/edit/PurchaseInvoice/${invoice.name}`
});
});
await form.$formModal.open(invoice);
}
},
{ {
label: 'Purchase Invoices', label: 'Purchase Invoices',
condition: form => form.doc.supplier, condition: form => form.doc.supplier,
action: form => { action: form => {
form.$router.push({ form.$router.push({
path: `/report/purchase-register?&supplier=${form.doc.name}` path: `/list/PurchaseInvoice?supplier=${form.doc.name}`
}); });
} }
}, },

View File

@ -0,0 +1,7 @@
import { _ } from 'frappejs/utils';
export default {
doctype: 'Party',
title: filters => (filters.customer ? 'Customer' : 'Supplier'),
columns: ['name', 'defaultAccount', 'address']
};

View File

@ -9,12 +9,6 @@ module.exports = {
keywordFields: [], keywordFields: [],
settings: 'PaymentSettings', settings: 'PaymentSettings',
fields: [ fields: [
{
fieldname: 'date',
label: 'Posting Date',
fieldtype: 'Date'
// default: new Date().toISOString().substring(0, 10)
},
{ {
fieldname: 'party', fieldname: 'party',
label: 'Party', label: 'Party',
@ -22,6 +16,12 @@ module.exports = {
target: 'Party', target: 'Party',
required: 1 required: 1
}, },
{
fieldname: 'date',
label: 'Posting Date',
fieldtype: 'Date',
defaultValue: new Date().toISOString()
},
{ {
fieldname: 'account', fieldname: 'account',
label: 'From Account', label: 'From Account',
@ -95,7 +95,10 @@ module.exports = {
fieldtype: 'Currency', fieldtype: 'Currency',
required: 1, required: 1,
disabled: true, disabled: true,
formula: doc => doc.getSum('for', 'amount') formula: doc => {
console.log(doc.getSum('for', 'amount'));
return frappe.format(doc.getSum('for', 'amount'), 'Currency');
}
}, },
{ {
fieldname: 'writeoff', fieldname: 'writeoff',
@ -115,10 +118,10 @@ module.exports = {
{ {
columns: [ columns: [
{ {
fields: ['date', 'account'] fields: ['party', 'account']
}, },
{ {
fields: ['party', 'paymentAccount'] fields: ['date', 'paymentAccount']
} }
] ]
}, },

View File

@ -7,7 +7,11 @@ export default {
columns: [ columns: [
'party', 'party',
{ {
label: 'Payment', label: 'Status',
fieldname: 'status',
fieldtype: 'Select',
size: 'small',
options: ['Status...', 'Reconciled', 'Not Reconciled'],
getValue(doc) { getValue(doc) {
if ( if (
doc.submitted === 1 && doc.submitted === 1 &&
@ -27,10 +31,9 @@ export default {
return indicators.ORANGE; return indicators.ORANGE;
} }
}, },
'account', 'paymentType',
'amount',
'date', 'date',
'clearanceDate', 'clearanceDate',
'name' 'amount'
] ]
}; };

View File

@ -1,28 +1,31 @@
module.exports = { module.exports = {
name: "PaymentFor", name: 'PaymentFor',
label: "Payment For", label: 'Payment For',
isSingle: 0, isSingle: 0,
isChild: 1, isChild: 1,
keywordFields: [], keywordFields: [],
fields: [ fields: [
{ {
fieldname: "referenceType", fieldname: 'referenceType',
label: "Reference Type", label: 'Reference Type',
fieldtype: "Data", fieldtype: 'Data',
required: 1 required: 1
}, },
{ {
fieldname: "referenceName", fieldname: 'referenceName',
label: "Reference Name", label: 'Reference Name',
fieldtype: "DynamicLink", fieldtype: 'DynamicLink',
references: "referenceType", references: 'referenceType',
required: 1 required: 1
}, },
{ {
fieldname: "amount", fieldname: 'amount',
label: "Amount", label: 'Amount',
fieldtype: "Currency", fieldtype: 'Currency',
required: 1 formula: (row, doc) => {
}, doc.getFrom(doc.referenceType, doc.referenceName, 'grandTotal');
] },
} required: 1
}
]
};

View File

@ -16,7 +16,8 @@ module.exports = {
{ {
fieldname: 'date', fieldname: 'date',
label: 'Date', label: 'Date',
fieldtype: 'Date' fieldtype: 'Date',
defaultValue: new Date().toISOString()
}, },
{ {
fieldname: 'supplier', fieldname: 'supplier',

View File

@ -8,6 +8,10 @@ export default {
'supplier', 'supplier',
{ {
label: 'Status', label: 'Status',
fieldname: 'status',
fieldtype: 'Select',
size: 'small',
options: ['Status...', 'Paid', 'Pending'],
getValue(doc) { getValue(doc) {
if (doc.submitted === 1 && doc.outstandingAmount === 0.0) { if (doc.submitted === 1 && doc.outstandingAmount === 0.0) {
return 'Paid'; return 'Paid';
@ -21,8 +25,8 @@ export default {
return indicators.ORANGE; return indicators.ORANGE;
} }
}, },
'grandTotal',
'date', 'date',
'grandTotal',
'outstandingAmount' 'outstandingAmount'
] ]
}; };

View File

@ -19,8 +19,8 @@ module.exports = {
{ {
fieldname: 'date', fieldname: 'date',
label: 'Date', label: 'Date',
fieldtype: 'Date' fieldtype: 'Date',
// default: (new Date()).toISOString() defaultValue: new Date().toISOString()
}, },
{ {
fieldname: 'customer', fieldname: 'customer',
@ -70,7 +70,7 @@ module.exports = {
fieldname: 'netTotal', fieldname: 'netTotal',
label: 'Net Total', label: 'Net Total',
fieldtype: 'Currency', fieldtype: 'Currency',
formula: doc => doc.getSum('items', 'amount'), formula: doc => frappe.format(doc.getSum('items', 'amount'), 'Currency'),
disabled: true, disabled: true,
readOnly: 1 readOnly: 1
}, },

View File

@ -68,13 +68,14 @@ module.exports = class SalesInvoice extends BaseDocument {
getGrandTotal() { getGrandTotal() {
this.makeTaxSummary(); this.makeTaxSummary();
let grandTotal = this.netTotal; let grandTotal = frappe.parseNumber(this.netTotal);
if (this.taxes) { if (this.taxes) {
for (let row of this.taxes) { for (let row of this.taxes) {
grandTotal += row.amount; grandTotal += row.amount;
} }
} }
grandTotal = Math.floor(grandTotal * 100) / 100; grandTotal = Math.floor(grandTotal * 100) / 100;
return grandTotal;
return frappe.format(grandTotal, 'Currency');
} }
}; };

View File

@ -8,6 +8,10 @@ export default {
'customer', 'customer',
{ {
label: 'Status', label: 'Status',
fieldname: 'status',
fieldtype: 'Select',
size: 'small',
options: ['Status..', 'Paid', 'Pending'],
getValue(doc) { getValue(doc) {
if (doc.submitted === 1 && doc.outstandingAmount === 0.0) { if (doc.submitted === 1 && doc.outstandingAmount === 0.0) {
return 'Paid'; return 'Paid';
@ -21,8 +25,8 @@ export default {
return indicators.ORANGE; return indicators.ORANGE;
} }
}, },
'grandTotal',
'date', 'date',
'grandTotal',
'outstandingAmount' 'outstandingAmount'
] ]
}; };

View File

@ -17,10 +17,18 @@
@changeColor="changeColor($event)" @changeColor="changeColor($event)"
@changeTemplate="changeTemplate($event)" @changeTemplate="changeTemplate($event)"
@changeFont="changeFont($event)" @changeFont="changeFont($event)"
@updateTemplateView="updateTemplateView"
/> />
</div> </div>
<div class="col-8 bg-white mt-4 mx-auto border shadow" ref="printComponent"> <div class="col-8 bg-white mt-4 mx-auto border shadow" ref="printComponent">
<component :themeColor="themeColor" :font="font" :is="template" v-if="doc" :doc="doc" /> <component
:themeColor="themeColor"
:font="font"
:is="template"
v-if="doc"
:doc="doc"
:key="usedForReRender"
/>
</div> </div>
</div> </div>
</div> </div>
@ -48,7 +56,8 @@ export default {
showInvoiceCustomizer: false, showInvoiceCustomizer: false,
themeColor: undefined, themeColor: undefined,
template: undefined, template: undefined,
font: undefined font: undefined,
usedForReRender: 0
}; };
}, },
async created() { async created() {
@ -76,14 +85,17 @@ export default {
await this.loadInvoice(); await this.loadInvoice();
this.showInvoiceCustomizer = !this.showInvoiceCustomizer; this.showInvoiceCustomizer = !this.showInvoiceCustomizer;
}, },
async changeColor(color) { changeColor(color) {
this.themeColor = color; this.themeColor = color;
}, },
async changeTemplate(template) { changeTemplate(template) {
this.template = invoiceTemplates[template]; this.template = invoiceTemplates[template];
}, },
async changeFont(font) { changeFont(font) {
this.font = font; this.font = font;
},
updateTemplateView() {
this.usedForReRender += 1;
} }
} }
}; };

View File

@ -20,7 +20,7 @@ module.exports = {
fieldtype: 'Select', fieldtype: 'Select',
options: ['Basic I', 'Basic II', 'Modern'], options: ['Basic I', 'Basic II', 'Modern'],
required: 1, required: 1,
default: 'Basic I' defaultValue: 'Basic I'
}, },
{ {
fieldname: 'font', fieldname: 'font',
@ -28,14 +28,14 @@ module.exports = {
fieldtype: 'Select', fieldtype: 'Select',
options: ['Montserrat', 'Open Sans', 'Oxygen', 'Merriweather'], options: ['Montserrat', 'Open Sans', 'Oxygen', 'Merriweather'],
required: 1, required: 1,
default: 'Montserrat' defaultValue: 'Montserrat'
}, },
{ {
fieldname: 'themeColor', fieldname: 'themeColor',
label: 'Theme Color', label: 'Theme Color',
fieldtype: 'Data', fieldtype: 'Data',
required: 1, required: 1,
default: '#000000', defaultValue: '#000000',
hidden: 1 hidden: 1
} }
] ]

View File

@ -3,6 +3,7 @@ module.exports = {
SetupWizard: require('./doctype/SetupWizard/SetupWizard'), SetupWizard: require('./doctype/SetupWizard/SetupWizard'),
DashboardSettings: require('./doctype/DashboardSettings/DashboardSettings'), DashboardSettings: require('./doctype/DashboardSettings/DashboardSettings'),
DashboardChart: require('./doctype/DashboardChart/DashboardChart'), DashboardChart: require('./doctype/DashboardChart/DashboardChart'),
Color: require('./doctype/Color/Color'),
Account: require('./doctype/Account/Account.js'), Account: require('./doctype/Account/Account.js'),
AccountingSettings: require('./doctype/AccountingSettings/AccountingSettings'), AccountingSettings: require('./doctype/AccountingSettings/AccountingSettings'),
CompanySettings: require('./doctype/CompanySettings/CompanySettings'), CompanySettings: require('./doctype/CompanySettings/CompanySettings'),

View File

@ -2,6 +2,8 @@ const frappe = require('frappejs');
class BankReconciliation { class BankReconciliation {
async run(params) { async run(params) {
if (!Object.keys(params).length) return [];
const filters = {}; const filters = {};
if (params.paymentAccount) filters.paymentAccount = params.paymentAccount; if (params.paymentAccount) filters.paymentAccount = params.paymentAccount;
if (params.party) filters.party = params.party; if (params.party) filters.party = params.party;

View File

@ -6,7 +6,9 @@ module.exports = {
{ {
fieldtype: 'Link', fieldtype: 'Link',
target: 'Account', target: 'Account',
label: 'Payement Account', size: 'small',
placeholder: 'Payment Account',
label: 'Payment Account',
fieldname: 'paymentAccount', fieldname: 'paymentAccount',
getFilters: () => { getFilters: () => {
return { return {
@ -18,20 +20,36 @@ module.exports = {
{ {
fieldtype: 'Link', fieldtype: 'Link',
target: 'Party', target: 'Party',
size: 'small',
label: 'Party', label: 'Party',
placeholder: 'Party',
fieldname: 'party' fieldname: 'party'
}, },
{ {
fieldtype: 'Date', fieldtype: 'Date',
size: 'small',
placeholder: 'From Date',
label: 'From Date', label: 'From Date',
fieldname: 'fromDate' fieldname: 'fromDate'
}, },
{ {
fieldtype: 'Date', fieldtype: 'Date',
size: 'small',
placeholder: 'To Date',
label: 'To Date', label: 'To Date',
fieldname: 'toDate' fieldname: 'toDate'
} }
], ],
linkFields: [
{
label: 'Clear Filters',
type: 'secondary',
action: async report => {
await report.getReportData({});
report.usedToReRender += 1;
}
}
],
getColumns() { getColumns() {
return [ return [
{ {

View File

@ -2,6 +2,8 @@ const frappe = require('frappejs');
class GeneralLedger { class GeneralLedger {
async run(params) { async run(params) {
if (!Object.keys(params).length) return [];
const filters = {}; const filters = {};
if (params.account) filters.account = params.account; if (params.account) filters.account = params.account;
if (params.party) filters.party = params.party; if (params.party) filters.party = params.party;

View File

@ -5,12 +5,15 @@ const viewConfig = {
filterFields: [ filterFields: [
{ {
fieldtype: 'Select', fieldtype: 'Select',
options: ['', 'SalesInvoice', 'Payment', 'PurchaseInvoice'], options: ['Select...', 'SalesInvoice', 'Payment', 'PurchaseInvoice'],
size: 'small',
label: 'Reference Type', label: 'Reference Type',
fieldname: 'referenceType' fieldname: 'referenceType'
}, },
{ {
fieldtype: 'DynamicLink', fieldtype: 'DynamicLink',
size: 'small',
placeholder: 'Reference Name',
references: 'referenceType', references: 'referenceType',
label: 'Reference Name', label: 'Reference Name',
fieldname: 'referenceName' fieldname: 'referenceName'
@ -18,6 +21,8 @@ const viewConfig = {
{ {
fieldtype: 'Link', fieldtype: 'Link',
target: 'Account', target: 'Account',
size: 'small',
placeholder: 'Account',
label: 'Account', label: 'Account',
fieldname: 'account' fieldname: 'account'
}, },
@ -25,21 +30,35 @@ const viewConfig = {
fieldtype: 'Link', fieldtype: 'Link',
target: 'Party', target: 'Party',
label: 'Party', label: 'Party',
size: 'small',
placeholder: 'Party',
fieldname: 'party' fieldname: 'party'
}, },
{ {
fieldtype: 'Date', fieldtype: 'Date',
size: 'small',
placeholder: 'From Date',
label: 'From Date', label: 'From Date',
fieldname: 'fromDate' fieldname: 'fromDate'
}, },
{ {
fieldtype: 'Date', fieldtype: 'Date',
size: 'small',
placeholder: 'To Date',
label: 'To Date', label: 'To Date',
fieldname: 'toDate' fieldname: 'toDate'
} }
], ],
method: 'general-ledger', method: 'general-ledger',
linkFields: [ linkFields: [
{
label: 'Clear Filters',
type: 'secondary',
action: async report => {
await report.getReportData({});
report.usedToReRender += 1;
}
},
{ {
label: 'Export', label: 'Export',
type: 'primary', type: 'primary',
@ -70,13 +89,6 @@ const viewConfig = {
props: await getReportDetails() props: await getReportDetails()
}); });
} }
},
{
label: 'Clear Filters',
type: 'secondary',
action: async report => {
await report.$router.push(`/report/general-ledger`);
}
} }
], ],
getColumns() { getColumns() {

View File

@ -10,29 +10,29 @@ module.exports = {
'B2C-Large', 'B2C-Large',
'B2C-Small', 'B2C-Small',
'Nil Rated, Exempted and Non GST supplies' 'Nil Rated, Exempted and Non GST supplies'
] ],
size: 'small'
}, },
{ {
fieldtype: 'Data', fieldtype: 'Data',
label: 'Place', label: 'Place',
size: 'small',
placeholder: 'Place',
fieldname: 'place' fieldname: 'place'
}, },
{ {
fieldtype: 'Date', fieldtype: 'Date',
label: 'From Date', label: 'From Date',
size: 'small',
placeholder: 'From Date',
fieldname: 'fromDate' fieldname: 'fromDate'
}, },
{ {
fieldtype: 'Date', fieldtype: 'Date',
label: 'To Date', label: 'To Date',
size: 'small',
placeholder: 'To Date',
fieldname: 'toDate' fieldname: 'toDate'
},
{
fieldtype: 'Select',
label: 'Report Type',
fieldname: 'reportType',
options: ['', 'GSTR-1', 'GSTR-2', 'GSTR-3B'],
hidden: 1
} }
], ],
linkFields: [ linkFields: [
@ -66,6 +66,14 @@ module.exports = {
props: await getReportDetails() props: await getReportDetails()
}); });
} }
},
{
label: 'Clear Filters',
type: 'secondary',
action: async report => {
await report.getReportData({});
report.usedToReRender += 1;
}
} }
], ],

View File

@ -2,6 +2,8 @@ const BaseGSTR = require('./BaseGSTR');
class GSTR1 extends BaseGSTR { class GSTR1 extends BaseGSTR {
async run(params) { async run(params) {
if (!Object.keys(params).length) return [];
let filters = {}; let filters = {};
if (params.toDate || params.fromDate) { if (params.toDate || params.fromDate) {
filters.date = []; filters.date = [];

View File

@ -2,6 +2,8 @@ const BaseGSTR = require('./BaseGSTR');
class GSTR2 extends BaseGSTR { class GSTR2 extends BaseGSTR {
async run(params) { async run(params) {
if (!Object.keys(params).length) return [];
let filters = {}; let filters = {};
if (params.toDate || params.fromDate) { if (params.toDate || params.fromDate) {
filters.date = []; filters.date = [];

View File

@ -2,6 +2,8 @@ const frappe = require('frappejs');
class PurchaseRegister { class PurchaseRegister {
async run({ fromDate, toDate, supplier }) { async run({ fromDate, toDate, supplier }) {
if (!fromDate && !toDate && !supplier) return { rows: [] };
let filters = {}; let filters = {};
if (supplier) { if (supplier) {
filters.supplier = supplier; filters.supplier = supplier;

View File

@ -8,6 +8,8 @@ module.exports = {
target: 'Party', target: 'Party',
label: 'Supplier Name', label: 'Supplier Name',
fieldname: 'supplier', fieldname: 'supplier',
size: 'small',
placeholder: 'Supplier Name',
getFilters: query => { getFilters: query => {
if (query) if (query)
return { return {
@ -23,10 +25,29 @@ module.exports = {
{ {
fieldtype: 'Date', fieldtype: 'Date',
fieldname: 'fromDate', fieldname: 'fromDate',
size: 'small',
placeholder: 'From Date',
label: 'From Date', label: 'From Date',
required: 1 required: 1
}, },
{ fieldtype: 'Date', fieldname: 'toDate', label: 'To Date', required: 1 } {
fieldtype: 'Date',
size: 'small',
placeholder: 'To Date',
fieldname: 'toDate',
label: 'To Date',
required: 1
}
],
linkFields: [
{
label: 'Clear Filters',
type: 'secondary',
action: async report => {
await report.getReportData({});
report.usedToReRender += 1;
}
}
], ],
getColumns() { getColumns() {
return [ return [

View File

@ -2,6 +2,8 @@ const frappe = require('frappejs');
class SalesRegister { class SalesRegister {
async run({ fromDate, toDate, customer }) { async run({ fromDate, toDate, customer }) {
if (!fromDate && !toDate && !customer) return { rows: [] };
let filters = {}; let filters = {};
if (customer) { if (customer) {
filters.customer = customer; filters.customer = customer;

View File

@ -7,6 +7,8 @@ module.exports = {
fieldtype: 'Link', fieldtype: 'Link',
target: 'Party', target: 'Party',
label: 'Customer Name', label: 'Customer Name',
size: 'small',
placeholder: 'Customer Name',
fieldname: 'customer', fieldname: 'customer',
getFilters: query => { getFilters: query => {
if (query) if (query)
@ -23,10 +25,29 @@ module.exports = {
{ {
fieldtype: 'Date', fieldtype: 'Date',
fieldname: 'fromDate', fieldname: 'fromDate',
size: 'small',
placeholder: 'From Date',
label: 'From Date', label: 'From Date',
required: 1 required: 1
}, },
{ fieldtype: 'Date', fieldname: 'toDate', label: 'To Date', required: 1 } {
fieldtype: 'Date',
size: 'small',
placeholder: 'To Date',
fieldname: 'toDate',
label: 'To Date',
required: 1
}
],
linkFields: [
{
label: 'Clear Filters',
type: 'secondary',
action: async report => {
await report.getReportData({});
report.usedToReRender += 1;
}
}
], ],
getColumns() { getColumns() {
return [ return [

View File

@ -5,6 +5,9 @@ const {
module.exports = class TrialBalance { module.exports = class TrialBalance {
async run({ fromDate, toDate }) { async run({ fromDate, toDate }) {
if (!fromDate && !toDate) {
return { rows: [] };
}
const promises = ['Asset', 'Expense', 'Income', 'Liability', 'Equity'].map( const promises = ['Asset', 'Expense', 'Income', 'Liability', 'Equity'].map(
rootType => { rootType => {
return getTrialBalance({ rootType, fromDate, toDate }); return getTrialBalance({ rootType, fromDate, toDate });

View File

@ -8,9 +8,28 @@ module.exports = {
fieldtype: 'Date', fieldtype: 'Date',
fieldname: 'fromDate', fieldname: 'fromDate',
label: 'From Date', label: 'From Date',
size: 'small',
placeholder: 'From Date',
required: 1 required: 1
}, },
{ fieldtype: 'Date', fieldname: 'toDate', label: 'To Date', required: 1 } {
fieldtype: 'Date',
size: 'small',
placeholder: 'To Date',
fieldname: 'toDate',
label: 'To Date',
required: 1
}
],
linkFields: [
{
label: 'Clear Filters',
type: 'secondary',
action: async report => {
await report.getReportData({});
report.usedToReRender += 1;
}
}
], ],
getColumns(data) { getColumns(data) {
const columns = [ const columns = [

View File

@ -12,7 +12,10 @@
<div class="row"> <div class="row">
<div class="col-12 mt-4"> <div class="col-12 mt-4">
<form-layout :doc="doc" :fields="fields" @updateDoc="saveDoc" /> <form-layout :doc="doc" :fields="fields" @updateDoc="saveDoc" />
<sketch-picker v-model="color" /> <sketch-picker v-model="color" class="shadow-none" />
<div class="mt-3">
<f-button secondary @click="openCompanySettings">{{ _('Company Settings') }}</f-button>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -56,6 +59,14 @@ export default {
this.doc.themeColor = this.color.hex; this.doc.themeColor = this.color.hex;
await this.doc.update(); await this.doc.update();
this.$emit('closeInvoiceCustomizer'); this.$emit('closeInvoiceCustomizer');
},
async openCompanySettings() {
const settings = await frappe.getSingle('CompanySettings');
settings.on('afterSave', async () => {
this.$formModal.close();
this.$emit('updateTemplateView');
});
this.$formModal.open(settings);
} }
}, },
watch: { watch: {

View File

@ -4,13 +4,17 @@
> >
<h5 class="m-0" v-if="title">{{ title }}</h5> <h5 class="m-0" v-if="title">{{ title }}</h5>
<div v-if="breadcrumbs"> <div v-if="breadcrumbs">
<a v-for="(item, index) in clickableBreadcrumbs" :key="index" :href="item.route"> <span v-for="(item, index) in breadcrumbs" :key="index">
<h5 class="breadCrumbRoute"> <a v-if="item.route.length != 0" :href="item.route">
{{ item.title }} <h5 class="breadCrumbRoute">{{ item.title }}</h5>
<feather-icon name="chevron-right" style="color: #212529 !important;"></feather-icon> </a>
</h5> <h5 v-else class="breadCrumbRoute">{{ item.title }}</h5>
</a> <feather-icon
<h5 class="breadCrumbRoute">{{ lastBreadcrumb.title }}</h5> v-if="index != breadcrumbs.length - 1"
name="chevron-right"
style="color: #212529 !important;"
></feather-icon>
</span>
</div> </div>
<div class="col-4 p-1"> <div class="col-4 p-1">
<SearchBar /> <SearchBar />
@ -40,7 +44,7 @@ export default {
.page-header { .page-header {
position: sticky; position: sticky;
top: 0; top: 0;
z-index: 1; z-index: 10;
} }
.breadCrumbRoute { .breadCrumbRoute {
display: inline; display: inline;

View File

@ -64,8 +64,29 @@ export default {
this.companyName = await sidebarConfig.getTitle(); this.companyName = await sidebarConfig.getTitle();
this.dbFileName = await sidebarConfig.getDbName(); this.dbFileName = await sidebarConfig.getDbName();
this.groups = sidebarConfig.getGroups(); this.groups = sidebarConfig.getGroups();
this.setActive();
}, },
methods: { methods: {
setActive() {
let currentRoute = this.$route.fullPath;
// check each group items
this.groups.forEach(title => {
// filter items which contains the current route
sidebarConfig.getItems(title).filter(item => {
// check for substring 'list' 'SalesInvoice' etc.
let found = true;
currentRoute.split('/').forEach(str => {
if (str.length) {
item.route.indexOf(str) != -1 ? '' : (found = false);
}
});
if (found) {
this.toggleGroup(title);
}
return found;
});
});
},
isCurrentRoute(route) { isCurrentRoute(route) {
if (this.activeGroup) return false; if (this.activeGroup) return false;
return this.$route.fullPath === route; return this.$route.fullPath === route;
@ -100,6 +121,7 @@ export default {
} }
.page-sidebar { .page-sidebar {
height: 100vh; height: 100vh;
min-width: 208px;
} }
.sidebar-item { .sidebar-item {

View File

@ -74,17 +74,75 @@ import Toasted from 'vue-toasted';
}); });
await doc.update(); await doc.update();
const systemSettings = await frappe.getSingle('SystemSettings');
await systemSettings.set({
dateFormat: countryList[country]['date_format'] || 'yyyy-MM-dd'
});
await systemSettings.update();
await setupAccountsAndDashboard(bankName);
await setupRegionalChanges(country);
frappe.events.trigger('show-desk');
});
async function setupAccountsAndDashboard(bankName) {
await frappe.call({ await frappe.call({
method: 'import-coa' method: 'import-coa'
}); });
const accountDoc = await frappe.newDoc({
doctype: 'Account'
});
Object.assign(accountDoc, {
name: bankName,
rootType: 'Asset',
parentAccount: 'Bank Accounts',
accountType: 'Bank'
});
accountDoc.insert();
const dashboardSettings = await frappe.getSingle('DashboardSettings');
const accounts = await frappe.db.getAll({
doctype: 'Account',
filters: { parentAccount: ['in', ['', undefined, null]] }
});
const colors = [
{ name: 'Red', hexvalue: '#d32f2f' },
{ name: 'Green', hexvalue: '#388e3c' },
{ name: 'Blue', hexvalue: '#0288d1' },
{ name: 'Yellow', hexvalue: '#cddc39' }
];
colors.forEach(async color => {
const c = await frappe.newDoc({ doctype: 'Color' });
c.set(color);
c.insert();
});
let charts = [];
accounts.forEach(account => {
charts.push({
account: account.name,
type: 'Bar',
color: colors[Math.floor(Math.random() * 4)].name
});
});
await dashboardSettings.set({
charts
});
await dashboardSettings.update();
}
async function setupRegionalChanges(country) {
const generateRegionalTaxes = require('../models/doctype/Tax/RegionalChanges'); const generateRegionalTaxes = require('../models/doctype/Tax/RegionalChanges');
await generateRegionalTaxes(country); await generateRegionalTaxes(country);
if (country === 'India') { if (country === 'India') {
frappe.models.Party = require('../models/doctype/Party/RegionalChanges'); frappe.models.Party = require('../models/doctype/Party/RegionalChanges');
await frappe.db.migrate(); await frappe.db.migrate();
} }
frappe.events.trigger('show-desk'); }
});
async function connectToLocalDatabase(filepath) { async function connectToLocalDatabase(filepath) {
try { try {

View File

@ -32,7 +32,7 @@ export default {
this.chartData.push({ this.chartData.push({
title: c.account, title: c.account,
type: c.type.toLowerCase(), type: c.type.toLowerCase(),
color: c.color, color: await frappe.db.getValue('Color', c.color, 'hexvalue'),
data: { data: {
labels, labels,
datasets datasets

View File

@ -56,14 +56,8 @@ export default {
if (this.doc) if (this.doc)
return [ return [
{ {
title: this.meta.label || this.doctype, title: this.getFormTitle(),
route: '#/list/' + this.doctype route: '#/list/' + this.getListTitle()
},
{
title: this.doc._notInserted
? 'New ' + (this.meta.label || this.doctype)
: this.doc.name,
route: ''
} }
]; ];
}, },
@ -75,6 +69,13 @@ export default {
} }
}, },
created() { created() {
if (!this.defaults) {
this.defaults = {};
}
this.meta.fields.map(field => {
if (field.defaultValue)
this.defaults[field.fieldname] = field.defaultValue;
});
this.loadDoc(); this.loadDoc();
}, },
methods: { methods: {
@ -94,9 +95,9 @@ export default {
this.doc.set('name', ''); this.doc.set('name', '');
} }
if (this.defaultValues) { if (this.defaults) {
for (let fieldname in this.defaultValues) { for (let fieldname in this.defaults) {
const value = this.defaultValues[fieldname]; const value = this.defaults[fieldname];
this.doc.set(fieldname, value); this.doc.set(fieldname, value);
} }
} }
@ -105,9 +106,25 @@ export default {
this.doc.on('change', this.setLinks); this.doc.on('change', this.setLinks);
} catch (e) { } catch (e) {
this.notFound = true; this.notFound = true;
this.$router.push( }
`/list/${this.doctype === 'Party' ? 'Customer' : this.doctype}` },
); //if reloaded while insert new Item,Invoice etc form. getFormTitle() {
try {
// For different list/form based on same doctype since they will have different title
return (
this.meta.getFormTitle(this.doc) || this.meta.label || this.doctype
);
} catch (e) {
return this.meta.label || this.doctype;
}
},
getListTitle() {
try {
// For different list/form based on same doctype
// Since they will have different list route
return this.meta.getListTitle(this.doc);
} catch (e) {
return this.doctype;
} }
}, },
async save() { async save() {

View File

@ -1,12 +1,19 @@
<template> <template>
<div class="list-container"> <div class="list-container">
<list-row class="text-muted rounded-top bg-light"> <list-row class="text-muted rounded-top bg-light">
<list-cell v-for="column in columns" :key="column.label">{{ column.label }}</list-cell> <list-cell
v-for="column in columns"
:key="column.label"
:class="['Float', 'Currency'].includes(column.fieldtype) ? 'text-right':''"
>{{ column.label }}</list-cell>
</list-row> </list-row>
<list-row v-for="doc in data" :key="doc.name" @click.native="openForm(doc.name)"> <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"> <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> <span
style="width: 100%"
:class="['Float', 'Currency'].includes(column.fieldtype) ? 'text-right':''"
>{{ frappe.format(column.getValue(doc), column.fieldtype || {}) }}</span>
</list-cell> </list-cell>
</list-row> </list-row>
</div> </div>
@ -18,28 +25,31 @@ import ListCell from './ListCell';
export default { export default {
name: 'List', name: 'List',
props: ['listConfig'], props: ['listConfig', 'filters'],
components: { components: {
ListRow, ListRow,
ListCell ListCell
}, },
watch: { watch: {
listConfig(oldValue, newValue) { listConfig(oldValue, newValue) {
if ( if (oldValue.doctype !== newValue.doctype) {
oldValue.doctype !== newValue.doctype ||
// To differntiate Customer and Supplier List based on same Party Doctype
oldValue.title !== newValue.title
) {
this.setupColumnsAndData(); this.setupColumnsAndData();
} }
} }
}, },
data() { data() {
return { return {
columns: [],
data: [] data: []
}; };
}, },
computed: {
columns() {
return this.prepareColumns();
},
meta() {
return frappe.getMeta(this.listConfig.doctype);
}
},
async mounted() { async mounted() {
await this.setupColumnsAndData(); await this.setupColumnsAndData();
frappe.listView.on('filterList', this.updateData.bind(this)); frappe.listView.on('filterList', this.updateData.bind(this));
@ -47,28 +57,40 @@ export default {
methods: { methods: {
async setupColumnsAndData() { async setupColumnsAndData() {
this.doctype = this.listConfig.doctype; this.doctype = this.listConfig.doctype;
this.meta = frappe.getMeta(this.doctype);
await this.prepareColumns();
await this.updateData(); await this.updateData();
}, },
openForm(name) { openForm(name) {
this.$router.push(`/edit/${this.doctype}/${name}`); this.$router.push(`/edit/${this.doctype}/${name}`);
}, },
async updateData(keywords) { async updateData(filters) {
let filters = this.listConfig.filters || null; if (!filters) filters = this.getFilters();
if (keywords) { // since passing filters as URL params which is String
if (!filters) filters = {}; filters = this.formatFilters(filters);
filters.keywords = ['like', keywords];
}
this.data = await frappe.db.getAll({ this.data = await frappe.db.getAll({
doctype: this.doctype, doctype: this.doctype,
fields: ['*'], fields: ['*'],
filters filters
}); });
}, },
getFilters() {
let filters = {};
Object.assign(filters, this.listConfig.filters || {});
Object.assign(filters, this.filters);
return filters;
},
formatFilters(filters) {
for (let key in filters) {
let value = filters[key];
this.meta.fields.forEach(field => {
if (field.fieldname === key) {
filters[key] = frappe.format(value, field.fieldtype);
}
});
}
return filters;
},
prepareColumns() { prepareColumns() {
this.columns = this.listConfig.columns return this.listConfig.columns
.map(col => { .map(col => {
if (typeof col === 'string') { if (typeof col === 'string') {
const field = this.meta.getField(col); const field = this.meta.getField(col);

View File

@ -0,0 +1,45 @@
<template>
<div :key="usedToReRender">
<div
class="mr-2 d-flex"
v-for="filter in Object.keys(currentFilters)"
:key="filter"
style="user-select: none; "
>
<span
class="p-0 pl-2 py-1 badge badge-light border lead d-flex align-items-center font-weight-normal"
>
{{ filter }} = "{{ currentFilters[filter] }}"
<feather-icon class="mb-1 mx-2" name="x" @click.native="removeFilter(filter)" />
</span>
</div>
</div>
</template>
<script>
export default {
name: 'ListFilters',
props: ['filters'],
data() {
return {
currentFilters: this.filters,
usedToReRender: 0
};
},
computed: {
filterValues() {
return this.currentFilters;
}
},
methods: {
removeFilter(filter) {
delete this.currentFilters[filter];
frappe.listView.trigger('filterList', this.currentFilters);
this.usedToReRender += 1;
}
}
};
</script>
<style scoped>
</style>

View File

@ -1,26 +1,23 @@
<template> <template>
<div class="row"> <div class="d-flex mt-2">
<div class="col-6 d-flex"> <div style="flex: 1;">
<!-- <search-bar class="mr-2" @change="keyword => filterList(keyword)" /> --> <list-filters :filters="filters"></list-filters>
</div> </div>
<div class="col-6 d-flex flex-row-reverse"> <div class="d-flex flex-column-reverse" style="padding-bottom: 1rem;">
<f-button primary @click="$emit('newClick')">{{ _('New {0}', listConfig.title) }}</f-button> <f-button primary @click="$emit('newClick')">{{ _('New {0}', title) }}</f-button>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import SearchBar from '@/components/SearchBar'; import ListFilters from './ListFilters';
export default { export default {
name: 'ListToolbar', name: 'ListToolbar',
props: ['listConfig'], props: ['title', 'filters'],
components: { components: {
SearchBar ListFilters
},
methods: {
filterList(keyword) {
frappe.listView.trigger('filterList', keyword);
}
} }
}; };
</script> </script>

View File

@ -1,14 +1,9 @@
<template> <template>
<div class="bg-white"> <div class="bg-white">
<page-header :title="listConfig.title" /> <page-header :title="title" />
<div class="px-4 py-3"> <div class="px-4 py-3">
<list-toolbar <list-toolbar :title="title" :filters="filters" @newClick="openNewForm" class="mb-2" />
:listConfig="listConfig" <list :listConfig="listConfig" :filters="filters" />
@newClick="openNewForm"
@filterList="keyword => filterList(keyword)"
class="mb-4"
/>
<list :listConfig="listConfig" />
</div> </div>
</div> </div>
</template> </template>
@ -22,7 +17,7 @@ import listConfigs from './listConfig';
export default { export default {
name: 'ListView', name: 'ListView',
props: ['listName'], props: ['listName', 'filters'],
components: { components: {
PageHeader, PageHeader,
ListToolbar, ListToolbar,
@ -38,6 +33,9 @@ export default {
if (this.listConfig.filters) { if (this.listConfig.filters) {
doc.set(this.listConfig.filters); doc.set(this.listConfig.filters);
} }
if (this.filters) {
doc.set(this.filters);
}
this.$router.push(`/edit/${doctype}/${doc.name}`); this.$router.push(`/edit/${doctype}/${doc.name}`);
doc.on('afterInsert', () => { doc.on('afterInsert', () => {
this.$router.push(`/edit/${doctype}/${doc.name}`); this.$router.push(`/edit/${doctype}/${doc.name}`);
@ -58,6 +56,13 @@ export default {
}); });
this.$router.go(-1); this.$router.go(-1);
} }
},
title() {
try {
return this.listConfig.title(this.filters);
} catch (e) {
return this.listConfig.title;
}
} }
} }
}; };

View File

@ -1,11 +1,11 @@
<template> <template>
<div> <div>
<div class="px-3"> <div>
<div class="row pb-4 d-flex"> <div class="pb-4 d-flex">
<page-header :breadcrumbs="breadcrumbs" style="flex-grow: 1;" /> <page-header :breadcrumbs="breadcrumbs" style="flex-grow: 1;" />
<report-links class="d-flex flex-row-reverse" v-if="linksExists" :links="links"></report-links> <report-links class="d-flex flex-row-reverse" v-if="linksExists" :links="links"></report-links>
</div> </div>
<div class="row pb-4 pl-1"> <div class="pl-1">
<report-filters <report-filters
class="col-12" class="col-12"
v-if="shouldRenderFields" v-if="shouldRenderFields"
@ -13,9 +13,10 @@
:filterDoc="filterDoc" :filterDoc="filterDoc"
:filterDefaults="filters" :filterDefaults="filters"
@change="getReportData" @change="getReportData"
:key="usedToReRender"
></report-filters> ></report-filters>
</div> </div>
<div class="pt-2 pr-2 pl-2" ref="datatable" v-once></div> <div class="pt-2 px-4" ref="datatable" v-once></div>
</div> </div>
<not-found v-if="!reportConfig" /> <not-found v-if="!reportConfig" />
</div> </div>
@ -34,6 +35,7 @@ export default {
data() { data() {
return { return {
currentFilters: this.filters, currentFilters: this.filters,
usedToReRender: 0,
filterDoc: undefined, filterDoc: undefined,
links: [] links: []
}; };
@ -43,7 +45,7 @@ export default {
return [ return [
{ {
title: 'Reports', title: 'Reports',
route: '#/reportList' route: ''
}, },
{ {
title: this.reportConfig.title, title: this.reportConfig.title,
@ -94,14 +96,22 @@ export default {
} }
if (this.datatable) { if (this.datatable) {
if (rows.length) this.datatable.refresh(rows, columns); if (rows.length) {
this.datatable.refresh(rows, columns);
} else {
// remove all rows form datatable
this.datatable.wrapper.innerHTML = '';
this.datatable = undefined;
}
} else { } else {
this.datatable = new DataTable(this.$refs.datatable, { if (rows.length) {
columns: columns, this.datatable = new DataTable(this.$refs.datatable, {
data: rows, columns: columns,
treeView: this.reportConfig.treeView || false, data: rows,
cellHeight: 35 treeView: this.reportConfig.treeView || false,
}); cellHeight: 35
});
}
} }
return [rows, columns]; return [rows, columns];
}, },

View File

@ -1,9 +1,9 @@
<template> <template>
<div> <div>
<page-header title="Settings" /> <page-header title="Settings" />
<div class="row"> <div>
<div class="col-12 bg-white border p-5"> <div class="col-9 col-lg-7 col-xl-6 mx-2 mt-4">
<div class="col-9 col-lg-6 ml-1"> <div>
<setting-section doctype="AccountingSettings" /> <setting-section doctype="AccountingSettings" />
<hr class="mt-4" /> <hr class="mt-4" />
<setting-section doctype="CompanySettings" /> <setting-section doctype="CompanySettings" />

View File

@ -15,7 +15,7 @@
:doc="doc" :doc="doc"
:fields="fields" :fields="fields"
:layout="layout" :layout="layout"
:currentSection="currentSection" :currentSection="compCurrentSection"
/> />
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<div> <div>
@ -80,6 +80,9 @@ export default {
} }
}, },
computed: { computed: {
compCurrentSection() {
return this.currentSection;
},
fields() { fields() {
return this.meta.fields; return this.meta.fields;
}, },

View File

@ -29,7 +29,13 @@ const routes = [
path: '/list/:listName', path: '/list/:listName',
name: 'ListView', name: 'ListView',
component: ListView, component: ListView,
props: true props: route => {
const { listName } = route.params;
return {
listName,
filters: route.query
};
}
}, },
{ {
path: '/edit/:doctype/:name', path: '/edit/:doctype/:name',