mirror of
https://github.com/frappe/books.git
synced 2024-11-08 23:00:56 +00:00
feat: selected items table
This commit is contained in:
parent
1878f26110
commit
c12d9e1fb8
329
src/components/NeuPOS/SelectedItemRow.vue
Normal file
329
src/components/NeuPOS/SelectedItemRow.vue
Normal file
@ -0,0 +1,329 @@
|
||||
<template>
|
||||
<feather-icon
|
||||
:name="isExapanded ? 'chevron-up' : 'chevron-down'"
|
||||
class="w-4 h-4 inline-flex"
|
||||
@click="isExapanded = !isExapanded"
|
||||
/>
|
||||
|
||||
<Link
|
||||
:df="{
|
||||
fieldname: 'item',
|
||||
fieldtype: 'Link',
|
||||
target: 'Item',
|
||||
label: 'item',
|
||||
}"
|
||||
size="small"
|
||||
:border="false"
|
||||
:value="row.item"
|
||||
:read-only="true"
|
||||
/>
|
||||
|
||||
<Int
|
||||
:df="{
|
||||
fieldname: 'quantity',
|
||||
fieldtype: 'Int',
|
||||
label: 'Quantity',
|
||||
}"
|
||||
size="small"
|
||||
:border="false"
|
||||
:value="row.quantity"
|
||||
:read-only="true"
|
||||
/>
|
||||
|
||||
<Link
|
||||
:df="{
|
||||
fieldname: 'unit',
|
||||
fieldtype: 'Link',
|
||||
target: 'UOM',
|
||||
label: 'Unit',
|
||||
}"
|
||||
size="small"
|
||||
:border="false"
|
||||
:value="row.unit"
|
||||
:read-only="true"
|
||||
/>
|
||||
|
||||
<Currency
|
||||
:df="{
|
||||
fieldtype: 'Currency',
|
||||
fieldname: 'rate',
|
||||
label: 'rate',
|
||||
}"
|
||||
size="small"
|
||||
:border="false"
|
||||
:value="row.rate"
|
||||
:read-only="true"
|
||||
/>
|
||||
|
||||
<Currency
|
||||
:df="{
|
||||
fieldtype: 'Currency',
|
||||
fieldname: 'amount',
|
||||
label: 'Amount',
|
||||
}"
|
||||
size="small"
|
||||
:border="false"
|
||||
:value="row.amount"
|
||||
:read-only="true"
|
||||
/>
|
||||
|
||||
<div class="px-4">
|
||||
<feather-icon
|
||||
name="trash"
|
||||
class="w-4 text-xl text-red-500"
|
||||
@click="$emit('removeItem', row.idx)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div></div>
|
||||
|
||||
<template v-if="isExapanded">
|
||||
<div class="px-4 pt-6 col-span-1">
|
||||
<Float
|
||||
:df="{
|
||||
fieldname: 'quantity',
|
||||
fieldtype: 'Float',
|
||||
label: 'Quantity',
|
||||
}"
|
||||
size="medium"
|
||||
:min="0"
|
||||
:border="true"
|
||||
:show-label="true"
|
||||
:value="row.quantity"
|
||||
@change="(value) => (row.quantity = value)"
|
||||
:read-only="false"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="px-4 pt-6 col-span-2 flex">
|
||||
<Link
|
||||
:df="{
|
||||
fieldname: 'transferUnit',
|
||||
fieldtype: 'Link',
|
||||
target: 'UOM',
|
||||
label: t`Transfer Unit`,
|
||||
}"
|
||||
class="flex-1"
|
||||
:show-label="true"
|
||||
:border="true"
|
||||
:value="row.transferUnit"
|
||||
@change="(value) => setTransferUnit((row.transferUnit = value))"
|
||||
/>
|
||||
<feather-icon
|
||||
name="refresh-ccw"
|
||||
class="w-3.5 ml-2 mt-4 text-blue-500"
|
||||
@click="row.transferUnit = row.unit"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="px-4 pt-6 col-span-2">
|
||||
<Int
|
||||
:df="{
|
||||
fieldtype: 'Int',
|
||||
fieldname: 'transferQuantity',
|
||||
label: 'Transfer Quantity',
|
||||
}"
|
||||
size="medium"
|
||||
:border="true"
|
||||
:show-label="true"
|
||||
:value="row.transferQuantity"
|
||||
@change="(value) => setTransferQty((row.transferQuantity = value))"
|
||||
:read-only="false"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-show="row.links?.item.hasBatch" class="pl-6 px-4 pt-6 col-span-2">
|
||||
<Link
|
||||
:df="{
|
||||
fieldname: 'batch',
|
||||
fieldtype: 'Link',
|
||||
target: 'Batch',
|
||||
label: t`Batch`,
|
||||
}"
|
||||
value=""
|
||||
:border="true"
|
||||
:show-label="true"
|
||||
:read-only="false"
|
||||
@change="(value) => setBatch(value)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-show="!!row.links?.item.hasBatch" class="px-2 pt-6 col-span-2">
|
||||
<Float
|
||||
:df="{
|
||||
fieldname: 'availableQtyInBatch',
|
||||
fieldtype: 'Float',
|
||||
label: t`Qty in Batch`,
|
||||
}"
|
||||
size="medium"
|
||||
:min="0"
|
||||
:value="availableQtyInBatch"
|
||||
:show-label="true"
|
||||
:border="true"
|
||||
:read-only="true"
|
||||
:text-right="true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-show="!!row.links?.item.hasSerialNumber"
|
||||
class="px-2 pt-8 col-span-2"
|
||||
>
|
||||
<Text
|
||||
:df="{
|
||||
label: t`Serial Number`,
|
||||
fieldtype: 'Text',
|
||||
fieldname: 'serialNumber',
|
||||
}"
|
||||
:value="row.serialNumber"
|
||||
:show-label="true"
|
||||
:border="true"
|
||||
@change="(value:string)=> setSerialNumber(value)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class=""></div>
|
||||
|
||||
<div class="px-4 pt-6 col-span-2 flex">
|
||||
<Currency
|
||||
:df="{
|
||||
fieldtype: 'Currency',
|
||||
fieldname: 'rate',
|
||||
label: 'Rate',
|
||||
}"
|
||||
class="col-span-2 flex-1"
|
||||
size="medium"
|
||||
:show-label="true"
|
||||
:border="true"
|
||||
:value="row.rate"
|
||||
:read-only="false"
|
||||
@change="(value) => (row.rate = value)"
|
||||
/>
|
||||
<feather-icon
|
||||
name="refresh-ccw"
|
||||
class="w-3.5 ml-2 mt-5 text-blue-500"
|
||||
@click="row.rate= (defaultRate as Money)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="px-6 pt-6 col-span-2">
|
||||
<Currency
|
||||
:df="{
|
||||
fieldtype: 'Currency',
|
||||
fieldname: 'discountAmount',
|
||||
label: 'Discount Amount',
|
||||
}"
|
||||
class="col-span-2"
|
||||
size="medium"
|
||||
:show-label="true"
|
||||
:border="true"
|
||||
:value="row.itemDiscountAmount"
|
||||
:read-only="row.itemDiscountPercent as number > 0"
|
||||
@change="(value) => setItemDiscount('amount', value)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="px-4 pt-6">
|
||||
<Float
|
||||
:df="{
|
||||
fieldtype: 'Float',
|
||||
fieldname: 'itemDiscountPercent',
|
||||
label: 'Discount Percent',
|
||||
}"
|
||||
size="medium"
|
||||
:show-label="true"
|
||||
:border="true"
|
||||
:value="row.itemDiscountPercent"
|
||||
:read-only="!row.itemDiscountAmount?.isZero()"
|
||||
@change="(value) => setItemDiscount('percent', value)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { SalesInvoiceItem } from 'models/baseModels/SalesInvoiceItem/SalesInvoiceItem';
|
||||
import { Money } from 'pesa';
|
||||
import { inject } from 'vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import Data from '../Controls/Data.vue';
|
||||
import Int from '../Controls/Int.vue';
|
||||
import Currency from '../Controls/Currency.vue';
|
||||
import Link from '../Controls/Link.vue';
|
||||
import Text from '../Controls/Text.vue';
|
||||
import Float from '../Controls/Float.vue';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import { DiscountType } from './types';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SelectedItemRow',
|
||||
components: { Data, Int, Currency, Link, Text, Float },
|
||||
props: {
|
||||
row: { type: SalesInvoiceItem, required: true },
|
||||
},
|
||||
emits: ['removeItem', 'setItemSerialNumbers'],
|
||||
setup() {
|
||||
return {
|
||||
itemSerialNumbers: inject('itemSerialNumbers') as {
|
||||
[item: string]: string;
|
||||
},
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isExapanded: false,
|
||||
batches: [] as string[],
|
||||
availableQtyInBatch: 0,
|
||||
|
||||
defaultRate: this.row.rate as Money,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async getAvailableQtyInBatch(): Promise<number> {
|
||||
if (!this.row.batch) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (
|
||||
(await fyo.db.getStockQuantity(
|
||||
this.row.item as string,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
this.row.batch
|
||||
)) ?? 0
|
||||
);
|
||||
},
|
||||
async setBatch(batch: string) {
|
||||
this.row.batch = batch;
|
||||
this.availableQtyInBatch = await this.getAvailableQtyInBatch();
|
||||
},
|
||||
setSerialNumber(serialNumber: string) {
|
||||
if (!serialNumber) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.itemSerialNumbers[this.row.item as string] = serialNumber;
|
||||
},
|
||||
setItemDiscount(type: DiscountType, value: Money | number) {
|
||||
if (type === DiscountType.Percent) {
|
||||
this.row.setItemDiscountAmount = false;
|
||||
this.row.itemDiscountPercent = value as number;
|
||||
return;
|
||||
}
|
||||
this.row.setItemDiscountAmount = true;
|
||||
this.row.itemDiscountAmount = value as Money;
|
||||
},
|
||||
setTransferUnit(unit: string) {
|
||||
this.row._validateFields();
|
||||
this.row.setTransferUnit = unit;
|
||||
this.row._applyFormula('transferUnit');
|
||||
},
|
||||
setTransferQty(quantity: number) {
|
||||
this.row._validateFields();
|
||||
this.row.transferQuantity = quantity;
|
||||
this.row._applyFormula('transferQuantity');
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
132
src/components/NeuPOS/SelectedItemTable.vue
Normal file
132
src/components/NeuPOS/SelectedItemTable.vue
Normal file
@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<Row
|
||||
:ratio="ratio"
|
||||
class="border rounded-t px-2 text-gray-600 w-full flex items-center mt-4"
|
||||
>
|
||||
<div
|
||||
v-if="tableFields"
|
||||
v-for="df in tableFields"
|
||||
:key="df.fieldname"
|
||||
class="items-center text-lg flex px-2 py-2"
|
||||
:class="{
|
||||
'ms-auto': isNumeric(df as Field),
|
||||
}"
|
||||
:style="{
|
||||
height: ``,
|
||||
}"
|
||||
>
|
||||
{{ df.label }}
|
||||
</div>
|
||||
</Row>
|
||||
|
||||
<Row
|
||||
v-for="row in sinvDoc.items"
|
||||
:ratio="ratio"
|
||||
class="
|
||||
border
|
||||
w-full
|
||||
px-2
|
||||
py-2
|
||||
group
|
||||
flex
|
||||
items-center
|
||||
justify-center
|
||||
hover:bg-gray-25
|
||||
"
|
||||
>
|
||||
<SelectedItemRow
|
||||
:row="(row as SalesInvoiceItem)"
|
||||
@removeItem="removeItem"
|
||||
/>
|
||||
</Row>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import Row from '../Row.vue';
|
||||
import SelectedItemRow from './SelectedItemRow.vue';
|
||||
import { isNumeric } from 'src/utils';
|
||||
import { inject } from 'vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import { Field } from 'schemas/types';
|
||||
import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice';
|
||||
import { SalesInvoiceItem } from 'models/baseModels/SalesInvoiceItem/SalesInvoiceItem';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SelectedItemTable',
|
||||
components: { Row, SelectedItemRow },
|
||||
setup() {
|
||||
return {
|
||||
sinvDoc: inject('sinvDoc') as SalesInvoice,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isExapanded: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
ratio() {
|
||||
return [0.1, 1, 0.8, 0.8, 0.8, 0.8, 0.2];
|
||||
},
|
||||
tableFields() {
|
||||
return [
|
||||
{
|
||||
fieldname: 'toggler',
|
||||
fieldtype: 'Link',
|
||||
label: ' ',
|
||||
},
|
||||
{
|
||||
fieldname: 'item',
|
||||
fieldtype: 'Link',
|
||||
label: 'Item',
|
||||
placeholder: 'Item',
|
||||
required: true,
|
||||
schemaName: 'Item',
|
||||
},
|
||||
{
|
||||
fieldname: 'quantity',
|
||||
label: 'Quantity',
|
||||
placeholder: 'Quantity',
|
||||
fieldtype: 'Int',
|
||||
required: true,
|
||||
schemaName: '',
|
||||
},
|
||||
{
|
||||
fieldname: 'unit',
|
||||
label: 'Unit',
|
||||
placeholder: 'Unit',
|
||||
fieldtype: 'Link',
|
||||
required: true,
|
||||
schemaName: 'UOM',
|
||||
},
|
||||
{
|
||||
fieldname: 'rate',
|
||||
label: 'Rate',
|
||||
placeholder: 'Rate',
|
||||
fieldtype: 'Currency',
|
||||
required: true,
|
||||
schemaName: '',
|
||||
},
|
||||
{
|
||||
fieldname: 'amount',
|
||||
label: 'Amount',
|
||||
placeholder: 'Amount',
|
||||
fieldtype: 'Currency',
|
||||
required: true,
|
||||
schemaName: '',
|
||||
},
|
||||
{
|
||||
fieldname: 'removeItem',
|
||||
fieldtype: 'Link',
|
||||
label: ' ',
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
removeItem(idx: number) {
|
||||
this.sinvDoc.remove('items', idx);
|
||||
},
|
||||
isNumeric,
|
||||
},
|
||||
});
|
||||
</script>
|
@ -4,7 +4,7 @@
|
||||
<slot>
|
||||
<div class="flex justify-end">
|
||||
<Button class="bg-red-500" @click="toggleModal('ShiftClose')">
|
||||
<span class="text-white font-medium">{{
|
||||
<span class="font-medium text-white">{{
|
||||
t`Close POS Shift `
|
||||
}}</span>
|
||||
</Button>
|
||||
@ -22,37 +22,141 @@
|
||||
@toggle-modal="toggleModal"
|
||||
/>
|
||||
|
||||
<PaymentModal />
|
||||
<PaymentModal :open-modal="openPaymentModal" @toggle-modal="toggleModal" />
|
||||
|
||||
<div
|
||||
class="bg-gray-25 gap-2 grid grid-cols-12 p-4"
|
||||
style="height: calc(100vh - var(--h-row-largest))"
|
||||
>
|
||||
<div class="bg-white border col-span-5 rounded-md">
|
||||
<div class="rounded-md p-4 col-span-5">
|
||||
<Link
|
||||
class="border-r flex-shrink-0 w-40"
|
||||
:df="{
|
||||
label: t`Search an Item`,
|
||||
fieldtype: 'Link',
|
||||
fieldname: 'item',
|
||||
target: 'Item',
|
||||
}"
|
||||
:border="true"
|
||||
:class="['w-full']"
|
||||
value=""
|
||||
@change="
|
||||
async (item: string) => (item ? addItem(getItem(item, 0)) : null)
|
||||
"
|
||||
/>
|
||||
<ItemsTable @add-item="addItem" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-7">
|
||||
<div
|
||||
class="gap-5 grid grid-rows-6"
|
||||
style="height: calc(100vh - 6.1rem)"
|
||||
>
|
||||
<div class="bg-white border p-4 rounded-md row-span-5">
|
||||
<Link
|
||||
class="flex-shrink-0"
|
||||
size="medium"
|
||||
:border="true"
|
||||
:df="{
|
||||
label: t`Customer`,
|
||||
fieldtype: 'Link',
|
||||
fieldname: 'customer',
|
||||
target: 'Party',
|
||||
schemaName: 'SalesInvoice',
|
||||
}"
|
||||
:value="defaultCustomer"
|
||||
@change="(value) => (customer = value)"
|
||||
/>
|
||||
|
||||
<SelectedItemTable />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Button from 'src/components/Button.vue';
|
||||
import ClosePOSShiftModal from './ClosePOSShiftModal.vue';
|
||||
import ItemsTable from 'src/components/NeuPOS/ItemsTable.vue';
|
||||
import Link from 'src/components/Controls/Link.vue';
|
||||
import OpenPOSShiftModal from './OpenPOSShiftModal.vue';
|
||||
import PageHeader from 'src/components/PageHeader.vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import PaymentModal from './PaymentModal.vue';
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import { toggleSidebar } from 'src/utils/ui';
|
||||
import { ValuationMethod } from 'models/inventory/types';
|
||||
import {
|
||||
getRawStockLedgerEntries,
|
||||
getStockBalanceEntries,
|
||||
getStockLedgerEntries,
|
||||
} from 'reports/inventory/helpers';
|
||||
import { DocValueMap } from 'fyo/core/types';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice';
|
||||
import { ValidationError } from 'fyo/utils/errors';
|
||||
import { getItem } from 'models/inventory/tests/helpers';
|
||||
import { handleErrorWithDialog } from 'src/errorHandling';
|
||||
import { t } from 'fyo';
|
||||
import { ItemQtyMap, ItemSerialNumbers } from 'src/components/NeuPOS/types';
|
||||
import SelectedItemTable from 'src/components/NeuPOS/SelectedItemTable.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'NeuPOS',
|
||||
components: {
|
||||
Button,
|
||||
ClosePOSShiftModal,
|
||||
ItemsTable,
|
||||
Link,
|
||||
OpenPOSShiftModal,
|
||||
PageHeader,
|
||||
PaymentModal,
|
||||
SelectedItemTable,
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
itemQtyMap: computed(() => this.itemQtyMap),
|
||||
itemSerialNumbers: computed(() => this.itemSerialNumbers),
|
||||
sinvDoc: computed(() => this.sinvDoc),
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
openShiftOpenModal: false,
|
||||
isItemsSeeded: false,
|
||||
openPaymentModal: false,
|
||||
openShiftCloseModal: false,
|
||||
openShiftOpenModal: false,
|
||||
|
||||
customer: undefined as string | undefined,
|
||||
defaultCustomer: undefined as string | undefined,
|
||||
itemSerialNumbers: {} as ItemSerialNumbers,
|
||||
itemQtyMap: {} as ItemQtyMap,
|
||||
sinvDoc: {} as SalesInvoice,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isPosShiftOpen: () => !!fyo.singles.POSShift?.isShiftOpen,
|
||||
},
|
||||
watch: {
|
||||
sinvDoc: {
|
||||
async handler() {
|
||||
await this.sinvDoc.runFormulas();
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
async activated() {
|
||||
toggleSidebar(false);
|
||||
this.setSinvDoc();
|
||||
await this.setItemQtyMap();
|
||||
},
|
||||
deactivated() {
|
||||
toggleSidebar(true);
|
||||
},
|
||||
methods: {
|
||||
toggleModal(modal: 'ShiftOpen' | 'ShiftClose', value?: boolean) {
|
||||
if (value) {
|
||||
@ -60,6 +164,96 @@ export default defineComponent({
|
||||
}
|
||||
return (this[`open${modal}Modal`] = !this[`open${modal}Modal`]);
|
||||
},
|
||||
setDefaultCustomer() {
|
||||
this.defaultCustomer = this.fyo.singles.Defaults?.posCustomer ?? '';
|
||||
this.customer = this.defaultCustomer;
|
||||
},
|
||||
async setItemQtyMap(item?: string) {
|
||||
// TODO itemQty is not populated on first run
|
||||
|
||||
const filters = {
|
||||
item: item,
|
||||
};
|
||||
const valuationMethod =
|
||||
this.fyo.singles.InventorySettings?.valuationMethod ??
|
||||
ValuationMethod.FIFO;
|
||||
|
||||
const rawSLEs = await getRawStockLedgerEntries(this.fyo);
|
||||
const rawData = getStockLedgerEntries(rawSLEs, valuationMethod);
|
||||
|
||||
const stockBalance = getStockBalanceEntries(rawData, filters);
|
||||
|
||||
for (const row of stockBalance) {
|
||||
if (!this.itemQtyMap[row.item]) {
|
||||
this.itemQtyMap[row.item] = { availableQty: 0 };
|
||||
}
|
||||
this.itemQtyMap[row.item][row.batch] = row.balanceQuantity;
|
||||
|
||||
this.itemQtyMap[row.item].availableQty += row.balanceQuantity;
|
||||
}
|
||||
|
||||
this.isItemsSeeded = true;
|
||||
},
|
||||
async addItem(item: DocValueMap) {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.sinvDoc.runFormulas();
|
||||
|
||||
if (this.itemQtyMap[item.name as string].availableQty === 0) {
|
||||
const error = new ValidationError(
|
||||
t`Item ${item.name as string} has Zero Quantity`
|
||||
);
|
||||
await handleErrorWithDialog(error, this.sinvDoc as SalesInvoice);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const existingItems =
|
||||
this.sinvDoc.items?.filter((item) => item.item === item.item) ?? [];
|
||||
|
||||
if (item.hasBatch) {
|
||||
for (const item of existingItems) {
|
||||
const itemQty = item.quantity ?? 0;
|
||||
const qtyInBatch =
|
||||
this.itemQtyMap[item.item as string][item.batch as string] ?? 0;
|
||||
|
||||
if (itemQty < qtyInBatch) {
|
||||
item.quantity = (item.quantity as number) + 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await this.sinvDoc.append('items', {
|
||||
...item,
|
||||
item: item.name,
|
||||
name: undefined,
|
||||
});
|
||||
} catch (error) {
|
||||
await handleErrorWithDialog(error, this.sinvDoc as SalesInvoice);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (existingItems.length) {
|
||||
existingItems[0].quantity = (existingItems[0].quantity as number) + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
await this.sinvDoc.append('items', {
|
||||
...item,
|
||||
name: undefined,
|
||||
item: item.name,
|
||||
});
|
||||
},
|
||||
setSinvDoc() {
|
||||
this.sinvDoc = this.fyo.doc.getNewDoc(ModelNameEnum.SalesInvoice, {
|
||||
account: 'Debtors',
|
||||
party: this.customer,
|
||||
}) as SalesInvoice;
|
||||
},
|
||||
getItem,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue
Block a user