Updated charge close to working

This commit is contained in:
2025-09-09 18:26:21 -04:00
parent fd11c9e794
commit 98fe855e65
19 changed files with 1785 additions and 372 deletions

View File

@@ -0,0 +1,238 @@
<!-- src/pages/transactions/authorize/index.vue -->
<template>
<div class="flex">
<div class="w-full px-4 md:px-10 py-4">
<!-- Breadcrumbs & Title -->
<div class="text-sm breadcrumbs">
<ul>
<li><router-link :to="{ name: 'home' }">Home</router-link></li>
<li>Transactions</li>
<li>Authorize</li>
</ul>
</div>
<h1 class="text-3xl font-bold mt-4">Authorize.net</h1>
<!-- Main Content Card -->
<div class="bg-neutral rounded-lg p-4 sm:p-6 mt-6">
<!-- Header: Title and Count -->
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-4">
<h2 class="text-lg font-bold">All Transactions</h2>
</div>
<div class="divider"></div>
<!-- DESKTOP VIEW: Table -->
<div class="overflow-x-auto hidden xl:block">
<table class="table w-full">
<thead>
<tr>
<th>Transaction #</th>
<th>Transaction ID</th>
<th>Customer</th>
<th>Date</th>
<th>Status</th>
<th>Pre-Auth Amount</th>
<th>Charge Amount</th>
<th>Type</th>
<th>Source</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<template v-for="transaction in transactions" :key="transaction.id">
<tr class="hover:bg-blue-600 hover:text-white">
<td>{{ transaction.id }}</td>
<td>{{ transaction.auth_net_transaction_id || 'N/A' }}</td>
<td>
{{ transaction.customer_name || 'N/A' }}
</td>
<td>{{ formatDate(transaction.created_at) }}</td>
<td>
<span :class="'badge badge-sm ' + getStatusClass(transaction.status)">{{ getStatusText(transaction.status) }}</span>
</td>
<td>
${{ transaction.preauthorize_amount || '0.00' }}
</td>
<td>
${{ transaction.charge_amount || '0.00' }}
</td>
<td>
{{ transaction.transaction_type === 0 ? 'Charge' : transaction.transaction_type === 1 ? 'Auth' : 'Capture' }}
</td>
<td>
{{ getSourceText(transaction) }}
</td>
<td>
<div class="flex gap-1">
<router-link v-if="transaction.delivery_id" :to="{ name: 'deliveryOrder', params: { id: transaction.delivery_id } }" class="btn btn-xs btn-info">
View
</router-link>
<template v-if="(Number(transaction.preauthorize_amount) >= 0 && Number(transaction.charge_amount) === 0 && (transaction.delivery_id || transaction.service_id))">
<router-link v-if="!transaction.auth_net_transaction_id" :to="getPreauthRoute(transaction)" class="btn btn-xs btn-warning">
Preauth/Charge
</router-link>
<router-link v-else-if="Number(transaction.preauthorize_amount) > 0" :to="getCaptureRoute(transaction)" class="btn btn-xs btn-primary">
Capture
</router-link>
</template>
</div>
</td>
</tr>
<!-- Rejection Reason Row (Full Width) -->
<tr v-if="transaction.rejection_reason && transaction.rejection_reason.trim()" class="bg-transparent border-t border-gray-300">
<td colspan="10" class="px-4 py-3 text-red-800 font-medium">
<div class="flex items-center">
<svg class="w-5 h-5 mr-2 text-red-500" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path>
</svg>
<span class="text-red-700">{{ transaction.rejection_reason }}</span>
</div>
</td>
</tr>
</template>
</tbody>
</table>
</div>
<!-- MOBILE VIEW: Cards -->
<div class="xl:hidden space-y-4">
<div v-for="transaction in transactions" :key="transaction.id" class="card bg-base-100 shadow-md">
<div class="card-body p-4">
<div class="flex justify-between items-start">
<div>
<h2 class="card-title text-base">
<router-link v-if="transaction.customer_id" :to="{ name: 'customerProfile', params: { id: transaction.customer_id } }" class="link link-primary">
{{ transaction.customer_name || 'N/A' }}
</router-link>
<span v-else>{{ transaction.customer_name || 'N/A' }}</span>
</h2>
<p class="text-xs text-gray-400">Transaction #{{ transaction.id }}</p>
</div>
<div :class="'badge badge-' + getStatusClass(transaction.status)">
{{ getStatusText(transaction.status) }}
</div>
</div>
<div class="text-sm mt-2 space-y-1">
<p><strong>Transaction ID:</strong> {{ transaction.auth_net_transaction_id || 'N/A' }}</p>
<p><strong>Date:</strong> {{ formatDate(transaction.created_at) }}</p>
<p><strong>Pre-Auth:</strong> ${{ transaction.preauthorize_amount || '0.00' }}</p>
<p><strong>Charge:</strong> ${{ transaction.charge_amount || '0.00' }}</p>
<p><strong>Type:</strong> {{ transaction.transaction_type === 0 ? 'Charge' : transaction.transaction_type === 1 ? 'Auth' : 'Capture' }}</p>
<p><strong>Source:</strong> <router-link v-if="transaction.delivery_id" :to="{ name: 'deliveryOrder', params: { id: transaction.delivery_id } }" class="link link-primary">{{ getSourceText(transaction) }}</router-link><span v-else>{{ getSourceText(transaction) }}</span></p>
<!-- Rejection Reason in Mobile View -->
<div v-if="transaction.rejection_reason && transaction.rejection_reason.trim()" class="bg-transparent border border-gray-300 rounded-md p-3 mt-2">
<div class="flex items-start">
<svg class="w-4 h-4 mr-2 text-red-500 mt-0.5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path>
</svg>
<span class="text-red-700 text-sm">{{ transaction.rejection_reason }}</span>
</div>
</div>
<!-- Action Buttons -->
<div class="mt-3 space-y-2">
<router-link v-if="transaction.delivery_id" :to="{ name: 'deliveryOrder', params: { id: transaction.delivery_id } }" class="btn btn-xs btn-info btn-block">
View Delivery
</router-link>
<template v-if="(Number(transaction.preauthorize_amount) >= 0 && Number(transaction.charge_amount) === 0 && (transaction.delivery_id || transaction.service_id))">
<router-link v-if="!transaction.auth_net_transaction_id" :to="getPreauthRoute(transaction)" class="btn btn-xs btn-warning btn-block">
Preauth/Charge
</router-link>
<router-link v-else-if="Number(transaction.preauthorize_amount) > 0" :to="getCaptureRoute(transaction)" class="btn btn-xs btn-primary btn-block">
Capture Payment
</router-link>
</template>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<Footer />
</template>
<script lang="ts">
import {defineComponent} from 'vue'
import axios from 'axios'
import authHeader from '../../../services/auth.header'
import Header from '../../../layouts/headers/headerauth.vue'
import SideBar from '../../../layouts/sidebar/sidebar.vue'
import Footer from '../../../layouts/footers/footer.vue'
export default defineComponent({
name: 'transactionsAuthorize',
components: {
Header,
SideBar,
Footer,
},
data() {
return {
transactions: [] as any[],
}
},
created() {
this.getTransactions()
},
methods: {
getTransactions() {
let path = import.meta.env.VITE_BASE_URL + '/payment/transactions/authorize/1';
axios({
method: 'get',
url: path,
headers: authHeader(),
}).then((response: any) => {
this.transactions = response.data
}).catch(() => {
this.transactions = []
})
},
getStatusClass(status: number) {
return status === 0 ? 'badge-success' : 'badge-error'
},
getStatusText(status: number) {
return status === 0 ? 'Approved' : 'Declined'
},
getSourceText(transaction: any) {
if (transaction.delivery_id) {
return 'Delivery'
} else if (transaction.service_id) {
return 'Service'
} else {
return 'Other'
}
},
formatDate(dateStr: string) {
return dateStr.split('T')[0]; // YYYY-MM-DD
},
getCaptureRoute(transaction: any) {
if (transaction.service_id) {
return { name: 'chargeServiceAuthorize', params: { id: transaction.service_id } };
} else if (transaction.delivery_id) {
return { name: 'captureAuthorize', params: { id: transaction.delivery_id } };
}
return {}; // fallback, though condition should prevent this
},
getPreauthRoute(transaction: any) {
if (transaction.service_id) {
return { name: 'chargeServiceAuthorize', params: { id: transaction.service_id } };
} else if (transaction.delivery_id) {
return { name: 'authorizePreauthCharge', params: { id: transaction.delivery_id } };
}
return {}; // fallback, though condition should prevent this
},
},
})
</script>
<style scoped>
</style>