This commit is contained in:
Viet An
2026-06-29 17:23:48 +07:00
parent 34dd0413f3
commit 8b3da71895
7 changed files with 58 additions and 8 deletions

View File

@@ -2,6 +2,7 @@
const props = defineProps({ const props = defineProps({
cartItem: Object, cartItem: Object,
deleteable: Boolean, deleteable: Boolean,
invalid: Boolean,
}); });
const { $deleteapi, $formatNum, $snackbar } = useNuxtApp(); const { $deleteapi, $formatNum, $snackbar } = useNuxtApp();
const { getCarts } = inject("pos"); const { getCarts } = inject("pos");
@@ -30,7 +31,12 @@ async function removeFromCart() {
</script> </script>
<template> <template>
<div class="card m-0"> <div
class="card m-0"
:style="{
borderColor: invalid ? 'var(--bulma-danger-70)' : '',
}"
>
<div class="card-content p-4 is-flex is-gap-2 is-justify-content-space-between is-align-items-center"> <div class="card-content p-4 is-flex is-gap-2 is-justify-content-space-between is-align-items-center">
<div class="is-flex is-gap-4 is-justify-content-space-between is-align-items-center is-flex-grow-1"> <div class="is-flex is-gap-4 is-justify-content-space-between is-align-items-center is-flex-grow-1">
<div class="media m-0"> <div class="media m-0">
@@ -48,6 +54,14 @@ async function removeFromCart() {
<span> </span> <span> </span>
<span>{{ cartItem.imei__variant__color__name }}</span> <span>{{ cartItem.imei__variant__color__name }}</span>
</p> </p>
<p
v-if="invalid"
class="is-size-7 has-text-danger-40"
>
IMEI sản phẩm
<span class="tag is-light is-danger fs-11">{{ cartItem.imei__imei }}</span>
không sẵn
</p>
</div> </div>
</div> </div>
<p class="has-text-primary-50 font-medium"> <p class="has-text-primary-50 font-medium">

View File

@@ -4,10 +4,13 @@ import usePlaceOrder from "~/components/pos/composables/usePlaceOrder";
const id = "confirmOrderModal"; const id = "confirmOrderModal";
const emit = defineEmits(["close"]); const emit = defineEmits(["close"]);
const { activeCart, activeCartItems, orderInfo, fullAddress, getCarts, subtotal, total } = inject("pos"); const { activeCart, activeCartItems, invalidCartItems, orderInfo, fullAddress, getCarts, subtotal, total } =
inject("pos");
const { isPending, showVietQRModal, placeOrder, testReturnPage } = usePlaceOrder({ const { isPending, showVietQRModal, placeOrder, testReturnPage } = usePlaceOrder({
activeCart, activeCart,
activeCartItems, activeCartItems,
invalidCartItems,
orderInfo, orderInfo,
fullAddress, fullAddress,
subtotal, subtotal,
@@ -56,6 +59,7 @@ const { isPending, showVietQRModal, placeOrder, testReturnPage } = usePlaceOrder
v-for="cartItem in activeCartItems" v-for="cartItem in activeCartItems"
:key="cartItem.id" :key="cartItem.id"
:cartItem="cartItem" :cartItem="cartItem"
:invalid="invalidCartItems.find((ci) => ci.id === cartItem.id)"
/> />
</div> </div>
</div> </div>

View File

@@ -13,7 +13,7 @@ const { $insertapi, $formatNum } = useNuxtApp();
const { carts, cartItems, customers, getCarts, isPending } = useCartData(); const { carts, cartItems, customers, getCarts, isPending } = useCartData();
const { activeCartId, activeCart, activeCartItems, customerIdsWithNoCart, subtotal } = useActiveCart({ const { activeCartId, activeCart, activeCartItems, customerIdsWithNoCart, subtotal, invalidCartItems } = useActiveCart({
carts, carts,
cartItems, cartItems,
customers, customers,
@@ -45,7 +45,7 @@ function openConfirmModal() {
showModal.value = { showModal.value = {
component: "pos/ConfirmOrder", component: "pos/ConfirmOrder",
title: "Xác nhận đơn hàng", title: "Xác nhận đơn hàng",
width: "60%", width: "700px",
}; };
} }
@@ -62,6 +62,7 @@ provide("pos", {
activeCartId, activeCartId,
activeCart, activeCart,
activeCartItems, activeCartItems,
invalidCartItems,
isChangingCus, isChangingCus,
orderInfo, orderInfo,
fullAddress, fullAddress,
@@ -131,6 +132,7 @@ provide("pos", {
:key="cartItem.id" :key="cartItem.id"
:cartItem="cartItem" :cartItem="cartItem"
deleteable deleteable
:invalid="invalidCartItems.find((ci) => ci.id === cartItem.id)"
/> />
</div> </div>
<p <p

View File

@@ -27,5 +27,10 @@ export default function useActiveCart({ carts, cartItems, customers }) {
return activeCartItems.value?.reduce((prev, curr) => prev + curr.imei__variant__price, 0); return activeCartItems.value?.reduce((prev, curr) => prev + curr.imei__variant__price, 0);
}); });
return { activeCartId, activeCart, activeCartItems, customerIdsWithNoCart, subtotal }; const invalidCartItems = ref([]);
watch(activeCartId, () => {
invalidCartItems.value = [];
});
return { activeCartId, activeCart, activeCartItems, customerIdsWithNoCart, subtotal, invalidCartItems };
} }

View File

@@ -1,6 +1,7 @@
export default function usePlaceOrder({ export default function usePlaceOrder({
activeCart, activeCart,
activeCartItems, activeCartItems,
invalidCartItems,
orderInfo, orderInfo,
fullAddress, fullAddress,
subtotal, subtotal,
@@ -16,6 +17,22 @@ export default function usePlaceOrder({
const payment_record = ref(); const payment_record = ref();
const showVietQRModal = ref(); const showVietQRModal = ref();
async function checkImeiAvai() {
const imeisSold = await $getdata("IMEI_Sold");
const invalidImeis = [];
for (const cartItem of activeCartItems.value) {
if (imeisSold.find((sold) => sold.imei === cartItem.imei__imei)) {
invalidImeis.push(cartItem);
}
}
return {
allAvailable: invalidImeis.length === 0,
invalidImeis,
};
}
/** /**
* Create a record in `invoice` as `pending` * Create a record in `invoice` as `pending`
*/ */
@@ -193,6 +210,14 @@ export default function usePlaceOrder({
} }
async function placeOrder() { async function placeOrder() {
const { allAvailable, invalidImeis } = await checkImeiAvai();
if (!allAvailable) {
invalidCartItems.value = invalidImeis;
console.error("IMEIs not available", invalidImeis);
$snackbar("Một số IMEI đã được bán, vui lòng kiểm tra lại", "Error");
return;
}
await createOrder(); await createOrder();
if (orderInfo.value.paymentMethod.code === "CASH") { if (orderInfo.value.paymentMethod.code === "CASH") {

View File

@@ -9,7 +9,7 @@
</span> </span>
<p <p
v-html="content" v-html="content"
class="control is-expanded fs-14 has-text-danger-85" class="control is-expanded fs-14 has-text-danger-90"
></p> ></p>
</div> </div>
</template> </template>

View File

@@ -4,12 +4,12 @@
<Icon <Icon
name="material-symbols:check-circle-rounded" name="material-symbols:check-circle-rounded"
:size="18" :size="18"
class="has-text-success-70" class="has-text-success-80"
/> />
</span> </span>
<p <p
v-html="content" v-html="content"
class="control is-expanded fs-14 has-text-success-80" class="control is-expanded fs-14 has-text-success-90"
></p> ></p>
</div> </div>
</template> </template>