feat: price vat
This commit is contained in:
parent
fb5e10fe04
commit
c5b3e4dbd7
3 changed files with 73 additions and 53 deletions
|
|
@ -1,13 +1,15 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, watch } from 'vue';
|
import { computed, watch } from 'vue';
|
||||||
import { precisionRound } from 'src/utils/arithmetic';
|
import { QTableProps } from 'quasar';
|
||||||
import ThaiBahtText from 'thai-baht-text';
|
import ThaiBahtText from 'thai-baht-text';
|
||||||
import { toWords } from 'number-to-words';
|
import { toWords } from 'number-to-words';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
||||||
import TableComponents from 'src/components/TableComponents.vue';
|
import { precisionRound } from 'src/utils/arithmetic';
|
||||||
import { QuotationPayload } from 'src/stores/quotations/types';
|
import TableComponents from 'components/TableComponents.vue';
|
||||||
|
import { QuotationPayload } from 'stores/quotations/types';
|
||||||
import { formatNumberDecimal } from 'stores/utils';
|
import { formatNumberDecimal } from 'stores/utils';
|
||||||
import { QTableProps } from 'quasar';
|
import { useConfigStore } from 'stores/config';
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
agentPrice: boolean;
|
agentPrice: boolean;
|
||||||
|
|
@ -17,6 +19,10 @@ defineEmits<{
|
||||||
(e: 'delete', index: number): void;
|
(e: 'delete', index: number): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const configStore = useConfigStore();
|
||||||
|
|
||||||
|
const { data: config } = storeToRefs(configStore);
|
||||||
|
|
||||||
const rows = defineModel<
|
const rows = defineModel<
|
||||||
Required<QuotationPayload['productServiceList'][number]>[]
|
Required<QuotationPayload['productServiceList'][number]>[]
|
||||||
>('rows', { required: true });
|
>('rows', { required: true });
|
||||||
|
|
@ -37,22 +43,21 @@ const summaryPrice = defineModel<{
|
||||||
});
|
});
|
||||||
|
|
||||||
function calcPrice(c: (typeof rows.value)[number]) {
|
function calcPrice(c: (typeof rows.value)[number]) {
|
||||||
const price = precisionRound(c.pricePerUnit * c.amount);
|
return precisionRound(
|
||||||
const discount = precisionRound(price * (c.discount || 0));
|
c.pricePerUnit * c.amount - c.discount + c.vat * c.amount,
|
||||||
const vat = precisionRound((price - discount) * c.vat);
|
);
|
||||||
|
|
||||||
return precisionRound(price - discount + vat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const summary = computed(() =>
|
const summary = computed(() =>
|
||||||
rows.value.reduce(
|
rows.value.reduce(
|
||||||
(a, c) => {
|
(a, c) => {
|
||||||
const price = precisionRound(c.pricePerUnit * c.amount);
|
const price = precisionRound(c.pricePerUnit * c.amount);
|
||||||
const discount = precisionRound(price - (c.discount || 0));
|
const vat = precisionRound(
|
||||||
const vat = precisionRound((price - discount) * c.vat);
|
(c.pricePerUnit * c.amount - c.discount) * (config.value?.vat || 0.07),
|
||||||
|
);
|
||||||
|
|
||||||
a.totalPrice = precisionRound(a.totalPrice + price);
|
a.totalPrice = precisionRound(a.totalPrice + price);
|
||||||
a.totalDiscount = precisionRound(a.totalDiscount + discount);
|
a.totalDiscount = precisionRound(a.totalDiscount + Number(c.discount));
|
||||||
a.vat = precisionRound(a.vat + vat);
|
a.vat = precisionRound(a.vat + vat);
|
||||||
a.finalPrice = precisionRound(a.totalPrice - a.totalDiscount + a.vat);
|
a.finalPrice = precisionRound(a.totalPrice - a.totalDiscount + a.vat);
|
||||||
|
|
||||||
|
|
@ -184,14 +189,7 @@ watch(
|
||||||
|
|
||||||
<template v-slot:body-cell-pricePerUnit="{ props }">
|
<template v-slot:body-cell-pricePerUnit="{ props }">
|
||||||
<q-td align="right">
|
<q-td align="right">
|
||||||
{{
|
{{ formatNumberDecimal(props.row.pricePerUnit, 2) }}
|
||||||
formatNumberDecimal(
|
|
||||||
(props.row.pricePerUnit = agentPrice
|
|
||||||
? props.row.product.agentPrice
|
|
||||||
: props.row.product.price),
|
|
||||||
2,
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</q-td>
|
</q-td>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -210,20 +208,13 @@ watch(
|
||||||
|
|
||||||
<template v-slot:body-cell-tax="{ props }">
|
<template v-slot:body-cell-tax="{ props }">
|
||||||
<q-td align="center">
|
<q-td align="center">
|
||||||
<q-input
|
{{
|
||||||
dense
|
precisionRound(
|
||||||
min="0"
|
(props.row.pricePerUnit * props.row.amount -
|
||||||
outlined
|
props.row.discount) *
|
||||||
type="number"
|
(config?.vat || 0.07),
|
||||||
readonly
|
)
|
||||||
class="bordered rounded"
|
}}
|
||||||
style="width: 70px"
|
|
||||||
v-model="props.row.vat"
|
|
||||||
>
|
|
||||||
<template v-slot:append>
|
|
||||||
<span class="text-caption no-padding">%</span>
|
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
</q-td>
|
</q-td>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,10 @@ import {
|
||||||
Service,
|
Service,
|
||||||
Work,
|
Work,
|
||||||
} from 'src/stores/product-service/types';
|
} from 'src/stores/product-service/types';
|
||||||
|
import { precisionRound } from 'src/utils/arithmetic';
|
||||||
|
import { useConfigStore } from 'src/stores/config';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { onMounted } from 'vue';
|
||||||
|
|
||||||
type Node = {
|
type Node = {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
|
|
@ -29,6 +33,13 @@ type Node = {
|
||||||
type ProductGroupId = string;
|
type ProductGroupId = string;
|
||||||
|
|
||||||
const optionStore = useOptionStore();
|
const optionStore = useOptionStore();
|
||||||
|
const configStore = useConfigStore();
|
||||||
|
|
||||||
|
const { data: config } = storeToRefs(configStore);
|
||||||
|
|
||||||
|
const prop = defineProps<{
|
||||||
|
agentPrice: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'selectGroup', id: string): void;
|
(e: 'selectGroup', id: string): void;
|
||||||
|
|
@ -69,6 +80,8 @@ const priceDisplay = computed(() => ({
|
||||||
]),
|
]),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
onMounted(configStore.getConfig);
|
||||||
|
|
||||||
const nodes = ref<Node[]>([]);
|
const nodes = ref<Node[]>([]);
|
||||||
const productServiceCard = ref<{
|
const productServiceCard = ref<{
|
||||||
service: Record<string, any>[];
|
service: Record<string, any>[];
|
||||||
|
|
@ -217,29 +230,44 @@ function mapNode() {
|
||||||
opened: w.productOnWork.length > 0,
|
opened: w.productOnWork.length > 0,
|
||||||
checked: true,
|
checked: true,
|
||||||
attributes: w.attributes,
|
attributes: w.attributes,
|
||||||
children: w.productOnWork.map((p) => ({
|
children: w.productOnWork.map((p) => {
|
||||||
id: p.product.id,
|
const price = prop.agentPrice
|
||||||
title: p.product.name,
|
? p.product.agentPrice
|
||||||
subtitle: p.product.code || ' ',
|
: p.product.price;
|
||||||
checked: true,
|
const pricePerUnit = p.product.vatIncluded
|
||||||
detail: p.product.detail,
|
? precisionRound(price / (1 + (config.value?.vat || 0.07)))
|
||||||
remark: p.product.remark,
|
: price;
|
||||||
value: {
|
console.log(pricePerUnit);
|
||||||
vat: 0,
|
return {
|
||||||
pricePerUnit: 0,
|
id: p.product.id,
|
||||||
discount: 0,
|
title: p.product.name,
|
||||||
amount: 0,
|
subtitle: p.product.code || ' ',
|
||||||
service: v.raw,
|
checked: true,
|
||||||
work: w,
|
detail: p.product.detail,
|
||||||
product: p.product,
|
remark: p.product.remark,
|
||||||
},
|
value: {
|
||||||
type: 'product',
|
vat: 0,
|
||||||
})),
|
pricePerUnit,
|
||||||
|
discount: 0,
|
||||||
|
amount: 0,
|
||||||
|
service: v.raw,
|
||||||
|
work: w,
|
||||||
|
product: p.product,
|
||||||
|
},
|
||||||
|
type: 'product',
|
||||||
|
};
|
||||||
|
}),
|
||||||
}));
|
}));
|
||||||
return noNameObjects.concat(withNameObjects);
|
return noNameObjects.concat(withNameObjects);
|
||||||
})(),
|
})(),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
const price = prop.agentPrice ? v.agentPrice : v.price;
|
||||||
|
const pricePerUnit = v.vatIncluded
|
||||||
|
? precisionRound(price / (1 + (config.value?.vat || 0.07)))
|
||||||
|
: price;
|
||||||
|
|
||||||
|
console.log(pricePerUnit);
|
||||||
return {
|
return {
|
||||||
id: v.id,
|
id: v.id,
|
||||||
title: v.name,
|
title: v.name,
|
||||||
|
|
@ -248,7 +276,7 @@ function mapNode() {
|
||||||
remark: v.remark,
|
remark: v.remark,
|
||||||
value: {
|
value: {
|
||||||
vat: 0,
|
vat: 0,
|
||||||
pricePerUnit: 0,
|
pricePerUnit,
|
||||||
discount: 0,
|
discount: 0,
|
||||||
amount: 0,
|
amount: 0,
|
||||||
product: v.raw,
|
product: v.raw,
|
||||||
|
|
|
||||||
|
|
@ -690,6 +690,7 @@ watch(
|
||||||
v-model:product-group="productGroup"
|
v-model:product-group="productGroup"
|
||||||
v-model:product-list="productList"
|
v-model:product-list="productList"
|
||||||
v-model:service-list="serviceList"
|
v-model:service-list="serviceList"
|
||||||
|
:agent-price="agentPrice"
|
||||||
@submit="convertToTable"
|
@submit="convertToTable"
|
||||||
@select-group="
|
@select-group="
|
||||||
async (id) => {
|
async (id) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue