mirror of
https://github.com/frappe/books.git
synced 2025-02-02 12:08:27 +00:00
fix(ux): improve status indication
This commit is contained in:
parent
d5b881c98f
commit
daebdb0ea9
@ -1,6 +1,6 @@
|
||||
import { DocValue, DocValueMap } from 'fyo/core/types';
|
||||
import SystemSettings from 'fyo/models/SystemSettings';
|
||||
import { FieldType, SelectOption } from 'schemas/types';
|
||||
import { FieldType, Schema, SelectOption } from 'schemas/types';
|
||||
import { QueryFilter } from 'utils/db/types';
|
||||
import { Router } from 'vue-router';
|
||||
import { Doc } from './doc';
|
||||
@ -69,12 +69,17 @@ export interface Action {
|
||||
};
|
||||
}
|
||||
|
||||
export interface RenderData {
|
||||
schema: Schema,
|
||||
[key: string]: DocValue | Schema
|
||||
}
|
||||
|
||||
export interface ColumnConfig {
|
||||
label: string;
|
||||
fieldtype: FieldType;
|
||||
fieldname?: string;
|
||||
size?: string;
|
||||
render?: (doc: Doc) => { template: string };
|
||||
render?: (doc: RenderData) => { template: string };
|
||||
getValue?: (doc: Doc) => string;
|
||||
}
|
||||
|
||||
@ -88,3 +93,11 @@ export interface TreeViewSettings {
|
||||
parentField: string;
|
||||
getRootLabel: () => Promise<string>;
|
||||
}
|
||||
|
||||
export type DocStatus =
|
||||
| ''
|
||||
| 'Draft'
|
||||
| 'Saved'
|
||||
| 'NotSaved'
|
||||
| 'Submitted'
|
||||
| 'Cancelled';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Fyo } from 'fyo';
|
||||
import { Doc } from 'fyo/model/doc';
|
||||
import { Action } from 'fyo/model/types';
|
||||
import { Action, DocStatus } from 'fyo/model/types';
|
||||
import { Money } from 'pesa';
|
||||
import { Field, OptionField, SelectOption } from 'schemas/types';
|
||||
import { getIsNullOrUndef } from 'utils';
|
||||
|
@ -7,7 +7,12 @@ import {
|
||||
ListViewSettings,
|
||||
} from 'fyo/model/types';
|
||||
import { DateTime } from 'luxon';
|
||||
import { getLedgerLinkAction } from 'models/helpers';
|
||||
import {
|
||||
getDocStatus,
|
||||
getLedgerLinkAction,
|
||||
getStatusMap,
|
||||
statusColor,
|
||||
} from 'models/helpers';
|
||||
import { Transactional } from 'models/Transactional/Transactional';
|
||||
import { Money } from 'pesa';
|
||||
import { LedgerPosting } from '../../Transactional/LedgerPosting';
|
||||
@ -55,20 +60,12 @@ export class JournalEntry extends Transactional {
|
||||
fieldtype: 'Select',
|
||||
size: 'small',
|
||||
render(doc) {
|
||||
let status = 'Draft';
|
||||
let color = 'gray';
|
||||
if (doc.submitted) {
|
||||
color = 'green';
|
||||
status = 'Submitted';
|
||||
}
|
||||
|
||||
if (doc.cancelled) {
|
||||
color = 'red';
|
||||
status = 'Cancelled';
|
||||
}
|
||||
const status = getDocStatus(doc);
|
||||
const color = statusColor[status] ?? 'gray';
|
||||
const label = getStatusMap()[status];
|
||||
|
||||
return {
|
||||
template: `<Badge class="text-xs" color="${color}">${status}</Badge>`,
|
||||
template: `<Badge class="text-xs" color="${color}">${label}</Badge>`,
|
||||
};
|
||||
},
|
||||
},
|
||||
|
@ -13,7 +13,12 @@ import {
|
||||
ValidationMap,
|
||||
} from 'fyo/model/types';
|
||||
import { ValidationError } from 'fyo/utils/errors';
|
||||
import { getLedgerLinkAction } from 'models/helpers';
|
||||
import {
|
||||
getDocStatus,
|
||||
getLedgerLinkAction,
|
||||
getStatusMap,
|
||||
statusColor,
|
||||
} from 'models/helpers';
|
||||
import { LedgerPosting } from 'models/Transactional/LedgerPosting';
|
||||
import { Transactional } from 'models/Transactional/Transactional';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
@ -449,19 +454,12 @@ export class Payment extends Transactional {
|
||||
fieldtype: 'Select',
|
||||
size: 'small',
|
||||
render(doc) {
|
||||
let status = 'Draft';
|
||||
let color = 'gray';
|
||||
if (doc.submitted) {
|
||||
color = 'green';
|
||||
status = 'Submitted';
|
||||
}
|
||||
if (doc.cancelled) {
|
||||
color = 'red';
|
||||
status = 'Cancelled';
|
||||
}
|
||||
const status = getDocStatus(doc);
|
||||
const color = statusColor[status] ?? 'gray';
|
||||
const label = getStatusMap()[status];
|
||||
|
||||
return {
|
||||
template: `<Badge class="text-xs" color="${color}">${status}</Badge>`,
|
||||
template: `<Badge class="text-xs" color="${color}">${label}</Badge>`,
|
||||
};
|
||||
},
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Fyo, t } from 'fyo';
|
||||
import { Doc } from 'fyo/model/doc';
|
||||
import { Action, ColumnConfig } from 'fyo/model/types';
|
||||
import { Action, ColumnConfig, DocStatus, RenderData } from 'fyo/model/types';
|
||||
import { NotFoundError } from 'fyo/utils/errors';
|
||||
import { DateTime } from 'luxon';
|
||||
import { Money } from 'pesa';
|
||||
@ -76,21 +76,17 @@ export function getLedgerLinkAction(fyo: Fyo): Action {
|
||||
}
|
||||
|
||||
export function getTransactionStatusColumn(): ColumnConfig {
|
||||
const statusMap = {
|
||||
Unpaid: t`Unpaid`,
|
||||
Paid: t`Paid`,
|
||||
Draft: t`Draft`,
|
||||
Cancelled: t`Cancelled`,
|
||||
};
|
||||
const statusMap = getStatusMap();
|
||||
|
||||
return {
|
||||
label: t`Status`,
|
||||
fieldname: 'status',
|
||||
fieldtype: 'Select',
|
||||
render(doc: Doc) {
|
||||
const status = getInvoiceStatus(doc) as InvoiceStatus;
|
||||
render(doc) {
|
||||
const status = getDocStatus(doc) as InvoiceStatus;
|
||||
const color = statusColor[status];
|
||||
const label = statusMap[status];
|
||||
|
||||
return {
|
||||
template: `<Badge class="text-xs" color="${color}">${label}</Badge>`,
|
||||
};
|
||||
@ -98,27 +94,97 @@ export function getTransactionStatusColumn(): ColumnConfig {
|
||||
};
|
||||
}
|
||||
|
||||
export const statusColor = {
|
||||
export const statusColor: Record<
|
||||
DocStatus | InvoiceStatus,
|
||||
string | undefined
|
||||
> = {
|
||||
'': 'gray',
|
||||
Draft: 'gray',
|
||||
Unpaid: 'orange',
|
||||
Paid: 'green',
|
||||
Saved: 'gray',
|
||||
NotSaved: 'gray',
|
||||
Submitted: 'green',
|
||||
Cancelled: 'red',
|
||||
};
|
||||
|
||||
export function getInvoiceStatus(doc: Doc) {
|
||||
let status = 'Unpaid';
|
||||
if (!doc.submitted) {
|
||||
status = 'Draft';
|
||||
export function getStatusMap(): Record<DocStatus | InvoiceStatus, string> {
|
||||
return {
|
||||
'': '',
|
||||
Draft: t`Draft`,
|
||||
Unpaid: t`Unpaid`,
|
||||
Paid: t`Paid`,
|
||||
Saved: t`Saved`,
|
||||
NotSaved: t`Not Saved`,
|
||||
Submitted: t`Submitted`,
|
||||
Cancelled: t`Cancelled`,
|
||||
};
|
||||
}
|
||||
|
||||
export function getDocStatus(
|
||||
doc?: RenderData | Doc
|
||||
): DocStatus | InvoiceStatus {
|
||||
if (!doc) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (doc.submitted && (doc.outstandingAmount as Money).isZero()) {
|
||||
status = 'Paid';
|
||||
if (doc.notInserted) {
|
||||
return 'Draft';
|
||||
}
|
||||
|
||||
if (doc.dirty) {
|
||||
return 'NotSaved';
|
||||
}
|
||||
|
||||
if (!doc.schema?.isSubmittable) {
|
||||
return 'Saved';
|
||||
}
|
||||
|
||||
return getSubmittableDocStatus(doc);
|
||||
}
|
||||
|
||||
function getSubmittableDocStatus(doc: RenderData | Doc) {
|
||||
if (
|
||||
[ModelNameEnum.SalesInvoice, ModelNameEnum.PurchaseInvoice].includes(
|
||||
doc.schema.name as ModelNameEnum
|
||||
)
|
||||
) {
|
||||
return getInvoiceStatus(doc);
|
||||
}
|
||||
|
||||
if (!!doc.submitted && !doc.cancelled) {
|
||||
return 'Submitted';
|
||||
}
|
||||
|
||||
if (!!doc.submitted && !!doc.cancelled) {
|
||||
return 'Cancelled';
|
||||
}
|
||||
|
||||
return 'Saved';
|
||||
}
|
||||
|
||||
export function getInvoiceStatus(doc: RenderData | Doc): InvoiceStatus {
|
||||
if (
|
||||
doc.submitted &&
|
||||
!doc.cancelled &&
|
||||
(doc.outstandingAmount as Money).isZero()
|
||||
) {
|
||||
return 'Paid';
|
||||
}
|
||||
|
||||
if (
|
||||
doc.submitted &&
|
||||
!doc.cancelled &&
|
||||
(doc.outstandingAmount as Money).isPositive()
|
||||
) {
|
||||
return 'Unpaid';
|
||||
}
|
||||
|
||||
if (doc.cancelled) {
|
||||
status = 'Cancelled';
|
||||
return 'Cancelled';
|
||||
}
|
||||
return status;
|
||||
|
||||
return 'Saved';
|
||||
}
|
||||
|
||||
export async function getExchangeRate({
|
||||
|
@ -1,4 +1,4 @@
|
||||
export type InvoiceStatus = 'Draft' | 'Unpaid' | 'Cancelled' | 'Paid';
|
||||
export type InvoiceStatus = 'Draft' | 'Saved' | 'Unpaid' | 'Cancelled' | 'Paid';
|
||||
export enum ModelNameEnum {
|
||||
Account = 'Account',
|
||||
AccountingLedgerEntry = 'AccountingLedgerEntry',
|
||||
@ -29,4 +29,4 @@ export enum ModelNameEnum {
|
||||
SystemSettings = 'SystemSettings',
|
||||
}
|
||||
|
||||
export type ModelName = keyof typeof ModelNameEnum
|
||||
export type ModelName = keyof typeof ModelNameEnum;
|
||||
|
@ -4,8 +4,7 @@
|
||||
}}</Badge>
|
||||
</template>
|
||||
<script>
|
||||
import { t } from 'fyo';
|
||||
import { statusColor } from 'src/utils/colors';
|
||||
import { getStatusMap, statusColor } from 'models/helpers';
|
||||
import Badge from './Badge.vue';
|
||||
|
||||
export default {
|
||||
@ -16,14 +15,8 @@ export default {
|
||||
return statusColor[this.status];
|
||||
},
|
||||
statusLabel() {
|
||||
return (
|
||||
{
|
||||
Draft: t`Draft`,
|
||||
Unpaid: t`Unpaid`,
|
||||
Paid: t`Paid`,
|
||||
Cancelled: t`Cancelled`,
|
||||
}[this.status] ?? this.status
|
||||
);
|
||||
const statusMap = getStatusMap();
|
||||
return statusMap[this.status] ?? this.status;
|
||||
},
|
||||
},
|
||||
components: { Badge },
|
||||
|
@ -179,7 +179,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import { computed } from '@vue/reactivity';
|
||||
import { getInvoiceStatus } from 'models/helpers';
|
||||
import { getDocStatus } from 'models/helpers';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
import Button from 'src/components/Button.vue';
|
||||
import FormControl from 'src/components/Controls/FormControl.vue';
|
||||
@ -189,10 +189,10 @@ import FormContainer from 'src/components/FormContainer.vue';
|
||||
import StatusBadge from 'src/components/StatusBadge.vue';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import {
|
||||
getActionsForDocument,
|
||||
openSettings,
|
||||
routeTo,
|
||||
showMessageDialog
|
||||
getActionsForDocument,
|
||||
openSettings,
|
||||
routeTo,
|
||||
showMessageDialog,
|
||||
} from 'src/utils/ui';
|
||||
import { handleErrorWithDialog } from '../errorHandling';
|
||||
|
||||
@ -224,15 +224,15 @@ export default {
|
||||
};
|
||||
},
|
||||
updated() {
|
||||
this.chstatus = !this.chstatus
|
||||
this.chstatus = !this.chstatus;
|
||||
},
|
||||
computed: {
|
||||
address() {
|
||||
return this.printSettings && this.printSettings.getLink('address');
|
||||
},
|
||||
status() {
|
||||
this.chstatus
|
||||
return getInvoiceStatus(this.doc);
|
||||
this.chstatus;
|
||||
return getDocStatus(this.doc);
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
|
@ -24,7 +24,17 @@
|
||||
|
||||
<!-- Journal Entry Form -->
|
||||
<template #body v-if="doc">
|
||||
<div class="px-4 text-xl font-semibold flex justify-between h-row-large items-center">
|
||||
<div
|
||||
class="
|
||||
px-4
|
||||
text-xl
|
||||
font-semibold
|
||||
flex
|
||||
justify-between
|
||||
h-row-large
|
||||
items-center
|
||||
"
|
||||
>
|
||||
<h1>
|
||||
{{ doc.notInserted ? t`New Entry` : doc.name }}
|
||||
</h1>
|
||||
@ -130,6 +140,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import { computed } from '@vue/reactivity';
|
||||
import { getDocStatus } from 'models/helpers';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
import Button from 'src/components/Button.vue';
|
||||
import FormControl from 'src/components/Controls/FormControl.vue';
|
||||
@ -187,11 +198,7 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
status() {
|
||||
if (this.doc.notInserted || !this.doc.submitted) {
|
||||
return 'Draft';
|
||||
}
|
||||
|
||||
return '';
|
||||
return getDocStatus(this.doc);
|
||||
},
|
||||
totalDebit() {
|
||||
let value = 0;
|
||||
|
@ -189,11 +189,13 @@ export default defineComponent({
|
||||
? 'date'
|
||||
: 'created';
|
||||
|
||||
this.data = await fyo.db.getAll(this.schemaName, {
|
||||
fields: ['*'],
|
||||
filters,
|
||||
orderBy,
|
||||
});
|
||||
this.data = (
|
||||
await fyo.db.getAll(this.schemaName, {
|
||||
fields: ['*'],
|
||||
filters,
|
||||
orderBy,
|
||||
})
|
||||
).map((d) => ({ ...d, schema: fyo.schemaMap[this.schemaName] }));
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -16,15 +16,15 @@
|
||||
</div>
|
||||
|
||||
<!-- Actions, Badge and Status Change Buttons -->
|
||||
<div class="flex items-stretch">
|
||||
<DropdownWithActions :actions="actions" />
|
||||
<div class="flex items-stretch gap-2">
|
||||
<StatusBadge :status="status" />
|
||||
<DropdownWithActions :actions="actions" />
|
||||
<Button
|
||||
:icon="true"
|
||||
@click="sync"
|
||||
type="primary"
|
||||
v-if="doc?.dirty || doc?.notInserted"
|
||||
class="ml-2 text-white text-xs"
|
||||
class="text-white text-xs"
|
||||
>
|
||||
{{ t`Save` }}
|
||||
</Button>
|
||||
@ -38,7 +38,7 @@
|
||||
!doc?.notInserted &&
|
||||
!(doc?.cancelled || false)
|
||||
"
|
||||
class="ml-2 text-white text-xs"
|
||||
class="text-white text-xs"
|
||||
>
|
||||
{{ t`Submit` }}
|
||||
</Button>
|
||||
@ -89,6 +89,7 @@
|
||||
<script>
|
||||
import { computed } from '@vue/reactivity';
|
||||
import { t } from 'fyo';
|
||||
import { getDocStatus } from 'models/helpers';
|
||||
import Button from 'src/components/Button.vue';
|
||||
import FormControl from 'src/components/Controls/FormControl.vue';
|
||||
import DropdownWithActions from 'src/components/DropdownWithActions.vue';
|
||||
@ -148,11 +149,7 @@ export default {
|
||||
return fyo.schemaMap[this.schemaName] ?? null;
|
||||
},
|
||||
status() {
|
||||
if (this.doc && this.doc.notInserted) {
|
||||
return 'Draft';
|
||||
}
|
||||
|
||||
return '';
|
||||
return getDocStatus(this.doc);
|
||||
},
|
||||
fields() {
|
||||
if (!this.schema) {
|
||||
|
@ -75,7 +75,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
if (filterKeys.length) {
|
||||
await this.report.postSet();
|
||||
await this.report.updateData();
|
||||
}
|
||||
|
||||
if (fyo.store.isDevelopment) {
|
||||
|
@ -14,12 +14,6 @@ export const indicators = {
|
||||
BLACK: 'black',
|
||||
};
|
||||
|
||||
export const statusColor = {
|
||||
Draft: 'gray',
|
||||
Unpaid: 'orange',
|
||||
Paid: 'green',
|
||||
Cancelled: 'red',
|
||||
};
|
||||
|
||||
const getValidColor = (color: string) => {
|
||||
const isValid = [
|
||||
|
Loading…
x
Reference in New Issue
Block a user