Good progress

This commit is contained in:
2025-09-18 13:02:28 -04:00
parent 827debd1cc
commit 6baefe9f50
6 changed files with 397 additions and 186 deletions

View File

@@ -1,4 +1,3 @@
<!-- src/pages/delivery/update_tickets/finalize_ticket.vue -->
<template>
<div class="flex">
@@ -90,7 +89,7 @@
<div class="font-bold">When Ordered</div>
<div class="opacity-80">{{ deliveryOrder.when_ordered }}</div>
</div>
</div>
</div>
@@ -159,12 +158,14 @@
<div class="font-bold text-sm">Payment Method</div>
<div class="opacity-80 text-sm">
<span v-if="deliveryOrder.payment_type == 0">Cash</span>
<span v-else-if="deliveryOrder.payment_type == 1">Credit Card</span>
<span v-else-if="deliveryOrder.payment_type == 2">Credit Card & cash</span>
<span v-else-if="deliveryOrder.payment_type == 1">CC - Tiger (Physical)</span>
<span v-else-if="deliveryOrder.payment_type == 11">CC - Authorize (API)</span>
<span v-else-if="deliveryOrder.payment_type == 2">Credit Card & Cash</span>
<span v-else-if="deliveryOrder.payment_type == 3">Check</span>
<span v-else-if="deliveryOrder.payment_type == 4">Other</span>
<span v-else>No Payment Type Added</span>
</div>
<div v-if="userCardfound && (deliveryOrder.payment_type == 1 || deliveryOrder.payment_type == 2)" class="mt-2 p-3 rounded-lg border bg-accent/20 border-accent">
<div v-if="userCardfound && (deliveryOrder.payment_type == 1 || deliveryOrder.payment_type == 2 || deliveryOrder.payment_type == 11)" class="mt-2 p-3 rounded-lg border bg-accent/20 border-accent">
<!-- --- MODIFICATION --- Full display of card data -->
<div class="font-bold text-sm">{{ userCard.type_of_card }}</div>
<div class="text-sm font-mono tracking-wider space-y-1">
@@ -175,15 +176,30 @@
</div>
</div>
</div>
<!-- Total -->
<div class="flex justify-between items-center border-t border-base-100 pt-3">
<span class="text-lg font-bold">
Final Charge Amount
</span>
<!-- --- MODIFICATION --- Use `finalChargeAmount` computed property for live updates -->
<span class="text-2xl font-bold text-success">
${{ finalChargeAmount.toFixed(2) }}
</span>
<!-- Total Breakdown -->
<div class="border-t border-base-100 pt-3 space-y-2">
<!-- Show breakdown only when promo is active -->
<div v-if="promo_active">
<!-- Oil & Fees Total (before discount) -->
<div class="flex justify-between items-center text-sm">
<span>Oil & Fees Total</span>
<span>${{ total_amount.toFixed(2) }}</span>
</div>
<!-- Promo Discount -->
<div class="flex justify-between items-center text-sm text-success">
<span>{{ promo.name_of_promotion }}</span>
<span>-${{ discount.toFixed(2) }}</span>
</div>
</div>
<!-- Final Charge Amount (always show) -->
<div class="flex justify-between items-center">
<span class="text-lg font-bold">
Final Charge Amount
</span>
<span class="text-2xl font-bold text-success">
${{ finalChargeAmount.toFixed(2) }}
</span>
</div>
</div>
</div>
</div>
@@ -205,7 +221,7 @@
<label class="label"><span class="label-text font-bold">Fill Location</span></label>
<input v-model="FinalizeOilOrderForm.fill_location" class="input input-bordered input-sm w-full max-w-xs" type="text" placeholder="Fill location (e.g., 1-12)" />
</div>
<div>
<label class="label"><span class="label-text font-bold">Cash Received</span></label>
<input v-model="FinalizeOilOrderForm.cash_recieved" class="input input-bordered input-sm w-full max-w-xs" type="number" step="0.01" placeholder="Amount received" />
@@ -270,7 +286,6 @@ export default defineComponent({
isLoading: false,
user: { id: 0 },
userCardfound: false,
total_amount: 0,
preChargeTotal: 0,
FinalizeOilOrderForm: {
cash_recieved: '',
@@ -307,16 +322,33 @@ export default defineComponent({
same_day: 0,
payment_type: 0,
payment_card_id: '',
promo_id: null,
},
pricing: {
price_prime: 0,
price_same_day: 0,
},
promo_active: false,
promo: {
name_of_promotion: '',
description: '',
money_off_delivery: 0,
text_on_ticket: ''
},
total_amount: 0,
discount: 0,
total_amount_after_discount: 0,
transaction: null as any,
}
},
computed: {
finalChargeAmount(): number {
// If promo is active, use server-calculated totals (which include discounts)
if (this.promo_active && this.total_amount_after_discount > 0) {
return this.total_amount_after_discount;
}
// Otherwise, calculate locally
const gallons = Number(this.FinalizeOilOrderForm.gallons_delivered);
const pricePerGallon = Number(this.deliveryOrder.customer_price);
if (isNaN(gallons) || isNaN(pricePerGallon) || gallons <= 0) {
@@ -340,7 +372,7 @@ export default defineComponent({
const path = `${import.meta.env.VITE_BASE_URL}/delivery/order/${delivery_id}`;
// --- DEBUGGING STEP 2 ---
console.log(`[DEBUG] Calling getOilOrder API at: ${path}`);
try {
const response = await axios.get(path, { withCredentials: true, headers: authHeader() });
// --- DEBUGGING STEP 3 ---
@@ -349,10 +381,10 @@ export default defineComponent({
if (response.data && response.data.ok) {
console.log('[DEBUG] Response is OK. Processing data...');
this.deliveryOrder = response.data.delivery;
// --- DEBUGGING STEP 4 ---
console.log(`[DEBUG] Value of response.data.total_amount is:`, response.data.total_amount);
this.total_amount = response.data.delivery.total_amount || 0;
this.preChargeTotal = response.data.delivery.total_amount || 0;
this.FinalizeOilOrderForm.gallons_delivered = this.deliveryOrder.gallons_delivered || '';
@@ -360,10 +392,17 @@ export default defineComponent({
await this.getCustomer(this.deliveryOrder.customer_id);
if ([1, 2].includes(this.deliveryOrder.payment_type) && this.deliveryOrder.payment_card_id) {
if ([1, 2, 11].includes(this.deliveryOrder.payment_type) && this.deliveryOrder.payment_card_id) {
this.getPaymentCard(this.deliveryOrder.payment_card_id);
}
if (this.deliveryOrder.promo_id != null) {
this.getPromo(this.deliveryOrder.promo_id);
}
// Fetch calculated totals including discounts
this.sumdelivery(delivery_id);
// Call transaction fetch after customer is loaded
setTimeout(() => this.getTransaction(delivery_id), 500);
} else {
@@ -411,57 +450,95 @@ export default defineComponent({
.then((response: any) => { this.pricing = response.data; })
.catch((error: any) => { console.error("[DEBUG] Error fetching oil pricing:", error); });
},
getTransaction(delivery_id: any) {
// Consistent with delivery/view.vue - use customer transaction endpoint
if (this.customer && this.customer.id) {
const path = `${import.meta.env.VITE_BASE_URL}/payment/transactions/customer/${this.customer.id}/1`;
axios.get(path, { withCredentials: true, headers: authHeader() })
.then((response: any) => {
console.log("Transaction API response:", response.data);
// Handle both single transaction object and array responses
if (response.data && Array.isArray(response.data) && response.data.length > 0) {
// Find the transaction for this specific delivery
const deliveryTransaction = response.data.find((txn: any) =>
txn.delivery_id === parseInt(delivery_id) ||
txn.transaction_id === delivery_id ||
txn.delivery_number === delivery_id
);
this.transaction = deliveryTransaction || null;
} else if (response.data && !Array.isArray(response.data)) {
// If single transaction, check if it's for this delivery
const txn = response.data;
if (txn.delivery_id === parseInt(delivery_id) ||
txn.transaction_id === delivery_id ||
txn.delivery_number === delivery_id) {
this.transaction = txn;
} else {
this.transaction = null;
}
} else {
this.transaction = null;
}
if (!this.transaction) {
console.log(`No transaction found for delivery ${delivery_id} among customer transactions`);
}
})
.catch((error: any) => {
// Handle various error responses gracefully
if (error.response && error.response.status === 404) {
console.log(`No transactions found for customer ${this.customer.id}`);
this.transaction = null;
} else if (error.response && error.response.status === 400) {
console.log(`Bad request for customer transactions: ${error.response.data?.detail || error.message}`);
this.transaction = null;
} else {
console.error("Error fetching transaction:", error);
this.transaction = null;
}
getPromo(promo_id: any) {
let path = import.meta.env.VITE_BASE_URL + "/promo/" + promo_id;
axios({
method: "get",
url: path,
withCredentials: true,
headers: authHeader(),
})
.then((response: any) => {
if (response.data) {
this.promo = response.data
this.promo_active = true
}
})
},
sumdelivery(delivery_id: any) {
let path = import.meta.env.VITE_BASE_URL + "/delivery/total/" + delivery_id;
axios({
method: "get",
url: path,
withCredentials: true,
})
.then((response: any) => {
if (response.data.ok) {
this.total_amount = parseFloat(response.data.total_amount) || 0;
this.discount = parseFloat(response.data.discount) || 0;
this.total_amount_after_discount = parseFloat(response.data.total_amount_after_discount) || 0;
}
})
.catch(() => {
notify({
title: "Error",
text: "Could not get oil pricing",
type: "error",
});
} else {
console.log("Customer data not available, cannot fetch transactions");
this.transaction = null;
});
},
getTransaction(delivery_id: any) {
// Add guard to prevent undefined customer ID API calls
if (!delivery_id || !this.customer || !this.customer.id) {
console.log("Skipping transaction fetch - delivery or customer data not available");
return;
}
// Consistent with delivery/view.vue - use customer transaction endpoint
const path = `${import.meta.env.VITE_BASE_URL}/payment/transactions/customer/${this.customer.id}/1`;
axios.get(path, { withCredentials: true, headers: authHeader() })
.then((response: any) => {
console.log("Transaction API response:", response.data);
// Handle both single transaction object and array responses
if (response.data && Array.isArray(response.data) && response.data.length > 0) {
// Find the transaction for this specific delivery
const deliveryTransaction = response.data.find((txn: any) =>
txn.delivery_id === parseInt(delivery_id) ||
txn.transaction_id === delivery_id ||
txn.delivery_number === delivery_id
);
this.transaction = deliveryTransaction || null;
} else if (response.data && !Array.isArray(response.data)) {
// If single transaction, check if it's for this delivery
const txn = response.data;
if (txn.delivery_id === parseInt(delivery_id) ||
txn.transaction_id === delivery_id ||
txn.delivery_number === delivery_id) {
this.transaction = txn;
} else {
this.transaction = null;
}
} else {
this.transaction = null;
}
if (!this.transaction) {
console.log(`No transaction found for delivery ${delivery_id} among customer transactions`);
}
})
.catch((error: any) => {
// Handle various error responses gracefully
if (error.response && error.response.status === 404) {
console.log(`No transactions found for customer ${this.customer.id}`);
this.transaction = null;
} else if (error.response && error.response.status === 400) {
console.log(`Bad request for customer transactions: ${error.response.data?.detail || error.message}`);
this.transaction = null;
} else {
console.error("Error fetching transaction:", error);
this.transaction = null;
}
});
},
getTypeColor(transactionType: number) {
switch (transactionType) {
@@ -499,12 +576,12 @@ export default defineComponent({
this.CreateTransaction();
notify({ title: "Success", text: "Ticket has been finalized.", type: "success" });
// Redirect based on payment type - redirect to capture for credit card payments
if ([1, 2].includes(this.deliveryOrder.payment_type)) {
this.$router.push({ name: "captureAuthorize", params: { id: this.deliveryOrder.id } });
} else {
this.$router.push({ name: "deliveryOrder", params: { id: this.deliveryOrder.id } });
}
// FIX: Wait for customer data to be loaded before redirecting
await this.waitForCustomerData(this.deliveryOrder.customer_id);
// Updated redirect logic based on your requirements
await this.handleRedirect();
} catch (error: any) {
const errorMessage = error.response?.data?.detail || "An error occurred during finalization.";
notify({ title: "Error", text: errorMessage, type: "error" });
@@ -512,6 +589,75 @@ export default defineComponent({
this.isLoading = false;
}
},
// NEW: Wait for customer data to be loaded before redirecting
async waitForCustomerData(customerId: number): Promise<void> {
return new Promise((resolve) => {
const checkCustomer = () => {
if (this.customer && this.customer.id && this.customer.id === customerId) {
resolve();
} else {
setTimeout(checkCustomer, 100);
}
};
checkCustomer();
});
},
// NEW: Updated redirect logic based on payment type and transaction status
async handleRedirect() {
console.log('[DEBUG] Starting redirect logic...');
console.log('[DEBUG] payment_type:', this.deliveryOrder.payment_type);
console.log('[DEBUG] transaction:', this.transaction);
console.log('[DEBUG] customer:', this.customer);
if (this.deliveryOrder.payment_type === 1) {
// payment_type 1: Manual charging - already charged, just redirect to profile
console.log('[DEBUG] payment_type 1 - redirecting to customer profile');
this.$router.push({ name: "customerProfile", params: { id: this.customer.id } });
} else if (this.deliveryOrder.payment_type === 11) {
// payment_type 11: API charging - check transaction type
console.log('[DEBUG] payment_type 11 - checking transaction type');
if (this.transaction) {
console.log('[DEBUG] Transaction found, type:', this.transaction.transaction_type);
if (this.transaction.transaction_type === 0) {
// Already charged (transaction_type = 0) - redirect to profile
console.log('[DEBUG] Already charged - redirecting to customer profile');
this.$router.push({ name: "customerProfile", params: { id: this.customer.id } });
} else if (this.transaction.transaction_type === 1) {
// Auth only (transaction_type = 1) - redirect to capture page
console.log('[DEBUG] Auth only - redirecting to capture page');
this.$router.push({ name: "captureAuthorize", params: { id: this.deliveryOrder.id } });
} else {
// Unknown transaction type - default to customer profile
console.log('[DEBUG] Unknown transaction type - redirecting to customer profile');
this.$router.push({ name: "customerProfile", params: { id: this.customer.id } });
}
} else {
// No transaction found for payment_type 11 - redirect to customer profile
console.log('[DEBUG] No transaction found for payment_type 11 - redirecting to customer profile');
this.$router.push({ name: "customerProfile", params: { id: this.customer.id } });
}
} else if ([2].includes(this.deliveryOrder.payment_type)) {
// payment_type 2: Credit Card & Cash - go to capture page for any remaining payment
console.log('[DEBUG] payment_type 2 - redirecting to capture page');
this.$router.push({ name: "captureAuthorize", params: { id: this.deliveryOrder.id } });
} else {
// Default case (cash, check, etc.) - redirect to customer profile
console.log('[DEBUG] Default payment type - redirecting to customer profile');
this.$router.push({ name: "customerProfile", params: { id: this.customer.id } });
}
},
},
});
</script>
<style scoped></style>