feat: price vat

This commit is contained in:
Methapon Metanipat 2024-10-07 15:14:33 +07:00
parent fb5e10fe04
commit c5b3e4dbd7
3 changed files with 73 additions and 53 deletions

View file

@ -1,13 +1,15 @@
<script lang="ts" setup>
import { computed, watch } from 'vue';
import { precisionRound } from 'src/utils/arithmetic';
import { QTableProps } from 'quasar';
import ThaiBahtText from 'thai-baht-text';
import { toWords } from 'number-to-words';
import { storeToRefs } from 'pinia';
import TableComponents from 'src/components/TableComponents.vue';
import { QuotationPayload } from 'src/stores/quotations/types';
import { precisionRound } from 'src/utils/arithmetic';
import TableComponents from 'components/TableComponents.vue';
import { QuotationPayload } from 'stores/quotations/types';
import { formatNumberDecimal } from 'stores/utils';
import { QTableProps } from 'quasar';
import { useConfigStore } from 'stores/config';
defineProps<{
agentPrice: boolean;
@ -17,6 +19,10 @@ defineEmits<{
(e: 'delete', index: number): void;
}>();
const configStore = useConfigStore();
const { data: config } = storeToRefs(configStore);
const rows = defineModel<
Required<QuotationPayload['productServiceList'][number]>[]
>('rows', { required: true });
@ -37,22 +43,21 @@ const summaryPrice = defineModel<{
});
function calcPrice(c: (typeof rows.value)[number]) {
const price = precisionRound(c.pricePerUnit * c.amount);
const discount = precisionRound(price * (c.discount || 0));
const vat = precisionRound((price - discount) * c.vat);
return precisionRound(price - discount + vat);
return precisionRound(
c.pricePerUnit * c.amount - c.discount + c.vat * c.amount,
);
}
const summary = computed(() =>
rows.value.reduce(
(a, c) => {
const price = precisionRound(c.pricePerUnit * c.amount);
const discount = precisionRound(price - (c.discount || 0));
const vat = precisionRound((price - discount) * c.vat);
const vat = precisionRound(
(c.pricePerUnit * c.amount - c.discount) * (config.value?.vat || 0.07),
);
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.finalPrice = precisionRound(a.totalPrice - a.totalDiscount + a.vat);
@ -184,14 +189,7 @@ watch(
<template v-slot:body-cell-pricePerUnit="{ props }">
<q-td align="right">
{{
formatNumberDecimal(
(props.row.pricePerUnit = agentPrice
? props.row.product.agentPrice
: props.row.product.price),
2,
)
}}
{{ formatNumberDecimal(props.row.pricePerUnit, 2) }}
</q-td>
</template>
@ -210,20 +208,13 @@ watch(
<template v-slot:body-cell-tax="{ props }">
<q-td align="center">
<q-input
dense
min="0"
outlined
type="number"
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>
{{
precisionRound(
(props.row.pricePerUnit * props.row.amount -
props.row.discount) *
(config?.vat || 0.07),
)
}}
</q-td>
</template>

View file

@ -16,6 +16,10 @@ import {
Service,
Work,
} 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 = {
[key: string]: any;
@ -29,6 +33,13 @@ type Node = {
type ProductGroupId = string;
const optionStore = useOptionStore();
const configStore = useConfigStore();
const { data: config } = storeToRefs(configStore);
const prop = defineProps<{
agentPrice: boolean;
}>();
const emit = defineEmits<{
(e: 'selectGroup', id: string): void;
@ -69,6 +80,8 @@ const priceDisplay = computed(() => ({
]),
}));
onMounted(configStore.getConfig);
const nodes = ref<Node[]>([]);
const productServiceCard = ref<{
service: Record<string, any>[];
@ -217,29 +230,44 @@ function mapNode() {
opened: w.productOnWork.length > 0,
checked: true,
attributes: w.attributes,
children: w.productOnWork.map((p) => ({
id: p.product.id,
title: p.product.name,
subtitle: p.product.code || ' ',
checked: true,
detail: p.product.detail,
remark: p.product.remark,
value: {
vat: 0,
pricePerUnit: 0,
discount: 0,
amount: 0,
service: v.raw,
work: w,
product: p.product,
},
type: 'product',
})),
children: w.productOnWork.map((p) => {
const price = prop.agentPrice
? p.product.agentPrice
: p.product.price;
const pricePerUnit = p.product.vatIncluded
? precisionRound(price / (1 + (config.value?.vat || 0.07)))
: price;
console.log(pricePerUnit);
return {
id: p.product.id,
title: p.product.name,
subtitle: p.product.code || ' ',
checked: true,
detail: p.product.detail,
remark: p.product.remark,
value: {
vat: 0,
pricePerUnit,
discount: 0,
amount: 0,
service: v.raw,
work: w,
product: p.product,
},
type: 'product',
};
}),
}));
return noNameObjects.concat(withNameObjects);
})(),
};
} 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 {
id: v.id,
title: v.name,
@ -248,7 +276,7 @@ function mapNode() {
remark: v.remark,
value: {
vat: 0,
pricePerUnit: 0,
pricePerUnit,
discount: 0,
amount: 0,
product: v.raw,

View file

@ -690,6 +690,7 @@ watch(
v-model:product-group="productGroup"
v-model:product-list="productList"
v-model:service-list="serviceList"
:agent-price="agentPrice"
@submit="convertToTable"
@select-group="
async (id) => {