2
0
mirror of https://github.com/frappe/books.git synced 2024-11-09 23:30:56 +00:00

fix(ux): Add sections for a few Entry types

- remove widgets from the QuickEditForm
- remove redundant files
This commit is contained in:
18alantom 2023-04-14 15:31:04 +05:30
parent c158ae8100
commit d9415233f5
8 changed files with 137 additions and 376 deletions

View File

@ -6,11 +6,28 @@
"isChild": false, "isChild": false,
"naming": "autoincrement", "naming": "autoincrement",
"fields": [ "fields": [
{
"label": "Entry No.",
"fieldname": "name",
"fieldtype": "Data",
"required": true,
"readOnly": true,
"section": "Default"
},
{ {
"fieldname": "date", "fieldname": "date",
"label": "Date", "label": "Date",
"fieldtype": "Datetime", "fieldtype": "Datetime",
"readOnly": true "readOnly": true,
"section": "Default"
},
{
"fieldname": "party",
"label": "Party",
"fieldtype": "Link",
"target": "Party",
"readOnly": true,
"section": "Default"
}, },
{ {
"fieldname": "account", "fieldname": "account",
@ -18,53 +35,53 @@
"fieldtype": "Link", "fieldtype": "Link",
"target": "Account", "target": "Account",
"required": true, "required": true,
"readOnly": true "readOnly": true,
}, "section": "Default"
{
"fieldname": "party",
"label": "Party",
"fieldtype": "Link",
"target": "Party",
"readOnly": true
}, },
{ {
"fieldname": "debit", "fieldname": "debit",
"label": "Debit", "label": "Debit",
"fieldtype": "Currency", "fieldtype": "Currency",
"readOnly": true "readOnly": true,
"section": "Details"
}, },
{ {
"fieldname": "credit", "fieldname": "credit",
"label": "Credit", "label": "Credit",
"fieldtype": "Currency", "fieldtype": "Currency",
"readOnly": true "readOnly": true,
"section": "Details"
}, },
{ {
"fieldname": "referenceType", "fieldname": "referenceType",
"label": "Ref. Type", "label": "Ref. Type",
"fieldtype": "Data", "fieldtype": "Data",
"readOnly": true "readOnly": true,
"section": "Reference"
}, },
{ {
"fieldname": "referenceName", "fieldname": "referenceName",
"label": "Ref. Name", "label": "Ref. Name",
"fieldtype": "DynamicLink", "fieldtype": "DynamicLink",
"references": "referenceType", "references": "referenceType",
"readOnly": true "readOnly": true,
"section": "Reference"
}, },
{ {
"fieldname": "reverted", "fieldname": "reverted",
"label": "Reverted", "label": "Reverted",
"fieldtype": "Check", "fieldtype": "Check",
"default": false, "default": false,
"readOnly": true "readOnly": true,
"section": "Reference"
}, },
{ {
"fieldname": "reverts", "fieldname": "reverts",
"label": "Reverts", "label": "Reverts",
"fieldtype": "Link", "fieldtype": "Link",
"target": "AccountingLedgerEntry", "target": "AccountingLedgerEntry",
"readOnly": true "readOnly": true,
"section": "Reference"
} }
], ],
"quickEditFields": [ "quickEditFields": [

View File

@ -3,17 +3,19 @@
"label": "Party", "label": "Party",
"naming": "manual", "naming": "manual",
"fields": [ "fields": [
{
"fieldname": "image",
"label": "Image",
"fieldtype": "AttachImage",
"section": "Default"
},
{ {
"fieldname": "name", "fieldname": "name",
"label": "Name", "label": "Name",
"fieldtype": "Data", "fieldtype": "Data",
"required": true, "required": true,
"placeholder": "Full Name" "placeholder": "Full Name",
}, "section": "Default"
{
"fieldname": "image",
"label": "Image",
"fieldtype": "AttachImage"
}, },
{ {
"fieldname": "role", "fieldname": "role",
@ -34,20 +36,38 @@
"label": "Customer" "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", "fieldname": "defaultAccount",
"label": "Default Account", "label": "Default Account",
"fieldtype": "Link", "fieldtype": "Link",
"target": "Account", "target": "Account",
"create": true "create": true,
}, "section": "Billing"
{
"fieldname": "outstandingAmount",
"label": "Outstanding Amount",
"fieldtype": "Currency",
"hidden": true
}, },
{ {
"fieldname": "currency", "fieldname": "currency",
@ -55,31 +75,20 @@
"fieldtype": "Link", "fieldtype": "Link",
"target": "Currency", "target": "Currency",
"placeholder": "INR", "placeholder": "INR",
"create": true "create": true,
}, "section": "Billing"
{
"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
}, },
{ {
"fieldname": "taxId", "fieldname": "taxId",
"label": "Tax ID", "label": "Tax ID",
"fieldtype": "Data" "fieldtype": "Data",
"section": "Billing"
},
{
"fieldname": "outstandingAmount",
"label": "Outstanding Amount",
"fieldtype": "Currency",
"hidden": true
} }
], ],
"quickEditFields": [ "quickEditFields": [

View File

@ -6,57 +6,73 @@
"isChild": false, "isChild": false,
"naming": "autoincrement", "naming": "autoincrement",
"fields": [ "fields": [
{
"label": "Entry No.",
"fieldname": "name",
"fieldtype": "Data",
"required": true,
"readOnly": true,
"section": "Default"
},
{ {
"fieldname": "date", "fieldname": "date",
"label": "Date", "label": "Date",
"fieldtype": "Datetime", "fieldtype": "Datetime",
"readOnly": true "readOnly": true,
}, "section": "Default"
{
"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
}, },
{ {
"fieldname": "location", "fieldname": "location",
"label": "Location", "label": "Location",
"fieldtype": "Link", "fieldtype": "Link",
"target": "Location", "target": "Location",
"readOnly": true "readOnly": true,
}, "section": "Details"
{
"fieldname": "referenceName",
"label": "Ref. Name",
"fieldtype": "DynamicLink",
"references": "referenceType",
"readOnly": true
},
{
"fieldname": "referenceType",
"label": "Ref. Type",
"fieldtype": "Data",
"readOnly": true
}, },
{ {
"fieldname": "batch", "fieldname": "batch",
"label": "Batch", "label": "Batch",
"fieldtype": "Link", "fieldtype": "Link",
"target": "Batch", "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"
} }
] ]
} }

View File

@ -1,11 +1,6 @@
{ {
"name": "Party", "name": "Party",
"fields": [ "fields": [
{
"fieldname": "gstin",
"label": "GSTIN No.",
"fieldtype": "Data"
},
{ {
"fieldname": "gstType", "fieldname": "gstType",
"label": "GST Registration", "label": "GST Registration",
@ -25,7 +20,14 @@
"value": "Consumer", "value": "Consumer",
"label": "Consumer" "label": "Consumer"
} }
] ],
"section": "Billing"
},
{
"fieldname": "gstin",
"label": "GSTIN No.",
"fieldtype": "Data",
"section": "Billing"
} }
], ],
"quickEditFields": [ "quickEditFields": [

View File

@ -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>

View File

@ -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>

View File

@ -96,12 +96,8 @@
:fields="fields" :fields="fields"
:column-ratio="[1.1, 2]" :column-ratio="[1.1, 2]"
/> />
<!-- QuickEdit Widgets -->
<component v-if="quickEditWidget" :is="quickEditWidget" />
</div> </div>
</template> </template>
<script> <script>
import { computed } from '@vue/reactivity'; import { computed } from '@vue/reactivity';
import { t } from 'fyo'; import { t } from 'fyo';
@ -114,7 +110,6 @@ import StatusBadge from 'src/components/StatusBadge.vue';
import TwoColumnForm from 'src/components/TwoColumnForm.vue'; import TwoColumnForm from 'src/components/TwoColumnForm.vue';
import { fyo } from 'src/initFyo'; import { fyo } from 'src/initFyo';
import { shortcutsKey } from 'src/utils/injectionKeys'; import { shortcutsKey } from 'src/utils/injectionKeys';
import { getQuickEditWidget } from 'src/utils/quickEditWidgets';
import { import {
commonDocSubmit, commonDocSubmit,
commonDocSync, commonDocSync,
@ -123,7 +118,7 @@ import {
openQuickEdit, openQuickEdit,
} from 'src/utils/ui'; } from 'src/utils/ui';
import { useDocShortcuts } from 'src/utils/vueUtils'; import { useDocShortcuts } from 'src/utils/vueUtils';
import { ref, inject } from 'vue'; import { inject, ref } from 'vue';
export default { export default {
name: 'QuickEditForm', name: 'QuickEditForm',
@ -136,8 +131,6 @@ export default {
showName: { type: Boolean, default: true }, showName: { type: Boolean, default: true },
showSave: { type: Boolean, default: true }, showSave: { type: Boolean, default: true },
sourceDoc: { type: Doc, default: null }, sourceDoc: { type: Doc, default: null },
loadOnClose: { type: Boolean, default: true },
sourceFields: { type: Array, default: () => [] },
hideFields: { type: Array, default: () => [] }, hideFields: { type: Array, default: () => [] },
showFields: { type: Array, default: () => [] }, showFields: { type: Array, default: () => [] },
}, },
@ -205,10 +198,6 @@ export default {
return getDocStatus(this.doc); return getDocStatus(this.doc);
}, },
fields() { fields() {
if (this.sourceFields?.length) {
return this.sourceFields;
}
if (!this.schema) { if (!this.schema) {
return []; return [];
} }
@ -230,18 +219,6 @@ export default {
actions() { actions() {
return getActionsForDoc(this.doc); 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: { methods: {
setShortcuts() { setShortcuts() {
@ -316,7 +293,7 @@ export default {
}, 300); }, 300);
}, },
routeToPrevious() { routeToPrevious() {
if (this.loadOnClose && this.doc.dirty && !this.doc.notInserted) { if (this.doc.dirty && !this.doc.notInserted) {
this.doc.load(); this.doc.load();
} }

View File

@ -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;
}