mirror of
https://github.com/frappe/books.git
synced 2026-08-24 10:04:45 -05:00
fix: formatted code
This commit is contained in:
@@ -3,6 +3,7 @@ import { DocValue, DocValueMap } from 'fyo/core/types';
|
||||
import { Doc } from 'fyo/model/doc';
|
||||
import {
|
||||
CurrenciesMap,
|
||||
ChangeArg,
|
||||
FiltersMap,
|
||||
FormulaMap,
|
||||
HiddenMap,
|
||||
@@ -114,6 +115,27 @@ export abstract class InvoiceItem extends Doc {
|
||||
this._setGetCurrencies();
|
||||
}
|
||||
|
||||
override async change(ch: ChangeArg): Promise<void> {
|
||||
await super.change(ch);
|
||||
|
||||
if (ch.changed === 'item') {
|
||||
if (!this.isSales && this.item) {
|
||||
const hasBatch = await this.fyo.getValue(
|
||||
ModelNameEnum.Item,
|
||||
this.item,
|
||||
'hasBatch'
|
||||
);
|
||||
|
||||
if (hasBatch) {
|
||||
const batchName = await getSuggestedBatchName(this.fyo, this.item);
|
||||
if (batchName) {
|
||||
await this.set('batch', batchName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async getTotalTaxRate(): Promise<number> {
|
||||
if (!this.tax) {
|
||||
return 0;
|
||||
@@ -674,58 +696,51 @@ export abstract class InvoiceItem extends Doc {
|
||||
batchName: string,
|
||||
requiredQuantity: number
|
||||
): Promise<void> {
|
||||
try {
|
||||
let inventoryLocation: string | undefined;
|
||||
let inventoryLocation: string | undefined;
|
||||
|
||||
if (this.location) {
|
||||
inventoryLocation = this.location as string;
|
||||
if (this.location) {
|
||||
inventoryLocation = this.location as string;
|
||||
} else {
|
||||
const posProfileName = this.fyo.singles.POSSettings?.posProfile;
|
||||
|
||||
if (posProfileName) {
|
||||
const inventory = await this.fyo.getValue(
|
||||
ModelNameEnum.POSProfile,
|
||||
posProfileName as string,
|
||||
'inventory'
|
||||
);
|
||||
|
||||
inventoryLocation = inventory as string | undefined;
|
||||
} else {
|
||||
const posProfileName = this.fyo.singles.POSSettings?.posProfile;
|
||||
if (posProfileName) {
|
||||
const posProfile = await this.fyo.doc.getDoc(
|
||||
ModelNameEnum.POSProfile,
|
||||
posProfileName as string
|
||||
);
|
||||
inventoryLocation = posProfile?.inventory as string | undefined;
|
||||
} else {
|
||||
inventoryLocation = this.fyo.singles.POSSettings?.inventory;
|
||||
}
|
||||
inventoryLocation = this.fyo.singles.POSSettings?.inventory;
|
||||
}
|
||||
}
|
||||
|
||||
const valuationMethod =
|
||||
(this.fyo.singles.InventorySettings
|
||||
?.valuationMethod as ValuationMethod) ?? ValuationMethod.FIFO;
|
||||
const valuationMethod =
|
||||
(this.fyo.singles.InventorySettings
|
||||
?.valuationMethod as ValuationMethod) ?? ValuationMethod.FIFO;
|
||||
|
||||
const rawSLEs = await getRawStockLedgerEntries(this.fyo);
|
||||
const computedSLEs = getStockLedgerEntries(rawSLEs, valuationMethod);
|
||||
const rawSLEs = await getRawStockLedgerEntries(this.fyo);
|
||||
const computedSLEs = getStockLedgerEntries(rawSLEs, valuationMethod);
|
||||
|
||||
const stockBalance = getStockBalanceEntries(computedSLEs, {
|
||||
item: this.item!,
|
||||
location: inventoryLocation,
|
||||
batch: batchName,
|
||||
});
|
||||
const stockBalance = getStockBalanceEntries(computedSLEs, {
|
||||
item: this.item!,
|
||||
location: inventoryLocation,
|
||||
batch: batchName,
|
||||
});
|
||||
|
||||
const availableQuantity = stockBalance.reduce(
|
||||
(sum, entry) => sum + (entry.balanceQuantity || 0),
|
||||
0
|
||||
const availableQuantity = stockBalance.reduce(
|
||||
(sum, entry) => sum + (entry.balanceQuantity || 0),
|
||||
0
|
||||
);
|
||||
|
||||
if (requiredQuantity > availableQuantity) {
|
||||
throw new ValidationError(
|
||||
this.fyo.t`
|
||||
Batch ${batchName} only has ${availableQuantity} quantity available
|
||||
but ${requiredQuantity} is required
|
||||
`
|
||||
);
|
||||
|
||||
if (requiredQuantity > availableQuantity) {
|
||||
// ✅ dynamic import just like your example
|
||||
const { showToast } = await import('src/utils/interactive');
|
||||
|
||||
showToast({
|
||||
type: 'warning',
|
||||
message: this.fyo.t`
|
||||
Batch ${batchName} only has ${availableQuantity} quantity available
|
||||
but ${requiredQuantity} is required
|
||||
`,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof ValidationError) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -769,28 +784,26 @@ export abstract class InvoiceItem extends Doc {
|
||||
return { for: ['not in', [itemNotFor]] };
|
||||
},
|
||||
batch: async (doc: Doc) => {
|
||||
const hasBatch = await doc.fyo.getValue(
|
||||
const hasBatch = !!(await doc.fyo.getValue(
|
||||
ModelNameEnum.Item,
|
||||
doc.item as string,
|
||||
'hasBatch'
|
||||
);
|
||||
));
|
||||
|
||||
if (!hasBatch) {
|
||||
return { name: ['in', []] };
|
||||
}
|
||||
|
||||
let suggestedBatch: string | undefined;
|
||||
|
||||
if (!doc.isSales) {
|
||||
const batchName = await getSuggestedBatchName(
|
||||
suggestedBatch = await getSuggestedBatchName(
|
||||
doc.fyo,
|
||||
doc.item as string
|
||||
);
|
||||
|
||||
if (batchName) {
|
||||
await doc.set('batch', batchName);
|
||||
|
||||
return {
|
||||
name: ['in', [batchName]],
|
||||
};
|
||||
if (suggestedBatch) {
|
||||
await doc.set('batch', suggestedBatch);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -829,31 +842,32 @@ export abstract class InvoiceItem extends Doc {
|
||||
.filter((entry) => entry.batch && entry.balanceQuantity > 0)
|
||||
.map((entry) => entry.batch);
|
||||
|
||||
if (batchesWithStock.length === 0) {
|
||||
const allBatchesWithStock = stockBalance
|
||||
.filter((entry) => entry.batch && entry.balanceQuantity > 0)
|
||||
.map((entry) => entry.batch);
|
||||
|
||||
if (allBatchesWithStock.length > 0) {
|
||||
return {
|
||||
name: ['in', allBatchesWithStock],
|
||||
};
|
||||
}
|
||||
const allBatches = new Set<string>(batchesWithStock);
|
||||
if (suggestedBatch) {
|
||||
allBatches.add(suggestedBatch);
|
||||
}
|
||||
|
||||
const finalBatchList = Array.from(allBatches);
|
||||
|
||||
return {
|
||||
name: ['in', batchesWithStock],
|
||||
name: ['in', finalBatchList],
|
||||
};
|
||||
} catch (error) {
|
||||
// Fallback to all batches for the item
|
||||
const batches = await doc.fyo.db.getAll(ModelNameEnum.Batch, {
|
||||
fields: ['name'],
|
||||
filters: { item: doc.item as string },
|
||||
});
|
||||
const batchName = batches.map((b) => b.name) as string[];
|
||||
const batchNames = batches.map((b) => b.name) as string[];
|
||||
|
||||
const allBatches = new Set<string>(batchNames);
|
||||
if (suggestedBatch) {
|
||||
allBatches.add(suggestedBatch);
|
||||
}
|
||||
|
||||
const finalBatchList = Array.from(allBatches);
|
||||
|
||||
return {
|
||||
name: ['in', batchName],
|
||||
name: ['in', finalBatchList],
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14,10 +14,6 @@ import { ValidationError } from 'fyo/utils/errors';
|
||||
import { Money } from 'pesa';
|
||||
import { AccountRootTypeEnum, AccountTypeEnum } from '../Account/types';
|
||||
|
||||
function getPaddedName(prefix: string, next: number, padZeros: number): string {
|
||||
return prefix + next.toString().padStart(padZeros ?? 4, '0');
|
||||
}
|
||||
|
||||
interface UOMConversionItem {
|
||||
name: string;
|
||||
uom: string;
|
||||
@@ -163,7 +159,7 @@ export class Item extends Doc {
|
||||
);
|
||||
const start = (batchSeriesDoc?.start as number) ?? 1001;
|
||||
const padZeros = (batchSeriesDoc?.padZeros as number) ?? 4;
|
||||
const batchName = getPaddedName(seriesName, start, padZeros);
|
||||
const batchName = start.toString().padStart(padZeros, '0');
|
||||
|
||||
const batchExists = await this.fyo.db.exists('Batch', batchName);
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ import { StockMovementItem } from './StockMovementItem';
|
||||
import { Transfer } from './Transfer';
|
||||
import {
|
||||
canValidateSerialNumber,
|
||||
createBatch,
|
||||
generateBatchForItem,
|
||||
getSerialNumberFromDoc,
|
||||
updateSerialNumbers,
|
||||
validateBatch,
|
||||
@@ -65,6 +67,42 @@ export class StockMovement extends Transfer {
|
||||
await updateSerialNumbers(this, false);
|
||||
}
|
||||
|
||||
async beforeSubmit(): Promise<void> {
|
||||
await super.beforeSubmit();
|
||||
|
||||
const batchesToCreate: { item: string; batch: string }[] = [];
|
||||
|
||||
for (const item of this.items ?? []) {
|
||||
if (!item.item || !item.batch) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const hasBatch = await this.fyo.getValue(
|
||||
ModelNameEnum.Item,
|
||||
item.item,
|
||||
'hasBatch'
|
||||
);
|
||||
|
||||
if (hasBatch) {
|
||||
const batchExists = await this.fyo.db.exists(
|
||||
ModelNameEnum.Batch,
|
||||
item.batch
|
||||
);
|
||||
|
||||
if (!batchExists) {
|
||||
batchesToCreate.push({
|
||||
item: item.item,
|
||||
batch: item.batch,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const { item, batch } of batchesToCreate) {
|
||||
await createBatch(this.fyo, item, batch);
|
||||
}
|
||||
}
|
||||
|
||||
async afterCancel(): Promise<void> {
|
||||
await super.afterCancel();
|
||||
await updateSerialNumbers(this, true);
|
||||
@@ -125,10 +163,10 @@ export class StockMovement extends Transfer {
|
||||
item: row.item!,
|
||||
rate: row.rate!,
|
||||
quantity: row.quantity!,
|
||||
batch: row.batch!,
|
||||
serialNumber: row.serialNumber!,
|
||||
fromLocation: row.fromLocation,
|
||||
toLocation: row.toLocation,
|
||||
batch: row.batch ?? undefined,
|
||||
serialNumber: row.serialNumber ?? undefined,
|
||||
fromLocation: row.fromLocation ?? undefined,
|
||||
toLocation: row.toLocation ?? undefined,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -142,19 +180,30 @@ export class StockMovement extends Transfer {
|
||||
throw new ValidationError(t`Item ${name} not found`);
|
||||
}
|
||||
|
||||
let batch: string | null | undefined =
|
||||
(itemDoc.defaultBatch as string | null | undefined) ?? null;
|
||||
|
||||
if (
|
||||
this.movementType === MovementTypeEnum.MaterialReceipt &&
|
||||
itemDoc.hasBatch &&
|
||||
!batch
|
||||
) {
|
||||
batch = await generateBatchForItem(this.fyo, name);
|
||||
}
|
||||
|
||||
const item = {
|
||||
name: itemDoc.name,
|
||||
batch: itemDoc.defaultBatch ?? null,
|
||||
batch,
|
||||
};
|
||||
|
||||
if (item.batch) {
|
||||
const batchDoc = await this.fyo.doc.getDoc(
|
||||
ModelNameEnum.Batch,
|
||||
item.batch as string
|
||||
item.batch
|
||||
);
|
||||
if (batchDoc && batchDoc.item !== name) {
|
||||
throw new ValidationError(
|
||||
t`Batch ${item.batch as string} does not belong to Item ${name}`
|
||||
t`Batch ${item.batch} does not belong to Item ${name}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import { ValidationError } from 'fyo/utils/errors';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
import { Money } from 'pesa';
|
||||
import { safeParseFloat } from 'utils/index';
|
||||
import { generateSerialNumbersForItem } from './helpers';
|
||||
import { generateSerialNumbersForItem, getSuggestedBatchName } from './helpers';
|
||||
import { StockMovement } from './StockMovement';
|
||||
import { TransferItem } from './TransferItem';
|
||||
import { MovementTypeEnum } from './types';
|
||||
@@ -80,14 +80,43 @@ export class StockMovementItem extends TransferItem {
|
||||
};
|
||||
},
|
||||
batch: async (doc: Doc) => {
|
||||
let suggestedBatch: string | undefined;
|
||||
let hasBatch = false;
|
||||
|
||||
if (doc.parentdoc?.movementType === MovementTypeEnum.MaterialReceipt) {
|
||||
hasBatch = !!(await doc.fyo.getValue(
|
||||
ModelNameEnum.Item,
|
||||
doc.item as string,
|
||||
'hasBatch'
|
||||
));
|
||||
|
||||
if (hasBatch) {
|
||||
suggestedBatch = await getSuggestedBatchName(
|
||||
doc.fyo,
|
||||
doc.item as string
|
||||
);
|
||||
|
||||
if (suggestedBatch) {
|
||||
await doc.set('batch', suggestedBatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const batches = await doc.fyo.db.getAll(ModelNameEnum.Batch, {
|
||||
fields: ['name'],
|
||||
filters: { item: doc.item as string },
|
||||
});
|
||||
const batchName = batches.map((b) => b.name) as string[];
|
||||
const existingBatchNames = batches.map((b) => b.name) as string[];
|
||||
|
||||
const allBatches = new Set<string>(existingBatchNames);
|
||||
if (suggestedBatch) {
|
||||
allBatches.add(suggestedBatch);
|
||||
}
|
||||
|
||||
const finalBatchList = Array.from(allBatches);
|
||||
|
||||
return {
|
||||
name: ['in', batchName],
|
||||
name: ['in', finalBatchList],
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -338,6 +367,24 @@ export class StockMovementItem extends TransferItem {
|
||||
if (ch.changed === 'item') {
|
||||
await this.set('serialNumber', '');
|
||||
|
||||
if (
|
||||
this.parentdoc?.movementType === MovementTypeEnum.MaterialReceipt &&
|
||||
this.item
|
||||
) {
|
||||
const hasBatch = await this.fyo.getValue(
|
||||
ModelNameEnum.Item,
|
||||
this.item,
|
||||
'hasBatch'
|
||||
);
|
||||
|
||||
if (hasBatch) {
|
||||
const batchName = await getSuggestedBatchName(this.fyo, this.item);
|
||||
if (batchName) {
|
||||
await this.set('batch', batchName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldGenerateSerialNumbers) {
|
||||
await this.generateAndSetSerialNumbers();
|
||||
}
|
||||
|
||||
+16
-17
@@ -23,7 +23,9 @@ export async function validateBatch(
|
||||
|
||||
if (
|
||||
doc.schemaName === ModelNameEnum.PurchaseInvoice ||
|
||||
doc.schemaName === ModelNameEnum.PurchaseReceipt
|
||||
doc.schemaName === ModelNameEnum.PurchaseReceipt ||
|
||||
doc.schemaName === ModelNameEnum.StockMovement ||
|
||||
doc.schemaName === ModelNameEnum.Shipment
|
||||
) {
|
||||
for (const row of doc.items ?? []) {
|
||||
if (row.item && row.batch) {
|
||||
@@ -576,6 +578,7 @@ export async function getSuggestedBatchName(
|
||||
}
|
||||
|
||||
const seriesName = (batchSeries as string).trim();
|
||||
|
||||
const seriesExists = await fyo.db.exists('BatchSeries', seriesName);
|
||||
|
||||
if (!seriesExists) {
|
||||
@@ -596,7 +599,6 @@ export async function getSuggestedBatchName(
|
||||
|
||||
const padZeros = (batchSeriesDoc.padZeros as number) ?? 4;
|
||||
|
||||
const prefix = seriesName.endsWith('-') ? seriesName : seriesName + '-';
|
||||
const existingBatches = (await fyo.db.getAllRaw(ModelNameEnum.Batch, {
|
||||
fields: ['name'],
|
||||
filters: { item: itemName },
|
||||
@@ -609,13 +611,12 @@ export async function getSuggestedBatchName(
|
||||
|
||||
for (const batch of existingBatches) {
|
||||
const batchName = batch.name;
|
||||
if (batchName.startsWith(prefix)) {
|
||||
const numericPart = batchName.substring(prefix.length);
|
||||
const num = parseInt(numericPart, 10);
|
||||
// Extract numeric part from batch name (handles names like "com-1001")
|
||||
const numericPart = batchName.replace(seriesName, '');
|
||||
const num = parseInt(numericPart, 10);
|
||||
|
||||
if (!isNaN(num) && num > highestNumber) {
|
||||
highestNumber = num;
|
||||
}
|
||||
if (!isNaN(num) && num > highestNumber) {
|
||||
highestNumber = num;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -628,7 +629,9 @@ export async function getSuggestedBatchName(
|
||||
nextNumber = (batchSeriesDoc.start as number) ?? 1001;
|
||||
}
|
||||
|
||||
const batchName = prefix + nextNumber.toString().padStart(padZeros, '0');
|
||||
const batchName = `${seriesName}${nextNumber
|
||||
.toString()
|
||||
.padStart(padZeros, '0')}`;
|
||||
|
||||
return batchName;
|
||||
} catch (error) {
|
||||
@@ -667,14 +670,10 @@ export async function createBatch(
|
||||
seriesName
|
||||
)) as BatchSeries;
|
||||
|
||||
const prefix = seriesName.endsWith('-') ? seriesName : seriesName + '-';
|
||||
if (batchName.startsWith(prefix)) {
|
||||
const numericPart = batchName.substring(prefix.length);
|
||||
const num = parseInt(numericPart, 10);
|
||||
if (!isNaN(num)) {
|
||||
await batchSeriesDoc.set('current', num);
|
||||
await batchSeriesDoc.sync();
|
||||
}
|
||||
const num = parseInt(batchName, 10);
|
||||
if (!isNaN(num)) {
|
||||
await batchSeriesDoc.set('current', num);
|
||||
await batchSeriesDoc.sync();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
<feather-icon
|
||||
:name="isExapanded ? 'chevron-up' : 'chevron-down'"
|
||||
class="w-4 h-4 inline-flex cursor-pointer text-gray-700 dark:text-gray-200"
|
||||
@click="isExapanded = !isExapanded"
|
||||
@click="toggleExpand"
|
||||
/>
|
||||
|
||||
<div class="relative" @click="emitSelectedRow">
|
||||
<div class="relative" @click="toggleExpandAndEmit">
|
||||
<Link
|
||||
class="pt-2"
|
||||
:df="{
|
||||
@@ -27,7 +27,7 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center" @click="emitSelectedRow">
|
||||
<div class="flex items-center" @click="toggleExpandAndEmit">
|
||||
<Int
|
||||
:df="{
|
||||
fieldname: 'quantity',
|
||||
@@ -115,7 +115,7 @@
|
||||
<div></div>
|
||||
|
||||
<template v-if="isExapanded">
|
||||
<div class="px-4 pt-6 col-span-1" @click="emitSelectedRow">
|
||||
<div class="px-4 pt-6 col-span-1" @click="toggleExpandAndEmit">
|
||||
<Int
|
||||
v-if="isUOMConversionEnabled"
|
||||
:df="{
|
||||
@@ -286,7 +286,7 @@ import Link from 'src/components/Controls/Link.vue';
|
||||
import Text from 'src/components/Controls/Text.vue';
|
||||
import { inject } from 'vue';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import { defineComponent } from 'vue';
|
||||
import { defineComponent, PropType } from 'vue';
|
||||
import { SalesInvoiceItem } from 'models/baseModels/SalesInvoiceItem/SalesInvoiceItem';
|
||||
import { Money } from 'pesa';
|
||||
import { DiscountType } from '../types';
|
||||
@@ -305,8 +305,17 @@ export default defineComponent({
|
||||
props: {
|
||||
row: { type: SalesInvoiceItem, required: true },
|
||||
batchAdded: { type: Boolean, default: false },
|
||||
expandedBatchId: {
|
||||
type: String as PropType<string | null | undefined>,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
emits: ['runSinvFormulas', 'applyPricingRule', 'selectedRow'],
|
||||
emits: [
|
||||
'runSinvFormulas',
|
||||
'applyPricingRule',
|
||||
'selectedRow',
|
||||
'setExpandedBatchId',
|
||||
],
|
||||
setup() {
|
||||
return {
|
||||
isDiscountingEnabled: inject('isDiscountingEnabled') as boolean,
|
||||
@@ -331,11 +340,17 @@ export default defineComponent({
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
expandedBatchId(newVal) {
|
||||
if (newVal !== this.row.name) {
|
||||
this.isExapanded = false;
|
||||
}
|
||||
},
|
||||
'row.batch': {
|
||||
async handler(newBatch) {
|
||||
if (newBatch) {
|
||||
this.availableQtyInBatch = await this.getAvailableQtyInBatch();
|
||||
this.isExapanded = true;
|
||||
this.$emit('setExpandedBatchId', this.row.name);
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
@@ -466,6 +481,19 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
methods: {
|
||||
toggleExpand() {
|
||||
if (this.isExapanded) {
|
||||
this.isExapanded = false;
|
||||
this.$emit('setExpandedBatchId', undefined);
|
||||
} else {
|
||||
this.isExapanded = true;
|
||||
this.$emit('setExpandedBatchId', this.row.name);
|
||||
}
|
||||
},
|
||||
toggleExpandAndEmit() {
|
||||
this.toggleExpand();
|
||||
this.$emit('selectedRow', this.row);
|
||||
},
|
||||
emitSelectedRow() {
|
||||
this.$emit('selectedRow', this.row);
|
||||
},
|
||||
|
||||
@@ -53,6 +53,10 @@
|
||||
>
|
||||
<SelectedItemRow
|
||||
:row="(row as SalesInvoiceItem)"
|
||||
:expanded-batch-id="expandedBatchId"
|
||||
@set-expanded-batch-id="
|
||||
(rowName) => $emit('setExpandedBatchId', rowName)
|
||||
"
|
||||
@run-sinv-formulas="runSinvFormulas"
|
||||
@apply-pricing-rule="$emit('applyPricingRule')"
|
||||
@selected-row="selectedItemRow"
|
||||
@@ -70,7 +74,7 @@ import RowEditForm from 'src/pages/CommonForm/RowEditForm.vue';
|
||||
import SelectedItemRow from './SelectedItemRow.vue';
|
||||
import { isNumeric } from 'src/utils';
|
||||
import { inject } from 'vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import { defineComponent, PropType } from 'vue';
|
||||
import { SalesInvoiceItem } from 'models/baseModels/SalesInvoiceItem/SalesInvoiceItem';
|
||||
import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice';
|
||||
import { Field } from 'schemas/types';
|
||||
@@ -90,12 +94,13 @@ export default defineComponent({
|
||||
sinvDoc: inject('sinvDoc') as SalesInvoice,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isExapanded: false,
|
||||
};
|
||||
props: {
|
||||
expandedBatchId: {
|
||||
type: String as PropType<string | null | undefined>,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
emits: ['applyPricingRule', 'selectedRow'],
|
||||
emits: ['applyPricingRule', 'selectedRow', 'setExpandedBatchId'],
|
||||
computed: {
|
||||
ratio() {
|
||||
return [0.1, 0.9, 0.8, 0.8, 0.8, 0.8, 0.2];
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
<feather-icon
|
||||
:name="isExapanded ? 'chevron-up' : 'chevron-down'"
|
||||
class="w-4 h-4 inline-flex dark:text-white"
|
||||
@click="isExapanded = !isExapanded"
|
||||
@click="toggleExpand"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="relative" @click="isExapanded = !isExapanded">
|
||||
<div class="relative" @click="toggleExpand">
|
||||
<Link
|
||||
:df="{
|
||||
fieldname: 'item',
|
||||
@@ -245,7 +245,7 @@ import Link from 'src/components/Controls/Link.vue';
|
||||
import Text from 'src/components/Controls/Text.vue';
|
||||
import { inject } from 'vue';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import { defineComponent } from 'vue';
|
||||
import { defineComponent, PropType } from 'vue';
|
||||
import { SalesInvoiceItem } from 'models/baseModels/SalesInvoiceItem/SalesInvoiceItem';
|
||||
import { Money } from 'pesa';
|
||||
import { validateSerialNumberCount } from 'src/utils/pos';
|
||||
@@ -256,8 +256,18 @@ export default defineComponent({
|
||||
props: {
|
||||
row: { type: SalesInvoiceItem, required: true },
|
||||
batchAdded: { type: Boolean, default: false },
|
||||
expandedBatchId: {
|
||||
type: String as PropType<string | null | undefined>,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
emits: ['toggleModal', 'runSinvFormulas', 'selectedRow', 'applyPricingRule'],
|
||||
emits: [
|
||||
'toggleModal',
|
||||
'runSinvFormulas',
|
||||
'selectedRow',
|
||||
'applyPricingRule',
|
||||
'setExpandedBatchId',
|
||||
],
|
||||
|
||||
setup() {
|
||||
return {
|
||||
@@ -278,11 +288,17 @@ export default defineComponent({
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
expandedBatchId(newVal) {
|
||||
if (newVal !== this.row.name) {
|
||||
this.isExapanded = false;
|
||||
}
|
||||
},
|
||||
'row.batch': {
|
||||
async handler(newBatch) {
|
||||
if (newBatch) {
|
||||
this.availableQtyInBatch = await this.getAvailableQtyInBatch();
|
||||
this.isExapanded = true;
|
||||
this.$emit('setExpandedBatchId', this.row.name);
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
@@ -300,6 +316,15 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
toggleExpand() {
|
||||
if (this.isExapanded) {
|
||||
this.isExapanded = false;
|
||||
this.$emit('setExpandedBatchId', undefined);
|
||||
} else {
|
||||
this.isExapanded = true;
|
||||
this.$emit('setExpandedBatchId', this.row.name);
|
||||
}
|
||||
},
|
||||
handleOpenKeyboard(row: SalesInvoiceItem, field: string) {
|
||||
if (this.isReadOnly) {
|
||||
return;
|
||||
|
||||
@@ -41,6 +41,10 @@
|
||||
>
|
||||
<ModernPOSSelectedItemRow
|
||||
:row="(row as SalesInvoiceItem)"
|
||||
:expanded-batch-id="expandedBatchId"
|
||||
@set-expanded-batch-id="
|
||||
(rowName) => $emit('setExpandedBatchId', rowName)
|
||||
"
|
||||
@selected-row="selectedItemRow"
|
||||
@run-sinv-formulas="runSinvFormulas"
|
||||
@apply-pricing-rule="$emit('applyPricingRule')"
|
||||
@@ -59,7 +63,7 @@ import RowEditForm from 'src/pages/CommonForm/RowEditForm.vue';
|
||||
import ModernPOSSelectedItemRow from './ModernPOSSelectedItemRow.vue';
|
||||
import { isNumeric } from 'src/utils';
|
||||
import { t } from 'fyo';
|
||||
import { inject, defineComponent } from 'vue';
|
||||
import { inject, defineComponent, PropType } from 'vue';
|
||||
import { SalesInvoiceItem } from 'models/baseModels/SalesInvoiceItem/SalesInvoiceItem';
|
||||
import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice';
|
||||
import { Field } from 'schemas/types';
|
||||
@@ -79,12 +83,18 @@ export default defineComponent({
|
||||
sinvDoc: inject('sinvDoc') as SalesInvoice,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isExapanded: false,
|
||||
};
|
||||
props: {
|
||||
expandedBatchId: {
|
||||
type: String as PropType<string | null | undefined>,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
emits: ['toggleModal', 'selectedRow', 'applyPricingRule'],
|
||||
emits: [
|
||||
'toggleModal',
|
||||
'selectedRow',
|
||||
'applyPricingRule',
|
||||
'setExpandedBatchId',
|
||||
],
|
||||
computed: {
|
||||
ratio() {
|
||||
return [0.1, 0.8, 0.4, 0.8, 0.8, 0.3];
|
||||
|
||||
@@ -184,6 +184,10 @@
|
||||
/>
|
||||
|
||||
<SelectedItemTable
|
||||
:expanded-batch-id="expandedBatchId"
|
||||
@set-expanded-batch-id="
|
||||
(rowName) => $emit('setExpandedBatchId', rowName)
|
||||
"
|
||||
@apply-pricing-rule="emitEvent('applyPricingRule')"
|
||||
@selected-row="(row) => $emit('selectedRow', row)"
|
||||
/>
|
||||
@@ -496,8 +500,13 @@ export default defineComponent({
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
expandedBatchId: {
|
||||
type: String as PropType<string | null | undefined>,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
emits: [
|
||||
'setExpandedBatchId',
|
||||
'addItem',
|
||||
'toggleView',
|
||||
'toggleModal',
|
||||
|
||||
@@ -119,6 +119,10 @@
|
||||
/>
|
||||
|
||||
<ModernPOSSelectedItemTable
|
||||
:expanded-batch-id="expandedBatchId"
|
||||
@set-expanded-batch-id="
|
||||
(rowName) => $emit('setExpandedBatchId', rowName)
|
||||
"
|
||||
@selected-row="selectedRow"
|
||||
@apply-pricing-rule="emitEvent('applyPricingRule')"
|
||||
@toggle-modal="emitEvent('toggleModal', 'Keyboard')"
|
||||
@@ -502,8 +506,13 @@ export default defineComponent({
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
expandedBatchId: {
|
||||
type: String as PropType<string | null | undefined>,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
emits: [
|
||||
'setExpandedBatchId',
|
||||
'addItem',
|
||||
'toggleView',
|
||||
'toggleModal',
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
:open-return-sales-invoice-modal="openReturnSalesInvoiceModal"
|
||||
:open-batch-selection-modal="openBatchSelectionModal"
|
||||
:selected-item-for-batch="selectedItemForBatch"
|
||||
:expanded-batch-id="expandedBatchId"
|
||||
@set-expanded-batch-id="setExpandedBatchId"
|
||||
@add-item="addItem"
|
||||
@toggle-view="toggleView"
|
||||
@set-sinv-doc="setSinvDoc"
|
||||
@@ -100,6 +102,8 @@
|
||||
:open-return-sales-invoice-modal="openReturnSalesInvoiceModal"
|
||||
:open-batch-selection-modal="openBatchSelectionModal"
|
||||
:selected-item-for-batch="selectedItemForBatch"
|
||||
:expanded-batch-id="expandedBatchId"
|
||||
@set-expanded-batch-id="setExpandedBatchId"
|
||||
@add-item="addItem"
|
||||
@toggle-view="toggleView"
|
||||
@set-sinv-doc="setSinvDoc"
|
||||
@@ -262,6 +266,7 @@ export default defineComponent({
|
||||
quickQtyKeyUpHandler: null as ((e: KeyboardEvent) => void) | null,
|
||||
selectedItemForBatch: '' as string,
|
||||
pendingBatchItem: null as { item: POSItem; quantity: number } | null,
|
||||
expandedBatchId: undefined as string | null | undefined,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -317,6 +322,9 @@ export default defineComponent({
|
||||
setQuickQtySelectedRow(row: SalesInvoiceItem) {
|
||||
this.quickQtyRow = row;
|
||||
},
|
||||
setExpandedBatchId(rowName: string | null) {
|
||||
this.expandedBatchId = rowName;
|
||||
},
|
||||
addQuickQtyListeners() {
|
||||
this.quickQtyKeyDownHandler = (e: KeyboardEvent) =>
|
||||
this.onQuickQtyKeyDown(e);
|
||||
|
||||
Reference in New Issue
Block a user