mirror of
https://github.com/frappe/books.git
synced 2025-02-02 12:08:27 +00:00
fix(ux): Add sections for a few Entry types
- remove widgets from the QuickEditForm - remove redundant files
This commit is contained in:
parent
c158ae8100
commit
d9415233f5
@ -6,11 +6,28 @@
|
||||
"isChild": false,
|
||||
"naming": "autoincrement",
|
||||
"fields": [
|
||||
{
|
||||
"label": "Entry No.",
|
||||
"fieldname": "name",
|
||||
"fieldtype": "Data",
|
||||
"required": true,
|
||||
"readOnly": true,
|
||||
"section": "Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "date",
|
||||
"label": "Date",
|
||||
"fieldtype": "Datetime",
|
||||
"readOnly": true
|
||||
"readOnly": true,
|
||||
"section": "Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "party",
|
||||
"label": "Party",
|
||||
"fieldtype": "Link",
|
||||
"target": "Party",
|
||||
"readOnly": true,
|
||||
"section": "Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "account",
|
||||
@ -18,53 +35,53 @@
|
||||
"fieldtype": "Link",
|
||||
"target": "Account",
|
||||
"required": true,
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"fieldname": "party",
|
||||
"label": "Party",
|
||||
"fieldtype": "Link",
|
||||
"target": "Party",
|
||||
"readOnly": true
|
||||
"readOnly": true,
|
||||
"section": "Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "debit",
|
||||
"label": "Debit",
|
||||
"fieldtype": "Currency",
|
||||
"readOnly": true
|
||||
"readOnly": true,
|
||||
"section": "Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "credit",
|
||||
"label": "Credit",
|
||||
"fieldtype": "Currency",
|
||||
"readOnly": true
|
||||
"readOnly": true,
|
||||
"section": "Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "referenceType",
|
||||
"label": "Ref. Type",
|
||||
"fieldtype": "Data",
|
||||
"readOnly": true
|
||||
"readOnly": true,
|
||||
"section": "Reference"
|
||||
},
|
||||
{
|
||||
"fieldname": "referenceName",
|
||||
"label": "Ref. Name",
|
||||
"fieldtype": "DynamicLink",
|
||||
"references": "referenceType",
|
||||
"readOnly": true
|
||||
"readOnly": true,
|
||||
"section": "Reference"
|
||||
},
|
||||
{
|
||||
"fieldname": "reverted",
|
||||
"label": "Reverted",
|
||||
"fieldtype": "Check",
|
||||
"default": false,
|
||||
"readOnly": true
|
||||
"readOnly": true,
|
||||
"section": "Reference"
|
||||
},
|
||||
{
|
||||
"fieldname": "reverts",
|
||||
"label": "Reverts",
|
||||
"fieldtype": "Link",
|
||||
"target": "AccountingLedgerEntry",
|
||||
"readOnly": true
|
||||
"readOnly": true,
|
||||
"section": "Reference"
|
||||
}
|
||||
],
|
||||
"quickEditFields": [
|
||||
|
@ -3,17 +3,19 @@
|
||||
"label": "Party",
|
||||
"naming": "manual",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "image",
|
||||
"label": "Image",
|
||||
"fieldtype": "AttachImage",
|
||||
"section": "Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "name",
|
||||
"label": "Name",
|
||||
"fieldtype": "Data",
|
||||
"required": true,
|
||||
"placeholder": "Full Name"
|
||||
},
|
||||
{
|
||||
"fieldname": "image",
|
||||
"label": "Image",
|
||||
"fieldtype": "AttachImage"
|
||||
"placeholder": "Full Name",
|
||||
"section": "Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "role",
|
||||
@ -34,20 +36,38 @@
|
||||
"label": "Customer"
|
||||
}
|
||||
],
|
||||
"required": true
|
||||
"required": true,
|
||||
"section": "Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "email",
|
||||
"label": "Email",
|
||||
"fieldtype": "Data",
|
||||
"placeholder": "john@doe.com",
|
||||
"section": "Contacts"
|
||||
},
|
||||
{
|
||||
"fieldname": "phone",
|
||||
"label": "Phone",
|
||||
"fieldtype": "Data",
|
||||
"placeholder": "Phone",
|
||||
"section": "Contacts"
|
||||
},
|
||||
{
|
||||
"fieldname": "address",
|
||||
"label": "Address",
|
||||
"fieldtype": "Link",
|
||||
"target": "Address",
|
||||
"create": true,
|
||||
"section": "Contacts"
|
||||
},
|
||||
{
|
||||
"fieldname": "defaultAccount",
|
||||
"label": "Default Account",
|
||||
"fieldtype": "Link",
|
||||
"target": "Account",
|
||||
"create": true
|
||||
},
|
||||
{
|
||||
"fieldname": "outstandingAmount",
|
||||
"label": "Outstanding Amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": true
|
||||
"create": true,
|
||||
"section": "Billing"
|
||||
},
|
||||
{
|
||||
"fieldname": "currency",
|
||||
@ -55,31 +75,20 @@
|
||||
"fieldtype": "Link",
|
||||
"target": "Currency",
|
||||
"placeholder": "INR",
|
||||
"create": true
|
||||
},
|
||||
{
|
||||
"fieldname": "email",
|
||||
"label": "Email",
|
||||
"fieldtype": "Data",
|
||||
"placeholder": "john@doe.com"
|
||||
},
|
||||
{
|
||||
"fieldname": "phone",
|
||||
"label": "Phone",
|
||||
"fieldtype": "Data",
|
||||
"placeholder": "Phone"
|
||||
},
|
||||
{
|
||||
"fieldname": "address",
|
||||
"label": "Address",
|
||||
"fieldtype": "Link",
|
||||
"target": "Address",
|
||||
"create": true
|
||||
"create": true,
|
||||
"section": "Billing"
|
||||
},
|
||||
{
|
||||
"fieldname": "taxId",
|
||||
"label": "Tax ID",
|
||||
"fieldtype": "Data"
|
||||
"fieldtype": "Data",
|
||||
"section": "Billing"
|
||||
},
|
||||
{
|
||||
"fieldname": "outstandingAmount",
|
||||
"label": "Outstanding Amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": true
|
||||
}
|
||||
],
|
||||
"quickEditFields": [
|
||||
|
@ -6,57 +6,73 @@
|
||||
"isChild": false,
|
||||
"naming": "autoincrement",
|
||||
"fields": [
|
||||
{
|
||||
"label": "Entry No.",
|
||||
"fieldname": "name",
|
||||
"fieldtype": "Data",
|
||||
"required": true,
|
||||
"readOnly": true,
|
||||
"section": "Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "date",
|
||||
"label": "Date",
|
||||
"fieldtype": "Datetime",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"fieldname": "item",
|
||||
"label": "Item",
|
||||
"fieldtype": "Link",
|
||||
"target": "Item",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"fieldname": "rate",
|
||||
"label": "Rate",
|
||||
"fieldtype": "Currency",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"fieldname": "quantity",
|
||||
"label": "Quantity",
|
||||
"fieldtype": "Float",
|
||||
"readOnly": true
|
||||
"readOnly": true,
|
||||
"section": "Default"
|
||||
},
|
||||
{
|
||||
"fieldname": "location",
|
||||
"label": "Location",
|
||||
"fieldtype": "Link",
|
||||
"target": "Location",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"fieldname": "referenceName",
|
||||
"label": "Ref. Name",
|
||||
"fieldtype": "DynamicLink",
|
||||
"references": "referenceType",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"fieldname": "referenceType",
|
||||
"label": "Ref. Type",
|
||||
"fieldtype": "Data",
|
||||
"readOnly": true
|
||||
"readOnly": true,
|
||||
"section": "Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "batch",
|
||||
"label": "Batch",
|
||||
"fieldtype": "Link",
|
||||
"target": "Batch",
|
||||
"readOnly": true
|
||||
"readOnly": true,
|
||||
"section": "Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "item",
|
||||
"label": "Item",
|
||||
"fieldtype": "Link",
|
||||
"target": "Item",
|
||||
"readOnly": true,
|
||||
"section": "Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "rate",
|
||||
"label": "Rate",
|
||||
"fieldtype": "Currency",
|
||||
"readOnly": true,
|
||||
"section": "Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "quantity",
|
||||
"label": "Quantity",
|
||||
"fieldtype": "Float",
|
||||
"readOnly": true,
|
||||
"section": "Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "referenceType",
|
||||
"label": "Ref. Type",
|
||||
"fieldtype": "Data",
|
||||
"readOnly": true,
|
||||
"section": "Reference"
|
||||
},
|
||||
{
|
||||
"fieldname": "referenceName",
|
||||
"label": "Ref. Name",
|
||||
"fieldtype": "DynamicLink",
|
||||
"references": "referenceType",
|
||||
"readOnly": true,
|
||||
"section": "Reference"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1,11 +1,6 @@
|
||||
{
|
||||
"name": "Party",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "gstin",
|
||||
"label": "GSTIN No.",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldname": "gstType",
|
||||
"label": "GST Registration",
|
||||
@ -25,7 +20,14 @@
|
||||
"value": "Consumer",
|
||||
"label": "Consumer"
|
||||
}
|
||||
]
|
||||
],
|
||||
"section": "Billing"
|
||||
},
|
||||
{
|
||||
"fieldname": "gstin",
|
||||
"label": "GSTIN No.",
|
||||
"fieldtype": "Data",
|
||||
"section": "Billing"
|
||||
}
|
||||
],
|
||||
"quickEditFields": [
|
||||
|
@ -1,98 +0,0 @@
|
||||
<template>
|
||||
<div class="w-quick-edit border-s bg-white flex flex-col">
|
||||
<!-- Linked Entry Title -->
|
||||
<div class="flex items-center justify-between px-4 h-row-largest border-b">
|
||||
<Button :icon="true" @click="$emit('close-widget')">
|
||||
<feather-icon name="x" class="w-4 h-4" />
|
||||
</Button>
|
||||
<p class="font-semibold text-xl text-gray-600">
|
||||
{{ linked.title }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Linked Entry Items -->
|
||||
<div
|
||||
v-for="entry in linked.entries"
|
||||
:key="entry.name"
|
||||
class="p-4 border-b flex flex-col hover:bg-gray-50 cursor-pointer"
|
||||
@click="openEntry(entry.name)"
|
||||
>
|
||||
<!-- Name And Status -->
|
||||
<div class="mb-2 flex justify-between items-center">
|
||||
<p class="font-semibold text-gray-900">
|
||||
{{ entry.name }}
|
||||
</p>
|
||||
<StatusBadge
|
||||
:status="getStatus(entry)"
|
||||
:default-size="false"
|
||||
class="px-0 text-xs"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Date and Amount -->
|
||||
<div class="text-sm flex justify-between items-center">
|
||||
<p>
|
||||
{{ fyo.format(entry.date as Date, 'Date') }}
|
||||
</p>
|
||||
<p>{{ fyo.format(entry.amount as Money, 'Currency') }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Quantity and Location -->
|
||||
<div
|
||||
v-if="['Shipment', 'PurchaseReceipt'].includes(linked.schemaName)"
|
||||
class="text-sm flex justify-between items-center mt-1"
|
||||
>
|
||||
<p>
|
||||
{{ entry.location }}
|
||||
</p>
|
||||
<p>
|
||||
{{ t`Qty. ${fyo.format(entry.quantity as number, 'Float')}` }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Money } from 'pesa';
|
||||
import { getFormRoute, routeTo } from 'src/utils/ui';
|
||||
import { defineComponent, PropType } from 'vue';
|
||||
import Button from '../Button.vue';
|
||||
import StatusBadge from '../StatusBadge.vue';
|
||||
|
||||
interface Linked {
|
||||
schemaName: string;
|
||||
title: string;
|
||||
entries: {
|
||||
name: string;
|
||||
cancelled: boolean;
|
||||
submitted: boolean;
|
||||
[key: string]: unknown;
|
||||
}[];
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
emits: ['close-widget'],
|
||||
props: {
|
||||
linked: { type: Object as PropType<Linked>, required: true },
|
||||
},
|
||||
methods: {
|
||||
getStatus(entry: { cancelled?: boolean; submitted?: boolean }) {
|
||||
if (entry.cancelled) {
|
||||
return 'Cancelled';
|
||||
}
|
||||
|
||||
if (entry.submitted) {
|
||||
return 'Submitted';
|
||||
}
|
||||
|
||||
return 'Saved';
|
||||
},
|
||||
async openEntry(name: string) {
|
||||
const route = getFormRoute(this.linked.schemaName, name);
|
||||
await routeTo(route);
|
||||
},
|
||||
},
|
||||
components: { Button, StatusBadge },
|
||||
});
|
||||
</script>
|
@ -1,144 +0,0 @@
|
||||
<template>
|
||||
<div v-if="pendingInvoices.length">
|
||||
<div
|
||||
class="
|
||||
px-4
|
||||
text-sm text-gray-600
|
||||
border-b
|
||||
flex
|
||||
items-center
|
||||
h-row-smallest
|
||||
"
|
||||
>
|
||||
{{ t`Recent Invoices` }}
|
||||
</div>
|
||||
|
||||
<!-- Invoice List -->
|
||||
<div
|
||||
class="px-4 py-4 border-b hover:bg-gray-50 cursor-pointer text-base"
|
||||
v-for="invoice in pendingInvoices"
|
||||
:key="invoice.name"
|
||||
@click="routeToForm(invoice)"
|
||||
>
|
||||
<!-- Invoice Name & Status -->
|
||||
<div class="flex justify-between items-center mb-1">
|
||||
<span class="font-medium">
|
||||
{{ invoice.name }}
|
||||
</span>
|
||||
<span>
|
||||
<component :is="getStatusBadge(invoice)" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Invoice Date & Amount -->
|
||||
<div class="flex justify-between text-gray-900">
|
||||
<span>
|
||||
{{ fyo.format(invoice.date, getInvoiceField(invoice, 'date')) }}
|
||||
</span>
|
||||
<div>
|
||||
<!-- Paid Amount -->
|
||||
<span>
|
||||
{{
|
||||
fyo.format(
|
||||
amountPaid(invoice),
|
||||
getInvoiceField(invoice, 'baseGrandTotal')
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
|
||||
<!-- Outstanding Amount -->
|
||||
<span class="text-gray-600 font-medium" v-if="!fullyPaid(invoice)">
|
||||
({{
|
||||
fyo.format(
|
||||
invoice.outstandingAmount,
|
||||
getInvoiceField(invoice, 'outstandingAmount')
|
||||
)
|
||||
}})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Doc } from 'fyo/model/doc';
|
||||
import { PartyRoleEnum } from 'models/baseModels/Party/types';
|
||||
import { getTransactionStatusColumn } from 'models/helpers';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import { routeTo } from 'src/utils/ui';
|
||||
|
||||
export default {
|
||||
name: 'PartyWidget',
|
||||
props: { doc: Doc },
|
||||
data() {
|
||||
return {
|
||||
pendingInvoices: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
invoiceSchemaNames() {
|
||||
switch (this.doc.get('role')) {
|
||||
case PartyRoleEnum.Customer:
|
||||
return [ModelNameEnum.SalesInvoice];
|
||||
case PartyRoleEnum.Supplier:
|
||||
return [ModelNameEnum.PurchaseInvoice];
|
||||
case PartyRoleEnum.Both:
|
||||
default:
|
||||
return [ModelNameEnum.SalesInvoice, ModelNameEnum.PurchaseInvoice];
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.fetchPendingInvoices();
|
||||
},
|
||||
methods: {
|
||||
getInvoiceField(invoice, fieldname) {
|
||||
return fyo.getField(invoice.schemaName, fieldname);
|
||||
},
|
||||
async fetchPendingInvoices() {
|
||||
const pendingInvoices = [];
|
||||
for (const schemaName of this.invoiceSchemaNames) {
|
||||
const invoices = await fyo.db.getAll(schemaName, {
|
||||
fields: [
|
||||
'name',
|
||||
'date',
|
||||
'outstandingAmount',
|
||||
'baseGrandTotal',
|
||||
'submitted',
|
||||
],
|
||||
filters: {
|
||||
party: this.doc.name,
|
||||
cancelled: false,
|
||||
},
|
||||
limit: 3,
|
||||
orderBy: 'created',
|
||||
});
|
||||
|
||||
invoices.forEach((i) => {
|
||||
i.schemaName = schemaName;
|
||||
i.schema = fyo.schemaMap[schemaName];
|
||||
});
|
||||
|
||||
pendingInvoices.push(...invoices);
|
||||
}
|
||||
|
||||
this.pendingInvoices = pendingInvoices;
|
||||
},
|
||||
getStatusBadge(doc) {
|
||||
const statusColumn = getTransactionStatusColumn();
|
||||
return statusColumn.render(doc);
|
||||
},
|
||||
routeToForm(invoice) {
|
||||
routeTo(`/edit/${invoice.schemaName}/${invoice.name}`);
|
||||
},
|
||||
fullyPaid(invoice) {
|
||||
return invoice.outstandingAmount.isZero();
|
||||
},
|
||||
amountPaid(invoice) {
|
||||
return invoice.baseGrandTotal.sub(invoice.outstandingAmount);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
@ -96,12 +96,8 @@
|
||||
:fields="fields"
|
||||
:column-ratio="[1.1, 2]"
|
||||
/>
|
||||
|
||||
<!-- QuickEdit Widgets -->
|
||||
<component v-if="quickEditWidget" :is="quickEditWidget" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { computed } from '@vue/reactivity';
|
||||
import { t } from 'fyo';
|
||||
@ -114,7 +110,6 @@ import StatusBadge from 'src/components/StatusBadge.vue';
|
||||
import TwoColumnForm from 'src/components/TwoColumnForm.vue';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import { shortcutsKey } from 'src/utils/injectionKeys';
|
||||
import { getQuickEditWidget } from 'src/utils/quickEditWidgets';
|
||||
import {
|
||||
commonDocSubmit,
|
||||
commonDocSync,
|
||||
@ -123,7 +118,7 @@ import {
|
||||
openQuickEdit,
|
||||
} from 'src/utils/ui';
|
||||
import { useDocShortcuts } from 'src/utils/vueUtils';
|
||||
import { ref, inject } from 'vue';
|
||||
import { inject, ref } from 'vue';
|
||||
|
||||
export default {
|
||||
name: 'QuickEditForm',
|
||||
@ -136,8 +131,6 @@ export default {
|
||||
showName: { type: Boolean, default: true },
|
||||
showSave: { type: Boolean, default: true },
|
||||
sourceDoc: { type: Doc, default: null },
|
||||
loadOnClose: { type: Boolean, default: true },
|
||||
sourceFields: { type: Array, default: () => [] },
|
||||
hideFields: { type: Array, default: () => [] },
|
||||
showFields: { type: Array, default: () => [] },
|
||||
},
|
||||
@ -205,10 +198,6 @@ export default {
|
||||
return getDocStatus(this.doc);
|
||||
},
|
||||
fields() {
|
||||
if (this.sourceFields?.length) {
|
||||
return this.sourceFields;
|
||||
}
|
||||
|
||||
if (!this.schema) {
|
||||
return [];
|
||||
}
|
||||
@ -230,18 +219,6 @@ export default {
|
||||
actions() {
|
||||
return getActionsForDoc(this.doc);
|
||||
},
|
||||
quickEditWidget() {
|
||||
if (this.doc?.notInserted ?? true) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const widget = getQuickEditWidget(this.schemaName);
|
||||
if (widget === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return widget(this.doc);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setShortcuts() {
|
||||
@ -316,7 +293,7 @@ export default {
|
||||
}, 300);
|
||||
},
|
||||
routeToPrevious() {
|
||||
if (this.loadOnClose && this.doc.dirty && !this.doc.notInserted) {
|
||||
if (this.doc.dirty && !this.doc.notInserted) {
|
||||
this.doc.load();
|
||||
}
|
||||
|
||||
|
@ -1,18 +0,0 @@
|
||||
import { Doc } from 'fyo/model/doc';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
import PartyWidget from 'src/components/Widgets/PartyWidget.vue';
|
||||
import { h } from 'vue';
|
||||
|
||||
export function getQuickEditWidget(schemaName: string) {
|
||||
if (schemaName === ModelNameEnum.Party) {
|
||||
return (doc: Doc) => ({
|
||||
render() {
|
||||
return h(PartyWidget, {
|
||||
doc,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user