2
0
mirror of https://github.com/frappe/books.git synced 2025-01-03 07:12:21 +00:00

incr: add ledger links

- fix sidebar issue
- show grand total
This commit is contained in:
18alantom 2022-11-21 12:05:05 +05:30
parent 9a510f1a63
commit 5d732844fb
7 changed files with 106 additions and 33 deletions

View File

@ -7,11 +7,11 @@ import { safeParseFloat } from 'utils/index';
import { Router } from 'vue-router'; import { Router } from 'vue-router';
import { import {
AccountRootType, AccountRootType,
AccountRootTypeEnum AccountRootTypeEnum,
} from './baseModels/Account/types'; } from './baseModels/Account/types';
import { import {
Defaults, Defaults,
numberSeriesDefaultsMap numberSeriesDefaultsMap,
} from './baseModels/Defaults/Defaults'; } from './baseModels/Defaults/Defaults';
import { InvoiceStatus, ModelNameEnum } from './types'; import { InvoiceStatus, ModelNameEnum } from './types';
@ -60,15 +60,27 @@ export function getInvoiceActions(
]; ];
} }
export function getLedgerLinkAction(fyo: Fyo): Action { export function getLedgerLinkAction(
fyo: Fyo,
isStock: boolean = false
): Action {
let label = fyo.t`Ledger Entries`;
let reportClassName = 'GeneralLedger';
if (isStock) {
label = fyo.t`Stock Entries`;
reportClassName = 'StockLedger';
}
return { return {
label: fyo.t`Ledger Entries`, label,
condition: (doc: Doc) => doc.isSubmitted, condition: (doc: Doc) => doc.isSubmitted,
action: async (doc: Doc, router: Router) => { action: async (doc: Doc, router: Router) => {
router.push({ router.push({
name: 'Report', name: 'Report',
params: { params: {
reportClassName: 'GeneralLedger', reportClassName,
defaultFilters: JSON.stringify({ defaultFilters: JSON.stringify({
referenceType: doc.schemaName, referenceType: doc.schemaName,
referenceName: doc.name, referenceName: doc.name,

View File

@ -1,10 +1,12 @@
import { Fyo } from 'fyo';
import { import {
Action,
DefaultMap, DefaultMap,
FiltersMap, FiltersMap,
FormulaMap, FormulaMap,
ListViewSettings, ListViewSettings
} from 'fyo/model/types'; } from 'fyo/model/types';
import { getDocStatusListColumn } from 'models/helpers'; import { getDocStatusListColumn, getLedgerLinkAction } from 'models/helpers';
import { LedgerPosting } from 'models/Transactional/LedgerPosting'; import { LedgerPosting } from 'models/Transactional/LedgerPosting';
import { ModelNameEnum } from 'models/types'; import { ModelNameEnum } from 'models/types';
import { Money } from 'pesa'; import { Money } from 'pesa';
@ -63,4 +65,8 @@ export class StockMovement extends Transfer {
toLocation: row.toLocation, toLocation: row.toLocation,
})); }));
} }
static getActions(fyo: Fyo): Action[] {
return [getLedgerLinkAction(fyo, true)];
}
} }

View File

@ -1,10 +1,10 @@
import { t } from 'fyo'; import { Fyo, t } from 'fyo';
import { Attachment } from 'fyo/core/types'; import { Attachment } from 'fyo/core/types';
import { Doc } from 'fyo/model/doc'; import { Doc } from 'fyo/model/doc';
import { DefaultMap, FiltersMap, FormulaMap } from 'fyo/model/types'; import { Action, DefaultMap, FiltersMap, FormulaMap } from 'fyo/model/types';
import { NotFoundError, ValidationError } from 'fyo/utils/errors'; import { ValidationError } from 'fyo/utils/errors';
import { Defaults } from 'models/baseModels/Defaults/Defaults'; import { Defaults } from 'models/baseModels/Defaults/Defaults';
import { getNumberSeries } from 'models/helpers'; import { getLedgerLinkAction, getNumberSeries } from 'models/helpers';
import { LedgerPosting } from 'models/Transactional/LedgerPosting'; import { LedgerPosting } from 'models/Transactional/LedgerPosting';
import { ModelNameEnum } from 'models/types'; import { ModelNameEnum } from 'models/types';
import { Money } from 'pesa'; import { Money } from 'pesa';
@ -100,7 +100,7 @@ export abstract class StockTransfer extends Transfer {
await posting.credit(stockReceivedButNotBilled, amount); await posting.credit(stockReceivedButNotBilled, amount);
} }
await posting.makeRoundOffEntry() await posting.makeRoundOffEntry();
return posting; return posting;
} }
@ -133,4 +133,8 @@ export abstract class StockTransfer extends Transfer {
throw new ValidationError(messages.join(' ')); throw new ValidationError(messages.join(' '));
} }
} }
static getActions(fyo: Fyo): Action[] {
return [getLedgerLinkAction(fyo, false), getLedgerLinkAction(fyo, true)];
}
} }

View File

@ -17,6 +17,8 @@ type ReferenceType =
| ModelNameEnum.PurchaseInvoice | ModelNameEnum.PurchaseInvoice
| ModelNameEnum.Payment | ModelNameEnum.Payment
| ModelNameEnum.JournalEntry | ModelNameEnum.JournalEntry
| ModelNameEnum.Shipment
| ModelNameEnum.PurchaseReceipt
| 'All'; | 'All';
export class GeneralLedger extends LedgerReport { export class GeneralLedger extends LedgerReport {
@ -272,17 +274,25 @@ export class GeneralLedger extends LedgerReport {
} }
getFilters() { getFilters() {
const refTypeOptions = [
{ label: t`All`, value: 'All' },
{ label: t`Sales Invoices`, value: 'SalesInvoice' },
{ label: t`Purchase Invoices`, value: 'PurchaseInvoice' },
{ label: t`Payments`, value: 'Payment' },
{ label: t`Journal Entries`, value: 'JournalEntry' },
];
if (this.fyo.store.appFlags.isInventoryEnabled) {
refTypeOptions.push(
{ label: t`Shipment`, value: 'Shipment' },
{ label: t`Purchase Receipt`, value: 'PurchaseReceipt' }
);
}
return [ return [
{ {
fieldtype: 'Select', fieldtype: 'Select',
options: [ options: refTypeOptions,
{ label: t`All`, value: 'All' },
{ label: t`Sales Invoices`, value: 'SalesInvoice' },
{ label: t`Purchase Invoices`, value: 'PurchaseInvoice' },
{ label: t`Payments`, value: 'Payment' },
{ label: t`Journal Entries`, value: 'JournalEntry' },
],
label: t`Ref Type`, label: t`Ref Type`,
fieldname: 'referenceType', fieldname: 'referenceType',
placeholder: t`Ref Type`, placeholder: t`Ref Type`,

View File

@ -11,6 +11,12 @@ import { isNumeric } from 'src/utils';
import { getRawStockLedgerEntries, getStockLedgerEntries } from './helpers'; import { getRawStockLedgerEntries, getStockLedgerEntries } from './helpers';
import { ComputedStockLedgerEntry } from './types'; import { ComputedStockLedgerEntry } from './types';
type ReferenceType =
| ModelNameEnum.StockMovement
| ModelNameEnum.Shipment
| ModelNameEnum.PurchaseReceipt
| 'All';
export class StockLedger extends Report { export class StockLedger extends Report {
static title = t`Stock Ledger`; static title = t`Stock Ledger`;
static reportName = 'stock-ledger'; static reportName = 'stock-ledger';
@ -25,6 +31,9 @@ export class StockLedger extends Report {
fromDate?: string; fromDate?: string;
toDate?: string; toDate?: string;
ascending?: boolean; ascending?: boolean;
referenceType?: ReferenceType = 'All';
referenceName?: string;
groupBy: 'none' | 'item' | 'location' = 'none'; groupBy: 'none' | 'item' | 'location' = 'none';
constructor(fyo: Fyo) { constructor(fyo: Fyo) {
@ -101,6 +110,17 @@ export class StockLedger extends Report {
continue; continue;
} }
if (
this.referenceType !== 'All' &&
row.referenceType !== this.referenceType
) {
continue;
}
if (this.referenceName && row.referenceName !== this.referenceName) {
continue;
}
row.name = ++i; row.name = ++i;
filteredRawData.push(row); filteredRawData.push(row);
} }
@ -265,14 +285,14 @@ export class StockLedger extends Report {
getFilters(): Field[] { getFilters(): Field[] {
return [ return [
/*
{ {
fieldtype: 'Select', fieldtype: 'Select',
options: [ options: [
{ label: t`All`, value: 'All' }, { label: t`All`, value: 'All' },
{ label: t`Stock Movements`, value: 'StockMovement' }, { label: t`Stock Movements`, value: 'StockMovement' },
{ label: t`Shipment`, value: 'Shipment' },
{ label: t`Purchase Receipt`, value: 'PurchaseReceipt' },
], ],
label: t`Ref Type`, label: t`Ref Type`,
fieldname: 'referenceType', fieldname: 'referenceType',
placeholder: t`Ref Type`, placeholder: t`Ref Type`,
@ -285,7 +305,6 @@ export class StockLedger extends Report {
emptyMessage: t`Change Ref Type`, emptyMessage: t`Change Ref Type`,
fieldname: 'referenceName', fieldname: 'referenceName',
}, },
*/
{ {
fieldtype: 'Link', fieldtype: 'Link',
target: 'Item', target: 'Item',

View File

@ -208,11 +208,18 @@ export default {
} }
}, },
isItemActive(item) { isItemActive(item) {
let { path: currentRoute, params } = this.$route; const { path: currentRoute, params } = this.$route;
let routeMatch = currentRoute === item.route; const routeMatch = currentRoute === item.route;
let schemaNameMatch =
const schemaNameMatch =
item.schemaName && params.schemaName === item.schemaName; item.schemaName && params.schemaName === item.schemaName;
return routeMatch || schemaNameMatch;
const isMatch = routeMatch || schemaNameMatch;
if (params.name && item.schemaName && !isMatch) {
return currentRoute.includes(`${item.schemaName}/${params.name}`);
}
return isMatch;
}, },
isGroupActive(group) { isGroupActive(group) {
return this.activeGroup && group.label === this.activeGroup.label; return this.activeGroup && group.label === this.activeGroup.label;

View File

@ -28,7 +28,7 @@
<hr /> <hr />
<div> <div>
<!-- Invoice Form Data Entry --> <!-- Form Data Entry -->
<div class="m-4 grid grid-cols-3 gap-4"> <div class="m-4 grid grid-cols-3 gap-4">
<FormControl <FormControl
input-class="font-semibold" input-class="font-semibold"
@ -66,7 +66,7 @@
</div> </div>
<hr /> <hr />
<!-- Invoice Items Table --> <!-- Items Table -->
<Table <Table
class="text-base" class="text-base"
:df="getField('items')" :df="getField('items')"
@ -79,8 +79,7 @@
/> />
</div> </div>
<!-- Invoice Form Footer --> <!-- Form Footer -->
<div v-if="doc.items?.length ?? 0" class="mt-auto"> <div v-if="doc.items?.length ?? 0" class="mt-auto">
<hr /> <hr />
<div class="flex justify-between text-base m-4 gap-12"> <div class="flex justify-between text-base m-4 gap-12">
@ -96,6 +95,21 @@
:read-only="doc?.submitted" :read-only="doc?.submitted"
/> />
</div> </div>
<div class="w-1/2" v-if="doc.grandTotal">
<!-- Grand Total -->
<div
class="
flex
justify-between
text-green-600
font-semibold
text-base
"
>
<div>{{ t`Grand Total` }}</div>
<div>{{ formattedValue('grandTotal') }}</div>
</div>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -119,6 +133,7 @@
</template> </template>
<script> <script>
import { computed } from '@vue/reactivity'; import { computed } from '@vue/reactivity';
import { t } from 'fyo';
import { getDocStatus } from 'models/helpers'; import { getDocStatus } from 'models/helpers';
import Button from 'src/components/Button.vue'; import Button from 'src/components/Button.vue';
import FormControl from 'src/components/Controls/FormControl.vue'; import FormControl from 'src/components/Controls/FormControl.vue';
@ -235,7 +250,7 @@ export default {
message, message,
buttons: [ buttons: [
{ {
label: this.t`Yes`, label: t`Yes`,
async action() { async action() {
try { try {
await ref.doc.submit(); await ref.doc.submit();
@ -245,7 +260,7 @@ export default {
}, },
}, },
{ {
label: this.t`No`, label: t`No`,
action() {}, action() {},
}, },
], ],