chore: install prettier

This commit is contained in:
Viet An
2026-05-04 15:22:27 +07:00
parent 93d29ca7d8
commit bd58e2b847
267 changed files with 22950 additions and 13581 deletions

View File

@@ -1,6 +1,6 @@
import { ref } from 'vue';
import { useNuxtApp } from '#app';
import dayjs from 'dayjs';
import { ref } from "vue";
import { useNuxtApp } from "#app";
import dayjs from "dayjs";
// Interface cho các tham số từ UI
interface TransactionParams {
@@ -18,7 +18,7 @@ interface TransactionParams {
depositReceived: number;
people?: number | null;
earlyDiscountAmount?: number;
gifts?: Array<{ id: number }>; // Thêm trường gifts
gifts?: Array<{ id: number }>; // Thêm trường gifts
}
export function useAdvancedWorkflow() {
@@ -29,26 +29,22 @@ export function useAdvancedWorkflow() {
/**
* Helper: Tìm kết quả của một step cụ thể trong mảng 'result' của backend trả về
*/
const findStepResult = (
steps: any[],
stepCode: string,
filter?: string | ((res: any) => boolean)
) => {
const findStepResult = (steps: any[], stepCode: string, filter?: string | ((res: any) => boolean)) => {
if (!Array.isArray(steps)) return null;
// 1. Tìm đúng step đang thực thi
const step = steps.find(s => (s.step === stepCode || s.step?.startsWith(stepCode)) && s.executed);
const step = steps.find((s) => (s.step === stepCode || s.step?.startsWith(stepCode)) && s.executed);
if (!step || !Array.isArray(step.results) || step.results.length === 0) return null;
// 2. Nếu filter là một hàm (Callback)
if (typeof filter === 'function') {
if (typeof filter === "function") {
const matched = step.results.find(filter);
return matched ? matched.result : null;
}
// 3. Nếu filter là một chuỗi (Action Name)
if (typeof filter === 'string') {
const matched = step.results.find(r => r.action === filter);
if (typeof filter === "string") {
const matched = step.results.find((r) => r.action === filter);
return matched ? matched.result : null;
}
@@ -62,8 +58,8 @@ export function useAdvancedWorkflow() {
const mapDiscountsList = (detailedDiscounts: any[]) => {
if (!detailedDiscounts) return [];
return detailedDiscounts
.filter(d => d.id)
.map(d => ({
.filter((d) => d.id)
.map((d) => ({
discount: d.id,
value: d.customValue,
type: d.customType,
@@ -80,7 +76,7 @@ export function useAdvancedWorkflow() {
amount: depositReceived,
due_days: 0,
description: "Thanh toán tiền đặt cọc đã nhận",
detail: { note: "Thanh toán tiền đặt cọc" }
detail: { note: "Thanh toán tiền đặt cọc" },
});
}
@@ -90,7 +86,7 @@ export function useAdvancedWorkflow() {
amount: remaining,
due_days: 2,
description: "Phần cọc còn lại",
detail: { note: "Thanh toán phần cọc còn lại" }
detail: { note: "Thanh toán phần cọc còn lại" },
});
}
return installments;
@@ -103,7 +99,7 @@ export function useAdvancedWorkflow() {
try {
const userId = $store?.login?.id;
if (!userId) {
throw new Error('Không tìm thấy thông tin người dùng. Vui lòng đăng nhập lại.');
throw new Error("Không tìm thấy thông tin người dùng. Vui lòng đăng nhập lại.");
}
// 1. Cấu hình Body theo đúng workflow
@@ -127,37 +123,36 @@ export function useAdvancedWorkflow() {
installments: createInstallments(params.depositReceived, params.reservationAmount),
people: params.people || null,
early_discount_amount: Math.trunc(params.earlyDiscountAmount || 0),
gifts: params.gifts || [] // Thêm danh sách quà tặng
}
gifts: params.gifts || [], // Thêm danh sách quà tặng
},
};
// 2. Gọi API Workflow
const response = await $insertapi('workflow', workflowPayload, undefined, false);
const response = await $insertapi("workflow", workflowPayload, undefined, false);
// Kiểm tra thành công
if (response === 'error' || !response?.success) {
throw new Error(response?.message || 'Thực thi Workflow thất bại.');
if (response === "error" || !response?.success) {
throw new Error(response?.message || "Thực thi Workflow thất bại.");
}
// 3. Bóc tách dữ liệu từ mảng result trả về
const steps = response.result;
// Lấy Transaction từ step "create_transaction" với action "API_CALL"
const txnData = findStepResult(steps, 'create_transaction', 'API_CALL');
const txnData = findStepResult(steps, "create_transaction", "API_CALL");
console.log('Transaction Data:', txnData);
console.log("Transaction Data:", txnData);
$snackbar('Giao dịch đã được khởi tạo thành công!', 'Thành công', 'Success');
$snackbar("Giao dịch đã được khởi tạo thành công!", "Thành công", "Success");
// 4. Return transaction data
return {
transaction: txnData ? { id: txnData.id, code: txnData.code } : null,
};
} catch (e: any) {
error.value = e;
console.error('Workflow Error:', e);
$snackbar(e.message || 'Có lỗi xảy ra khi thực thi workflow.', 'Lỗi', 'Error');
console.error("Workflow Error:", e);
$snackbar(e.message || "Có lỗi xảy ra khi thực thi workflow.", "Lỗi", "Error");
return null;
} finally {
isLoading.value = false;
@@ -174,7 +169,7 @@ export function useAdvancedWorkflow() {
try {
const userId = $store?.login?.id;
if (!userId) {
throw new Error('Không tìm thấy thông tin người dùng. Vui lòng đăng nhập lại.');
throw new Error("Không tìm thấy thông tin người dùng. Vui lòng đăng nhập lại.");
}
const workflowPayload = {
@@ -184,23 +179,22 @@ export function useAdvancedWorkflow() {
data: {
payment_id: paymentId,
user_id: userId,
...payload
}
...payload,
},
};
const response = await $insertapi('workflow', workflowPayload, undefined, false);
const response = await $insertapi("workflow", workflowPayload, undefined, false);
if (response === 'error' || !response?.success) {
throw new Error(response?.message || 'Không thể xác nhận công nợ qua workflow.');
if (response === "error" || !response?.success) {
throw new Error(response?.message || "Không thể xác nhận công nợ qua workflow.");
}
$snackbar('Công nợ đã được xác nhận thành công!', 'Thành công', 'Success');
$snackbar("Công nợ đã được xác nhận thành công!", "Thành công", "Success");
return true;
} catch (e: any) {
error.value = e;
console.error('Workflow Error (confirmPaymentSchedule):', e);
$snackbar(e.message || 'Có lỗi xảy ra khi xác nhận công nợ.', 'Lỗi', 'Error');
console.error("Workflow Error (confirmPaymentSchedule):", e);
$snackbar(e.message || "Có lỗi xảy ra khi xác nhận công nợ.", "Lỗi", "Error");
return false;
} finally {
isLoading.value = false;
@@ -214,7 +208,7 @@ export function useAdvancedWorkflow() {
try {
const userId = $store?.login?.id;
if (!userId) {
throw new Error('Không tìm thấy thông tin người dùng. Vui lòng đăng nhập lại.');
throw new Error("Không tìm thấy thông tin người dùng. Vui lòng đăng nhập lại.");
}
const workflowPayload = {
@@ -224,26 +218,26 @@ export function useAdvancedWorkflow() {
payment_id: paymentId,
entry_code: entryCode,
amount: entryAmount,
}
},
};
const response = await $insertapi('workflow', workflowPayload, undefined, false);
const response = await $insertapi("workflow", workflowPayload, undefined, false);
if (response === 'error' || !response?.success) {
throw new Error(response?.message || 'Không thể hủy bút toán qua workflow.');
if (response === "error" || !response?.success) {
throw new Error(response?.message || "Không thể hủy bút toán qua workflow.");
}
$snackbar('Công nợ đã được xác nhận thành công!', 'Thành công', 'Success');
$snackbar("Công nợ đã được xác nhận thành công!", "Thành công", "Success");
return true;
} catch (e: any) {
error.value = e;
console.error('Workflow Error (confirmPaymentSchedule):', e);
$snackbar(e.message || 'Có lỗi xảy ra khi xác nhận công nợ.', 'Lỗi', 'Error');
console.error("Workflow Error (confirmPaymentSchedule):", e);
$snackbar(e.message || "Có lỗi xảy ra khi xác nhận công nợ.", "Lỗi", "Error");
return false;
} finally {
isLoading.value = false;
}
}
};
/**
* DUYỆT CHI TIẾT GIAO DỊCH (QUẢN LÝ) - SỬ DỤNG WORKFLOW
@@ -255,7 +249,7 @@ export function useAdvancedWorkflow() {
try {
const userId = $store?.login?.id;
if (!userId) {
throw new Error('Không tìm thấy thông tin người dùng. Vui lòng đăng nhập lại.');
throw new Error("Không tìm thấy thông tin người dùng. Vui lòng đăng nhập lại.");
}
const workflowPayload = {
@@ -265,22 +259,21 @@ export function useAdvancedWorkflow() {
detail_id: detailId,
status_code: statusCode,
user_id: userId,
}
},
};
const response = await $insertapi('workflow', workflowPayload, undefined, false);
const response = await $insertapi("workflow", workflowPayload, undefined, false);
if (response === 'error' || !response?.success) {
throw new Error(response?.message || 'Không thể duyệt chi tiết giao dịch qua workflow.');
if (response === "error" || !response?.success) {
throw new Error(response?.message || "Không thể duyệt chi tiết giao dịch qua workflow.");
}
$snackbar('Chi tiết giao dịch đã được duyệt thành công!', 'Thành công', 'Success');
$snackbar("Chi tiết giao dịch đã được duyệt thành công!", "Thành công", "Success");
return response;
} catch (e: any) {
error.value = e;
console.error('Workflow Error (approveTransactionDetail):', e);
$snackbar(e.message || 'Có lỗi xảy ra khi duyệt chi tiết giao dịch.', 'Lỗi', 'Error');
console.error("Workflow Error (approveTransactionDetail):", e);
$snackbar(e.message || "Có lỗi xảy ra khi duyệt chi tiết giao dịch.", "Lỗi", "Error");
return null;
} finally {
isLoading.value = false;
@@ -297,7 +290,7 @@ export function useAdvancedWorkflow() {
try {
const userId = $store?.login?.id;
if (!userId) {
throw new Error('Không tìm thấy thông tin người dùng. Vui lòng đăng nhập lại.');
throw new Error("Không tìm thấy thông tin người dùng. Vui lòng đăng nhập lại.");
}
const workflowPayload = {
@@ -306,38 +299,32 @@ export function useAdvancedWorkflow() {
data: {
detail_id: detailId,
user_id: userId,
}
},
};
const response = await $insertapi('workflow', workflowPayload, undefined, false);
const response = await $insertapi("workflow", workflowPayload, undefined, false);
if (response === 'error' || !response?.success) {
throw new Error(response?.message || 'Không thể chuyển giai đoạn giao dịch qua workflow.');
if (response === "error" || !response?.success) {
throw new Error(response?.message || "Không thể chuyển giai đoạn giao dịch qua workflow.");
}
const steps = response.result;
// 1. Tìm contract thông qua step bắt đầu bằng 'adv_from_phase_' với action là 'GENERATE_DOCUMENT'
const contract = findStepResult(
steps,
'adv_lookup_transaction',
'LOOKUP_DATA'
);
const contract = findStepResult(steps, "adv_lookup_transaction", "LOOKUP_DATA");
console.log("contract", contract);
console.log('contract', contract)
$snackbar('Chuyển giai đoạn giao dịch thành công!', contract, 'Success');
$snackbar("Chuyển giai đoạn giao dịch thành công!", contract, "Success");
return {
...response,
contract: contract
contract: contract,
};
} catch (e: any) {
error.value = e;
console.error('Workflow Error (advanceTransactionPhase):', e);
$snackbar(e.message || 'Có lỗi xảy ra khi chuyển giai đoạn.', 'Lỗi', 'Error');
console.error("Workflow Error (advanceTransactionPhase):", e);
$snackbar(e.message || "Có lỗi xảy ra khi chuyển giai đoạn.", "Lỗi", "Error");
return null;
} finally {
isLoading.value = false;
@@ -345,19 +332,19 @@ export function useAdvancedWorkflow() {
};
/**
* CHUYỂN ĐỔI KHÁCH HÀNG - SỬ DỤNG WORKFLOW
*/
* CHUYỂN ĐỔI KHÁCH HÀNG - SỬ DỤNG WORKFLOW
*/
const updateTransactionCustomer = async (
transactionId: number,
newCustomerId: number,
contractDate?: string
contractDate?: string,
): Promise<any> => {
isLoading.value = true;
error.value = null;
try {
const userId = $store?.login?.id;
if (!userId) {
throw new Error('Không tìm thấy thông tin người dùng. Vui lòng đăng nhập lại.');
throw new Error("Không tìm thấy thông tin người dùng. Vui lòng đăng nhập lại.");
}
const workflowPayload = {
@@ -367,35 +354,31 @@ export function useAdvancedWorkflow() {
transaction: transactionId,
new_cus: newCustomerId,
user_id: userId,
date: contractDate || dayjs().format('YYYY-MM-DD'),
}
date: contractDate || dayjs().format("YYYY-MM-DD"),
},
};
const response = await $insertapi('workflow', workflowPayload, undefined, false);
const response = await $insertapi("workflow", workflowPayload, undefined, false);
if (response === 'error' || !response?.success) {
throw new Error(response?.message || 'Không thể chuyển đổi khách hàng qua workflow.');
if (response === "error" || !response?.success) {
throw new Error(response?.message || "Không thể chuyển đổi khách hàng qua workflow.");
}
const steps = response.result;
// Find the contract from any executed step starting with 'GEN_'
const contract = findStepResult(
steps,
'GEN_',
'API_CALL'
);
const contract = findStepResult(steps, "GEN_", "API_CALL");
$snackbar('Chuyển đổi khách hàng thành công!', 'Thành công', 'Success');
$snackbar("Chuyển đổi khách hàng thành công!", "Thành công", "Success");
return {
...response,
contract: contract
contract: contract,
};
} catch (e: any) {
error.value = e;
console.error('Workflow Error (updateTransactionCustomer):', e);
$snackbar(e.message || 'Có lỗi xảy ra khi chuyển đổi khách hàng.', 'Lỗi', 'Error');
console.error("Workflow Error (updateTransactionCustomer):", e);
$snackbar(e.message || "Có lỗi xảy ra khi chuyển đổi khách hàng.", "Lỗi", "Error");
return null;
} finally {
isLoading.value = false;
@@ -410,6 +393,6 @@ export function useAdvancedWorkflow() {
approveTransactionDetail,
advanceTransactionPhase,
updateTransactionCustomer,
rollbackPayment
rollbackPayment,
};
}
}

View File

@@ -1,5 +1,5 @@
// composables/usePaymentCalculator.js
import { ref, computed } from 'vue';
import { ref, computed } from "vue";
export function usePaymentCalculator() {
// Inputs cơ bản
@@ -24,12 +24,14 @@ export function usePaymentCalculator() {
const details = [];
let currentBalance = originPrice.value || 0;
discounts.value.forEach(discountData => {
discounts.value.forEach((discountData) => {
const d = discountData;
let amount = 0;
if (d.type === 1) { // percent
if (d.type === 1) {
// percent
amount = (currentBalance * Number(d.value)) / 100;
} else { // fixed
} else {
// fixed
amount = Number(d.value);
}
if (currentBalance - amount < 0) {
@@ -44,7 +46,7 @@ export function usePaymentCalculator() {
customValue: d.value,
customType: d.type,
amount: amount,
remaining: currentBalance
remaining: currentBalance,
});
});
return details;
@@ -77,7 +79,7 @@ export function usePaymentCalculator() {
let lastToDateForPeriodCalc = new Date(startDate.value); // Used to calculate the duration of each installment period.
sortedPlan.forEach(plan => {
sortedPlan.forEach((plan) => {
let amount = 0;
// Xử lý linh hoạt theo type của Payment_Plan
@@ -110,7 +112,7 @@ export function usePaymentCalculator() {
status: 1,
type: plan.type,
value: plan.value,
payment_note: `Thanh toán theo kế hoạch đợt số ${plan.cycle}`
payment_note: `Thanh toán theo kế hoạch đợt số ${plan.cycle}`,
});
lastToDateForPeriodCalc = new Date(toDate); // Update the last due date for the next period's duration calculation.
@@ -133,12 +135,18 @@ export function usePaymentCalculator() {
const schedule = originalPaymentSchedule.value;
const numEarly = Math.min(earlyPaymentCycles.value, schedule.length);
const actualPaymentDate = new Date(startDate.value);
const actualPaymentDateOnly = new Date(actualPaymentDate.getFullYear(), actualPaymentDate.getMonth(), actualPaymentDate.getDate());
const actualPaymentDateOnly = new Date(
actualPaymentDate.getFullYear(),
actualPaymentDate.getMonth(),
actualPaymentDate.getDate(),
);
return schedule.slice(0, numEarly).map(item => {
return schedule.slice(0, numEarly).map((item) => {
const originalDate = new Date(item.to_date);
const originalDateOnly = new Date(originalDate.getFullYear(), originalDate.getMonth(), originalDate.getDate());
const earlyDays = Math.round((originalDateOnly.getTime() - actualPaymentDateOnly.getTime()) / (1000 * 60 * 60 * 24));
const earlyDays = Math.round(
(originalDateOnly.getTime() - actualPaymentDateOnly.getTime()) / (1000 * 60 * 60 * 24),
);
if (earlyDays <= 0) {
return 0;
@@ -159,12 +167,18 @@ export function usePaymentCalculator() {
const schedule = originalPaymentSchedule.value;
const numEarly = Math.min(earlyPaymentCycles.value, schedule.length);
const actualPaymentDate = new Date(startDate.value);
const actualPaymentDateOnly = new Date(actualPaymentDate.getFullYear(), actualPaymentDate.getMonth(), actualPaymentDate.getDate());
const actualPaymentDateOnly = new Date(
actualPaymentDate.getFullYear(),
actualPaymentDate.getMonth(),
actualPaymentDate.getDate(),
);
return schedule.slice(0, numEarly).map((item, index) => {
const originalDate = new Date(item.to_date);
const originalDateOnly = new Date(originalDate.getFullYear(), originalDate.getMonth(), originalDate.getDate());
const earlyDays = Math.round((originalDateOnly.getTime() - actualPaymentDateOnly.getTime()) / (1000 * 60 * 60 * 24));
const earlyDays = Math.round(
(originalDateOnly.getTime() - actualPaymentDateOnly.getTime()) / (1000 * 60 * 60 * 24),
);
return {
cycle: item.cycle,
@@ -189,7 +203,7 @@ export function usePaymentCalculator() {
const totalEarlyAmount = earlyItems.reduce((sum, i) => sum + i.amount, 0);
const mergedAmount = totalEarlyAmount - totalEarlyDiscount.value;
const originalCycles = earlyItems.map(i => i.cycle);
const originalCycles = earlyItems.map((i) => i.cycle);
const mergedItem = {
cycle: 1,
@@ -198,11 +212,11 @@ export function usePaymentCalculator() {
amount: Math.max(0, mergedAmount),
paid_amount: 0,
remain_amount: Math.max(0, mergedAmount),
payment_note: `Thanh toán gộp đợt ${originalCycles.join(', ')} (đã trừ số tiền chiết khấu thanh toán sớm là ${totalEarlyDiscount.value})`,
payment_note: `Thanh toán gộp đợt ${originalCycles.join(", ")} (đã trừ số tiền chiết khấu thanh toán sớm là ${totalEarlyDiscount.value})`,
days: 0,
status: 1,
is_merged: true,
original_cycles: originalCycles
original_cycles: originalCycles,
};
const remainingItems = base.slice(numEarly).map((item, idx) => ({
@@ -215,7 +229,7 @@ export function usePaymentCalculator() {
// Lịch thanh toán cuối cùng
const finalPaymentSchedule = computed(() => {
const schedule = scheduleAfterEarly.value.map(item => ({ ...item }));
const schedule = scheduleAfterEarly.value.map((item) => ({ ...item }));
let remainingPaid = paidAmount.value || 0;
for (let i = 0; i < schedule.length && remainingPaid > 0; i++) {
@@ -235,9 +249,7 @@ export function usePaymentCalculator() {
return schedule;
});
const totalRemaining = computed(() =>
finalPaymentSchedule.value.reduce((sum, item) => sum + item.remain_amount, 0)
);
const totalRemaining = computed(() => finalPaymentSchedule.value.reduce((sum, item) => sum + item.remain_amount, 0));
return {
originPrice,
@@ -261,4 +273,4 @@ export function usePaymentCalculator() {
totalEarlyDiscount,
totalRemaining,
};
}
}