mirror of
https://github.com/frappe/books.git
synced 2026-08-24 10:04:45 -05:00
@@ -36,6 +36,7 @@ export abstract class InvoiceItem extends Doc {
|
||||
transferUnit?: string;
|
||||
quantity?: number;
|
||||
transferQuantity?: number;
|
||||
qty?: number;
|
||||
unitConversionFactor?: number;
|
||||
batch?: string;
|
||||
|
||||
@@ -231,13 +232,28 @@ export abstract class InvoiceItem extends Doc {
|
||||
},
|
||||
transferQuantity: {
|
||||
formula: (fieldname) => {
|
||||
if (fieldname === 'qty') {
|
||||
return this.qty;
|
||||
}
|
||||
if (fieldname === 'quantity' || this.unit === this.transferUnit) {
|
||||
return this.quantity;
|
||||
}
|
||||
|
||||
return this.transferQuantity;
|
||||
},
|
||||
dependsOn: ['item', 'quantity'],
|
||||
dependsOn: ['item', 'quantity', 'qty'],
|
||||
},
|
||||
qty: {
|
||||
formula: (fieldname) => {
|
||||
if (fieldname === 'transferQuantity') {
|
||||
return this.transferQuantity;
|
||||
}
|
||||
if (fieldname === 'quantity' || this.unit === this.transferUnit) {
|
||||
return this.quantity;
|
||||
}
|
||||
return this.transferQuantity;
|
||||
},
|
||||
dependsOn: ['transferQuantity', 'quantity'],
|
||||
},
|
||||
quantity: {
|
||||
formula: async (fieldname) => {
|
||||
|
||||
@@ -44,6 +44,13 @@
|
||||
"default": 1,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"fieldname": "qty",
|
||||
"label": "Qty",
|
||||
"fieldtype": "Float",
|
||||
"default": 1,
|
||||
"computed": true
|
||||
},
|
||||
{
|
||||
"fieldname": "unit",
|
||||
"label": "Stock Unit",
|
||||
@@ -140,7 +147,7 @@
|
||||
"readOnly": true
|
||||
}
|
||||
],
|
||||
"tableFields": ["item", "tax", "quantity", "rate", "amount"],
|
||||
"tableFields": ["item", "tax", "qty", "rate", "amount"],
|
||||
"keywordFields": ["item", "tax"],
|
||||
"quickEditFields": [
|
||||
"item",
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
}"
|
||||
size="small"
|
||||
:border="false"
|
||||
:value="row.quantity"
|
||||
:value="getDisplayTransferQuantity()"
|
||||
:read-only="true"
|
||||
/>
|
||||
<div class="flex flex-col ml-1">
|
||||
@@ -70,13 +70,13 @@
|
||||
<Link
|
||||
class="ml-5"
|
||||
:df="{
|
||||
fieldname: 'unit',
|
||||
fieldname: 'transferUnit',
|
||||
fieldtype: 'Data',
|
||||
label: 'Unit',
|
||||
}"
|
||||
size="small"
|
||||
:border="false"
|
||||
:value="row.unit"
|
||||
:value="row.transferUnit || row.unit"
|
||||
:read-only="true"
|
||||
/>
|
||||
|
||||
@@ -133,18 +133,19 @@
|
||||
</div>
|
||||
|
||||
<div class="px-4 pt-6 col-span-2">
|
||||
<Link
|
||||
v-if="isUOMConversionEnabled"
|
||||
<AutoComplete
|
||||
v-if="isUOMConversionEnabled && transferUnitOptions.length"
|
||||
:key="row.item"
|
||||
:df="{
|
||||
fieldtype: 'AutoComplete',
|
||||
fieldname: 'transferUnit',
|
||||
fieldtype: 'Link',
|
||||
target: 'UOM',
|
||||
label: t`Transfer Unit`,
|
||||
options: transferUnitOptions,
|
||||
}"
|
||||
class="flex-1"
|
||||
:show-label="true"
|
||||
:border="true"
|
||||
:value="row.transferUnit"
|
||||
:value="row.transferUnit ?? ''"
|
||||
@change="(value:string) => row.set('transferUnit', value)"
|
||||
:read-only="isReadOnly"
|
||||
/>
|
||||
@@ -295,10 +296,11 @@ import { InvoiceItem } from 'models/baseModels/InvoiceItem/InvoiceItem';
|
||||
import { SalesInvoice } from 'models/baseModels/SalesInvoice/SalesInvoice';
|
||||
import { showToast } from 'src/utils/interactive';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
import AutoComplete from 'src/components/Controls/AutoComplete.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SelectedItemRow',
|
||||
components: { Currency, Data, Float, Int, Link, Text },
|
||||
components: { Currency, Data, Float, Int, Link, Text, AutoComplete },
|
||||
props: {
|
||||
row: { type: SalesInvoiceItem, required: true },
|
||||
batchAdded: { type: Boolean, default: false },
|
||||
@@ -321,6 +323,7 @@ export default defineComponent({
|
||||
defaultRate: this.row.rate as Money,
|
||||
profileDiscountSetting: null as boolean | null,
|
||||
profileRateSetting: null as boolean | null,
|
||||
transferUnitOptions: [] as Array<{ label: string; value: string }>,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
@@ -333,6 +336,16 @@ export default defineComponent({
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
'row.item': {
|
||||
async handler(newItem) {
|
||||
if (newItem) {
|
||||
await this.updateTransferUnitOptions();
|
||||
} else {
|
||||
this.transferUnitOptions = [];
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isUOMConversionEnabled(): boolean {
|
||||
@@ -394,6 +407,37 @@ export default defineComponent({
|
||||
|
||||
this.setQuantity(newQuantity);
|
||||
},
|
||||
async updateTransferUnitOptions() {
|
||||
if (!this.row.item) {
|
||||
this.transferUnitOptions = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const itemDoc = await fyo.doc.getDoc('Item', this.row.item as string);
|
||||
|
||||
const conversions = (itemDoc?.uomConversions ?? []) as Array<{
|
||||
uom: string;
|
||||
conversionFactor: number;
|
||||
}>;
|
||||
|
||||
const allowedUoms = new Set<string>();
|
||||
|
||||
if (typeof itemDoc?.unit === 'string') {
|
||||
allowedUoms.add(itemDoc.unit);
|
||||
}
|
||||
|
||||
for (const c of conversions) {
|
||||
if (typeof c.uom === 'string') {
|
||||
allowedUoms.add(c.uom);
|
||||
}
|
||||
}
|
||||
|
||||
this.transferUnitOptions = [...allowedUoms].map((uom) => ({
|
||||
label: uom,
|
||||
value: uom,
|
||||
}));
|
||||
},
|
||||
|
||||
async getAvailableQtyInBatch(): Promise<number> {
|
||||
if (!this.row.batch) {
|
||||
return 0;
|
||||
|
||||
@@ -125,7 +125,7 @@ export default defineComponent({
|
||||
},
|
||||
{
|
||||
fieldname: 'unit',
|
||||
label: 'Stock Unit',
|
||||
label: 'Unit Type',
|
||||
placeholder: 'Unit',
|
||||
fieldtype: 'Link',
|
||||
required: true,
|
||||
|
||||
@@ -60,12 +60,12 @@
|
||||
<section class="mt-8 text-base">
|
||||
<!-- Heading Row -->
|
||||
<section class="text-gray-600 w-full flex border-b">
|
||||
<div class="py-4 w-5/12">{{ t`Item` }}</div>
|
||||
<div class="py-4 w-5/12" v-if="doc.description">{{ t`Description` }}</div>
|
||||
<div class="py-4 text-right w-2/12" v-if="doc.showHSN">
|
||||
<div class="py-4 w-4/12">{{ t`Item` }}</div>
|
||||
<div class="py-4 w-4/12" v-if="doc.description">{{ t`Description` }}</div>
|
||||
<div class="py-4 text-right w-3/12" v-if="doc.showHSN">
|
||||
{{ t`HSN/SAC` }}
|
||||
</div>
|
||||
<div class="py-4 text-right w-1/12">{{ t`Quantity` }}</div>
|
||||
<div class="py-4 text-right w-3/12">{{ t`Qty` }}</div>
|
||||
<div class="py-4 text-right w-3/12">{{ t`Rate` }}</div>
|
||||
<div class="py-4 text-right w-3/12">{{ t`Amount` }}</div>
|
||||
</section>
|
||||
@@ -76,14 +76,17 @@
|
||||
v-for="row in doc.items"
|
||||
:key="row.name"
|
||||
>
|
||||
<div class="w-5/12 py-4">{{ row.item }}</div>
|
||||
<div class="w-5/12 py-4" v-if="doc.description">
|
||||
<div class="w-4/12 py-4">{{ row.item }}</div>
|
||||
<div class="w-4/12 py-4" v-if="doc.description">
|
||||
{{ row.description }}
|
||||
</div>
|
||||
<div class="w-2/12 text-right py-4" v-if="doc.showHSN">
|
||||
<div class="w-3/12 text-right py-4" v-if="doc.showHSN">
|
||||
{{ row.hsnCode }}
|
||||
</div>
|
||||
<div class="w-1/12 text-right py-4">{{ row.quantity }}</div>
|
||||
<div class="w-3/12 text-right py-4">
|
||||
<div v-if="row.transferUnit">{{ row.transferUnit }} {{ row.qty }}</div>
|
||||
<div v-else>{{ row.qty }}</div>
|
||||
</div>
|
||||
<div class="w-3/12 text-right py-4">{{ row.rate }}</div>
|
||||
<div class="w-3/12 text-right py-4">{{ row.amount }}</div>
|
||||
</section>
|
||||
|
||||
@@ -81,7 +81,13 @@
|
||||
{{ row.hsnCode }}
|
||||
</div>
|
||||
<div class="w-1/4 text-right py-1">{{ row.location }}</div>
|
||||
<div class="w-1/4 text-right py-1">{{ row.quantity }}</div>
|
||||
<div class="w-1/4 text-right py-1">
|
||||
<div>{{ row.quantity }}</div>
|
||||
<div v-if="row.transferUnit">
|
||||
({{row.transferQuantity}} of {{ row.transferUnit }})
|
||||
</div>
|
||||
<div v-else-if="row.unit">({{row.quantity}} of {{ row.unit }})</div>
|
||||
</div>
|
||||
<div class="w-3/12 text-right py-1">{{ row.rate }}</div>
|
||||
<div class="w-3/12 text-right py-1">{{ row.amount }}</div>
|
||||
</section>
|
||||
|
||||
@@ -60,10 +60,10 @@
|
||||
<section class="px-12 pt-12 text-lg">
|
||||
<!-- Heading Row -->
|
||||
<section class="mb-4 flex font-semibold">
|
||||
<div class="w-4/12">{{ t`Item` }}</div>
|
||||
<div class="w-4/12" v-if="doc.description">{{ t`Description` }}</div>
|
||||
<div class="w-2/12 text-right" v-if="doc.showHSN">{{ t`HSN/SAC` }}</div>
|
||||
<div class="w-2/12 text-right">{{ t`Quantity` }}</div>
|
||||
<div class="w-3/12">{{ t`Item` }}</div>
|
||||
<div class="w-3/12" v-if="doc.description">{{ t`Description` }}</div>
|
||||
<div class="w-3/12 text-right" v-if="doc.showHSN">{{ t`HSN/SAC` }}</div>
|
||||
<div class="w-3/12 text-right">{{ t`Qty` }}</div>
|
||||
<div class="w-3/12 text-right">{{ t`Rate` }}</div>
|
||||
<div class="w-3/12 text-right">{{ t`Amount` }}</div>
|
||||
</section>
|
||||
@@ -74,10 +74,13 @@
|
||||
v-for="row in doc.items"
|
||||
:key="row.name"
|
||||
>
|
||||
<div class="w-4/12">{{ row.item }}</div>
|
||||
<div class="w-4/12" v-if="doc.description">{{ row.description }}</div>
|
||||
<div class="w-2/12 text-right" v-if="doc.showHSN">{{ row.hsnCode }}</div>
|
||||
<div class="w-2/12 text-right">{{ row.quantity }}</div>
|
||||
<div class="w-3/12">{{ row.item }}</div>
|
||||
<div class="w-3/12" v-if="doc.description">{{ row.description }}</div>
|
||||
<div class="w-3/12 text-right" v-if="doc.showHSN">{{ row.hsnCode }}</div>
|
||||
<div class="w-3/12 text-right">
|
||||
<div v-if="row.transferUnit">{{ row.transferUnit }} {{ row.qty }}</div>
|
||||
<div v-else>{{ row.qty }}</div>
|
||||
</div>
|
||||
<div class="w-3/12 text-right">{{ row.rate }}</div>
|
||||
<div class="w-3/12 text-right">{{ row.amount }}</div>
|
||||
</section>
|
||||
|
||||
@@ -98,24 +98,27 @@
|
||||
text-gray-800
|
||||
"
|
||||
>
|
||||
<div class="w-4/12 text-left">{{ t`Item` }}</div>
|
||||
<div class="w-4/12 text-left" v-if="doc.description">
|
||||
<div class="w-3/12 text-left">{{ t`Item` }}</div>
|
||||
<div class="w-3/12 text-left" v-if="doc.description">
|
||||
{{ t`Description` }}
|
||||
</div>
|
||||
<div class="w-2/12 text-right" v-if="doc.showHSN">{{ t`HSN/SAC` }}</div>
|
||||
<div class="w-2/12 text-right">{{ t`Quantity` }}</div>
|
||||
<div class="w-3/12 text-right" v-if="doc.showHSN">{{ t`HSN/SAC` }}</div>
|
||||
<div class="w-3/12 text-right">{{ t`Qty` }}</div>
|
||||
<div class="w-3/12 text-right">{{ t`Rate` }}</div>
|
||||
<div class="w-3/12 text-right">{{ t`Amount`}}</div>
|
||||
</section>
|
||||
|
||||
<!-- Body Rows -->
|
||||
<section class="flex py-1 text-lg" v-for="row in doc.items" :key="row.name">
|
||||
<div class="w-4/12 text-left">{{ row.item }}</div>
|
||||
<div class="w-4/12 text-left" v-if="doc.description">
|
||||
<div class="w-3/12 text-left">{{ row.item }}</div>
|
||||
<div class="w-3/12 text-left" v-if="doc.description">
|
||||
{{ row.description }}
|
||||
</div>
|
||||
<div class="w-2/12 text-right" v-if="doc.showHSN">{{ row.hsnCode }}</div>
|
||||
<div class="w-2/12 text-right">{{ row.quantity }}</div>
|
||||
<div class="w-3/12 text-right" v-if="doc.showHSN">{{ row.hsnCode }}</div>
|
||||
<div class="w-3/12 text-right">
|
||||
<div v-if="row.transferUnit">{{ row.transferUnit }} {{ row.qty }}</div>
|
||||
<div v-else>{{ row.qty }}</div>
|
||||
</div>
|
||||
<div class="w-3/12 text-right">{{ row.rate }}</div>
|
||||
<div class="w-3/12 text-right">{{ row.amount }}</div>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user