mirror of
https://github.com/frappe/books.git
synced 2024-11-09 23:30:56 +00:00
feat: Party Widget in QuickEditForm
This commit is contained in:
parent
dc160a4232
commit
d05a50f01d
@ -1,6 +1,7 @@
|
||||
const frappe = require('frappejs');
|
||||
const { _ } = require('frappejs/utils');
|
||||
const router = require('@/router').default;
|
||||
const frappe = require('frappejs');
|
||||
const PartyWidget = require('./PartyWidget.vue').default;
|
||||
|
||||
module.exports = {
|
||||
name: 'Customer',
|
||||
@ -41,5 +42,12 @@ module.exports = {
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
quickEditWidget: doc => ({
|
||||
render(h) {
|
||||
return h(PartyWidget, {
|
||||
props: { doc }
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
|
@ -4,8 +4,6 @@ let { _ } = require('frappejs/utils');
|
||||
module.exports = {
|
||||
name: 'Party',
|
||||
label: 'Party',
|
||||
doctype: 'DocType',
|
||||
isSingle: 0,
|
||||
keywordFields: ['name'],
|
||||
fields: [
|
||||
{
|
||||
@ -53,8 +51,7 @@ module.exports = {
|
||||
{
|
||||
fieldname: 'outstandingAmount',
|
||||
label: 'Outstanding Amount',
|
||||
fieldtype: 'Currency',
|
||||
getCurrency: doc => doc.currency
|
||||
fieldtype: 'Currency'
|
||||
},
|
||||
{
|
||||
fieldname: 'currency',
|
||||
@ -97,79 +94,5 @@ module.exports = {
|
||||
}
|
||||
],
|
||||
|
||||
quickEditFields: ['email', 'phone', 'address', 'defaultAccount', 'currency'],
|
||||
|
||||
getFormTitle(doc) {
|
||||
if (doc.customer) return 'Customer';
|
||||
return 'Supplier';
|
||||
},
|
||||
|
||||
getListTitle(doc) {
|
||||
if (doc.customer) return 'Customer';
|
||||
return 'Supplier';
|
||||
},
|
||||
|
||||
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',
|
||||
condition: form => form.doc.customer,
|
||||
action: form => {
|
||||
form.$router.push({
|
||||
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',
|
||||
condition: form => form.doc.supplier,
|
||||
action: form => {
|
||||
form.$router.push({
|
||||
path: `/list/PurchaseInvoice?supplier=${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`
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
quickEditFields: ['email', 'phone', 'address', 'defaultAccount', 'currency']
|
||||
};
|
||||
|
118
models/doctype/Party/PartyWidget.vue
Normal file
118
models/doctype/Party/PartyWidget.vue
Normal file
@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<div class="py-4">
|
||||
<div class="px-4 text-sm text-gray-600 mb-1">
|
||||
{{ _('Recent Invoices') }}
|
||||
</div>
|
||||
<div
|
||||
class="px-4 py-3 border-b hover:bg-gray-100 cursor-pointer"
|
||||
v-for="invoice in pendingInvoices"
|
||||
:key="invoice.name"
|
||||
@click="routeToForm(invoice)"
|
||||
>
|
||||
<div class="text-base">
|
||||
<div class="flex justify-between items-center mb-1">
|
||||
<span class="font-medium">
|
||||
{{ invoice.name }}
|
||||
</span>
|
||||
<span>
|
||||
<component :is="getStatusBadge(invoice)" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span>
|
||||
{{ frappe.format(invoice.date, invoiceMeta.getField('date')) }}
|
||||
</span>
|
||||
<div>
|
||||
<span
|
||||
class="font-medium text-gray-900"
|
||||
v-if="fullyPaid(invoice) || notPaid(invoice)"
|
||||
>
|
||||
{{
|
||||
frappe.format(
|
||||
invoice.baseGrandTotal,
|
||||
invoiceMeta.getField('baseGrandTotal')
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
<span class="text-gray-600" v-if="partiallyPaid(invoice)">
|
||||
({{
|
||||
frappe.format(
|
||||
invoice.baseGrandTotal,
|
||||
invoiceMeta.getField('baseGrandTotal')
|
||||
)
|
||||
}})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import frappe from 'frappejs';
|
||||
import { getStatusColumn } from '../Transaction/Transaction';
|
||||
|
||||
export default {
|
||||
name: 'PartyWidget',
|
||||
props: ['doc'],
|
||||
data() {
|
||||
return {
|
||||
pendingInvoices: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
invoiceDoctype() {
|
||||
let isCustomer = this.doc.doctype === 'Customer';
|
||||
return isCustomer ? 'SalesInvoice' : 'PurchaseInvoice';
|
||||
},
|
||||
invoiceMeta() {
|
||||
return frappe.getMeta(this.invoiceDoctype);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchPendingInvoices();
|
||||
},
|
||||
methods: {
|
||||
async fetchPendingInvoices() {
|
||||
let isCustomer = this.doc.doctype === 'Customer';
|
||||
let doctype = this.invoiceDoctype;
|
||||
let partyField = isCustomer ? 'customer' : 'supplier';
|
||||
this.pendingInvoices = await frappe.db.getAll({
|
||||
doctype,
|
||||
fields: [
|
||||
'name',
|
||||
'date',
|
||||
'outstandingAmount',
|
||||
'baseGrandTotal',
|
||||
'submitted'
|
||||
],
|
||||
filters: {
|
||||
[partyField]: this.doc.name
|
||||
},
|
||||
limit: 3,
|
||||
orderBy: 'creation'
|
||||
});
|
||||
},
|
||||
getStatusBadge(doc) {
|
||||
let statusColumn = getStatusColumn();
|
||||
return statusColumn.render(doc);
|
||||
},
|
||||
routeToForm(doc) {
|
||||
this.$router.push(`/edit/${this.invoiceDoctype}/${doc.name}`);
|
||||
},
|
||||
fullyPaid(invoice) {
|
||||
return invoice.outstandingAmount == 0;
|
||||
},
|
||||
partiallyPaid(invoice) {
|
||||
return (
|
||||
invoice.outstandingAmount &&
|
||||
invoice.outstandingAmount !== invoice.baseGrandTotal
|
||||
);
|
||||
},
|
||||
notPaid(invoice) {
|
||||
return invoice.outstandingAmount === invoice.baseGrandTotal;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -1,6 +1,7 @@
|
||||
const { _ } = require('frappejs/utils');
|
||||
const router = require('@/router').default;
|
||||
const frappe = require('frappejs');
|
||||
const PartyWidget = require('./PartyWidget.vue').default;
|
||||
|
||||
module.exports = {
|
||||
name: 'Supplier',
|
||||
@ -41,5 +42,12 @@ module.exports = {
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
quickEditWidget: doc => ({
|
||||
render(h) {
|
||||
return h(PartyWidget, {
|
||||
props: { doc }
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
|
@ -62,7 +62,8 @@ function createSettingsWindow(tab = 'General') {
|
||||
backgroundColor: theme.backgroundColor.gray['200'],
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
}
|
||||
},
|
||||
resizable: false
|
||||
});
|
||||
|
||||
settingsWindow.loadURL(`${winURL}#/settings/${tab}`);
|
||||
|
@ -70,6 +70,7 @@
|
||||
:autosave="true"
|
||||
:column-ratio="[1.1, 2]"
|
||||
/>
|
||||
<component v-if="doc && quickEditWidget" :is="quickEditWidget" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -123,6 +124,12 @@ export default {
|
||||
},
|
||||
actions() {
|
||||
return getActionsForDocument(this.doc);
|
||||
},
|
||||
quickEditWidget() {
|
||||
if (!this.meta.quickEditWidget) {
|
||||
return null;
|
||||
}
|
||||
return this.meta.quickEditWidget(this.doc);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
Loading…
Reference in New Issue
Block a user