buyer data
This commit is contained in:
@@ -159,9 +159,9 @@ WHERE drop_id = ?
|
|||||||
If inventory is available:
|
If inventory is available:
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
-- Create sale
|
-- Create sale (include buyer_data_id for delivery information)
|
||||||
INSERT INTO sales (drop_id, buyer_id, size, payment_id)
|
INSERT INTO sales (drop_id, buyer_id, buyer_data_id, size, payment_id)
|
||||||
VALUES (?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?)
|
||||||
|
|
||||||
-- Delete pending order
|
-- Delete pending order
|
||||||
DELETE FROM pending_orders WHERE id = ?
|
DELETE FROM pending_orders WHERE id = ?
|
||||||
@@ -234,11 +234,11 @@ async function handleIPNCallback(callbackData) {
|
|||||||
return { error: 'Inventory no longer available' };
|
return { error: 'Inventory no longer available' };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 5: Create sale
|
// Step 5: Create sale (include buyer_data_id for delivery information)
|
||||||
await db.transaction(async (tx) => {
|
await db.transaction(async (tx) => {
|
||||||
await tx.query(
|
await tx.query(
|
||||||
'INSERT INTO sales (drop_id, buyer_id, size, payment_id) VALUES (?, ?, ?, ?)',
|
'INSERT INTO sales (drop_id, buyer_id, buyer_data_id, size, payment_id) VALUES (?, ?, ?, ?, ?)',
|
||||||
[pendingOrder.drop_id, pendingOrder.buyer_id, pendingOrder.size, pendingOrder.payment_id]
|
[pendingOrder.drop_id, pendingOrder.buyer_id, pendingOrder.buyer_data_id, pendingOrder.size, pendingOrder.payment_id]
|
||||||
);
|
);
|
||||||
await tx.query('DELETE FROM pending_orders WHERE id = ?', [pendingOrder.id]);
|
await tx.query('DELETE FROM pending_orders WHERE id = ?', [pendingOrder.id]);
|
||||||
});
|
});
|
||||||
@@ -367,8 +367,8 @@ WHERE drop_id = ? AND expires_at > NOW()
|
|||||||
```sql
|
```sql
|
||||||
START TRANSACTION;
|
START TRANSACTION;
|
||||||
|
|
||||||
INSERT INTO sales (drop_id, buyer_id, size, payment_id)
|
INSERT INTO sales (drop_id, buyer_id, buyer_data_id, size, payment_id)
|
||||||
VALUES (?, ?, ?, ?);
|
VALUES (?, ?, ?, ?, ?);
|
||||||
|
|
||||||
DELETE FROM pending_orders WHERE id = ?;
|
DELETE FROM pending_orders WHERE id = ?;
|
||||||
|
|
||||||
|
|||||||
74
app/api/buyer-data/get-or-create/route.ts
Normal file
74
app/api/buyer-data/get-or-create/route.ts
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { cookies } from 'next/headers'
|
||||||
|
import pool from '@/lib/db'
|
||||||
|
|
||||||
|
// POST /api/buyer-data/get-or-create - Get existing buyer_data or create new one
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const cookieStore = cookies()
|
||||||
|
const buyerIdCookie = cookieStore.get('buyer_id')?.value
|
||||||
|
|
||||||
|
if (!buyerIdCookie) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Authentication required' },
|
||||||
|
{ status: 401 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const buyer_id = parseInt(buyerIdCookie, 10)
|
||||||
|
const body = await request.json()
|
||||||
|
const { fullname, address, phone } = body
|
||||||
|
|
||||||
|
// Validate required fields
|
||||||
|
if (!fullname || !address || !phone) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Full name, address, and phone are required' },
|
||||||
|
{ status: 400 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate phone format (basic validation - 10-15 digits)
|
||||||
|
const phoneRegex = /^[+]?[\d\s\-()]{10,15}$/
|
||||||
|
if (!phoneRegex.test(phone)) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Invalid phone number format' },
|
||||||
|
{ status: 400 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if buyer_data with same values already exists for this buyer
|
||||||
|
const [existingRows] = await pool.execute(
|
||||||
|
'SELECT id FROM buyer_data WHERE buyer_id = ? AND fullname = ? AND address = ? AND phone = ?',
|
||||||
|
[buyer_id, fullname.trim(), address.trim(), phone.trim()]
|
||||||
|
)
|
||||||
|
|
||||||
|
const existing = existingRows as any[]
|
||||||
|
if (existing.length > 0) {
|
||||||
|
// Return existing buyer_data_id
|
||||||
|
return NextResponse.json({
|
||||||
|
buyer_data_id: existing[0].id,
|
||||||
|
created: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new buyer_data record
|
||||||
|
const [result] = await pool.execute(
|
||||||
|
'INSERT INTO buyer_data (buyer_id, fullname, address, phone) VALUES (?, ?, ?, ?)',
|
||||||
|
[buyer_id, fullname.trim(), address.trim(), phone.trim()]
|
||||||
|
)
|
||||||
|
|
||||||
|
const buyer_data_id = (result as any).insertId
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
buyer_data_id,
|
||||||
|
created: true,
|
||||||
|
}, { status: 201 })
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error getting or creating buyer_data:', error)
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Failed to process buyer data' },
|
||||||
|
{ status: 500 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
47
app/api/buyer-data/route.ts
Normal file
47
app/api/buyer-data/route.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { cookies } from 'next/headers'
|
||||||
|
import pool from '@/lib/db'
|
||||||
|
|
||||||
|
// GET /api/buyer-data - Get the most recent buyer_data for the current buyer
|
||||||
|
export async function GET(request: NextRequest) {
|
||||||
|
try {
|
||||||
|
const cookieStore = cookies()
|
||||||
|
const buyerIdCookie = cookieStore.get('buyer_id')?.value
|
||||||
|
|
||||||
|
if (!buyerIdCookie) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Authentication required' },
|
||||||
|
{ status: 401 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const buyer_id = parseInt(buyerIdCookie, 10)
|
||||||
|
|
||||||
|
// Get the most recent buyer_data for this buyer
|
||||||
|
// Note: buyer_data table doesn't have created_at, so we'll get the one with highest ID (most recent)
|
||||||
|
const [rows] = await pool.execute(
|
||||||
|
'SELECT id, fullname, address, phone FROM buyer_data WHERE buyer_id = ? ORDER BY id DESC LIMIT 1',
|
||||||
|
[buyer_id]
|
||||||
|
)
|
||||||
|
|
||||||
|
const buyerData = rows as any[]
|
||||||
|
|
||||||
|
if (buyerData.length === 0) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ buyer_data: null },
|
||||||
|
{ status: 200 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json({
|
||||||
|
buyer_data: buyerData[0],
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching buyer_data:', error)
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Failed to fetch buyer data' },
|
||||||
|
{ status: 500 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -22,12 +22,25 @@ export async function POST(request: NextRequest) {
|
|||||||
const buyer_id = parseInt(buyerIdCookie, 10)
|
const buyer_id = parseInt(buyerIdCookie, 10)
|
||||||
|
|
||||||
const body = await request.json()
|
const body = await request.json()
|
||||||
const { drop_id, size, pay_currency } = body
|
const { drop_id, size, pay_currency, buyer_data_id } = body
|
||||||
|
|
||||||
// Validate required fields
|
// Validate required fields
|
||||||
if (!drop_id || !size) {
|
if (!drop_id || !size || !buyer_data_id) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: 'Missing required fields: drop_id, size' },
|
{ error: 'Missing required fields: drop_id, size, and buyer_data_id' },
|
||||||
|
{ status: 400 }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify buyer_data_id exists and belongs to the buyer
|
||||||
|
const [buyerDataRows] = await pool.execute(
|
||||||
|
'SELECT id FROM buyer_data WHERE id = ? AND buyer_id = ?',
|
||||||
|
[buyer_data_id, buyer_id]
|
||||||
|
)
|
||||||
|
const buyerData = buyerDataRows as any[]
|
||||||
|
if (buyerData.length === 0) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Invalid buyer_data_id or buyer_data does not belong to user' },
|
||||||
{ status: 400 }
|
{ status: 400 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -176,8 +189,8 @@ export async function POST(request: NextRequest) {
|
|||||||
// Store pending order with expiration time (atomically reserves inventory)
|
// Store pending order with expiration time (atomically reserves inventory)
|
||||||
// payment.payment_id is the NOWPayments payment ID
|
// payment.payment_id is the NOWPayments payment ID
|
||||||
await connection.execute(
|
await connection.execute(
|
||||||
'INSERT INTO pending_orders (payment_id, order_id, drop_id, buyer_id, size, price_amount, price_currency, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
|
'INSERT INTO pending_orders (payment_id, order_id, drop_id, buyer_id, buyer_data_id, size, price_amount, price_currency, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
||||||
[payment.payment_id, orderId, drop_id, buyer_id, size, priceAmount, nowPaymentsConfig.currency, expiresAt]
|
[payment.payment_id, orderId, drop_id, buyer_id, buyer_data_id, size, priceAmount, nowPaymentsConfig.currency, expiresAt]
|
||||||
)
|
)
|
||||||
|
|
||||||
// Commit transaction - inventory is now reserved
|
// Commit transaction - inventory is now reserved
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ export default function Drop() {
|
|||||||
const [selectedCurrency, setSelectedCurrency] = useState<string>('btc')
|
const [selectedCurrency, setSelectedCurrency] = useState<string>('btc')
|
||||||
const [availableCurrencies, setAvailableCurrencies] = useState<string[]>([])
|
const [availableCurrencies, setAvailableCurrencies] = useState<string[]>([])
|
||||||
const [loadingCurrencies, setLoadingCurrencies] = useState(false)
|
const [loadingCurrencies, setLoadingCurrencies] = useState(false)
|
||||||
|
const [buyerFullname, setBuyerFullname] = useState<string>('')
|
||||||
|
const [buyerAddress, setBuyerAddress] = useState<string>('')
|
||||||
|
const [buyerPhone, setBuyerPhone] = useState<string>('')
|
||||||
const [showConfirmModal, setShowConfirmModal] = useState(false)
|
const [showConfirmModal, setShowConfirmModal] = useState(false)
|
||||||
const [showAuthModal, setShowAuthModal] = useState(false)
|
const [showAuthModal, setShowAuthModal] = useState(false)
|
||||||
const [showPaymentModal, setShowPaymentModal] = useState(false)
|
const [showPaymentModal, setShowPaymentModal] = useState(false)
|
||||||
@@ -192,29 +195,82 @@ export default function Drop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fetchBuyerData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/buyer-data', {
|
||||||
|
credentials: 'include',
|
||||||
|
})
|
||||||
|
if (response.ok) {
|
||||||
|
const data = await response.json()
|
||||||
|
if (data.buyer_data) {
|
||||||
|
// Autofill form fields with existing buyer data
|
||||||
|
setBuyerFullname(data.buyer_data.fullname || '')
|
||||||
|
setBuyerAddress(data.buyer_data.address || '')
|
||||||
|
setBuyerPhone(data.buyer_data.phone || '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching buyer data:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleJoinDrop = () => {
|
const handleJoinDrop = () => {
|
||||||
// Check if user is logged in
|
// Check if user is logged in
|
||||||
if (!user) {
|
if (!user) {
|
||||||
setShowAuthModal(true)
|
setShowAuthModal(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Fetch available currencies when opening confirm modal
|
// Fetch available currencies and buyer data when opening confirm modal
|
||||||
fetchAvailableCurrencies()
|
fetchAvailableCurrencies()
|
||||||
|
fetchBuyerData()
|
||||||
setShowConfirmModal(true)
|
setShowConfirmModal(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleLogin = (loggedInUser: User) => {
|
const handleLogin = (loggedInUser: User) => {
|
||||||
setUser(loggedInUser)
|
setUser(loggedInUser)
|
||||||
setShowAuthModal(false)
|
setShowAuthModal(false)
|
||||||
// After login, show the confirmation modal
|
// After login, fetch buyer data and show the confirmation modal
|
||||||
|
fetchAvailableCurrencies()
|
||||||
|
fetchBuyerData()
|
||||||
setShowConfirmModal(true)
|
setShowConfirmModal(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleConfirmPurchase = async () => {
|
const handleConfirmPurchase = async () => {
|
||||||
if (!drop) return
|
if (!drop) return
|
||||||
|
|
||||||
|
// Validate buyer data fields
|
||||||
|
if (!buyerFullname.trim() || !buyerAddress.trim() || !buyerPhone.trim()) {
|
||||||
|
setErrorMessage('Please fill in all delivery information (full name, address, and phone)')
|
||||||
|
setShowErrorModal(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
setProcessing(true)
|
setProcessing(true)
|
||||||
try {
|
try {
|
||||||
|
// First, get or create buyer_data
|
||||||
|
const buyerDataResponse = await fetch('/api/buyer-data/get-or-create', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
credentials: 'include',
|
||||||
|
body: JSON.stringify({
|
||||||
|
fullname: buyerFullname.trim(),
|
||||||
|
address: buyerAddress.trim(),
|
||||||
|
phone: buyerPhone.trim(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!buyerDataResponse.ok) {
|
||||||
|
const error = await buyerDataResponse.json()
|
||||||
|
setErrorMessage(error.error || 'Failed to save delivery information')
|
||||||
|
setShowErrorModal(true)
|
||||||
|
setProcessing(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const buyerData = await buyerDataResponse.json()
|
||||||
|
|
||||||
// Create NOWPayments payment
|
// Create NOWPayments payment
|
||||||
const response = await fetch('/api/payments/create-invoice', {
|
const response = await fetch('/api/payments/create-invoice', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -226,6 +282,7 @@ export default function Drop() {
|
|||||||
drop_id: drop.id,
|
drop_id: drop.id,
|
||||||
size: selectedSize, // Size in grams
|
size: selectedSize, // Size in grams
|
||||||
pay_currency: selectedCurrency, // Selected payment currency
|
pay_currency: selectedCurrency, // Selected payment currency
|
||||||
|
buyer_data_id: buyerData.buyer_data_id, // Buyer delivery data ID
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -481,9 +538,87 @@ export default function Drop() {
|
|||||||
<p style={{ marginBottom: '12px', color: 'var(--muted)' }}>
|
<p style={{ marginBottom: '12px', color: 'var(--muted)' }}>
|
||||||
<strong>Price per {drop.unit}:</strong> {(drop.ppu / 1000).toFixed(2)} CHF
|
<strong>Price per {drop.unit}:</strong> {(drop.ppu / 1000).toFixed(2)} CHF
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
{/* Delivery Information */}
|
||||||
|
<div style={{ marginTop: '24px', marginBottom: '16px' }}>
|
||||||
|
<h3 style={{ marginBottom: '16px', fontSize: '16px', color: 'var(--text)' }}>
|
||||||
|
Delivery Information
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div style={{ marginBottom: '12px' }}>
|
||||||
|
<label style={{ display: 'block', marginBottom: '6px', fontSize: '14px', color: 'var(--muted)' }}>
|
||||||
|
<strong>Full Name *</strong>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={buyerFullname}
|
||||||
|
onChange={(e) => setBuyerFullname(e.target.value)}
|
||||||
|
placeholder="Enter your full name"
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
padding: '12px',
|
||||||
|
background: 'var(--bg-soft)',
|
||||||
|
border: '1px solid var(--border)',
|
||||||
|
borderRadius: '8px',
|
||||||
|
fontSize: '14px',
|
||||||
|
color: 'var(--text)',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ marginBottom: '12px' }}>
|
||||||
|
<label style={{ display: 'block', marginBottom: '6px', fontSize: '14px', color: 'var(--muted)' }}>
|
||||||
|
<strong>Address *</strong>
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
value={buyerAddress}
|
||||||
|
onChange={(e) => setBuyerAddress(e.target.value)}
|
||||||
|
placeholder="Enter your delivery address"
|
||||||
|
required
|
||||||
|
rows={3}
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
padding: '12px',
|
||||||
|
background: 'var(--bg-soft)',
|
||||||
|
border: '1px solid var(--border)',
|
||||||
|
borderRadius: '8px',
|
||||||
|
fontSize: '14px',
|
||||||
|
color: 'var(--text)',
|
||||||
|
fontFamily: 'inherit',
|
||||||
|
resize: 'vertical',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ marginBottom: '12px' }}>
|
||||||
|
<label style={{ display: 'block', marginBottom: '6px', fontSize: '14px', color: 'var(--muted)' }}>
|
||||||
|
<strong>Phone Number *</strong>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="tel"
|
||||||
|
value={buyerPhone}
|
||||||
|
onChange={(e) => setBuyerPhone(e.target.value)}
|
||||||
|
placeholder="Enter your phone number"
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
padding: '12px',
|
||||||
|
background: 'var(--bg-soft)',
|
||||||
|
border: '1px solid var(--border)',
|
||||||
|
borderRadius: '8px',
|
||||||
|
fontSize: '14px',
|
||||||
|
color: 'var(--text)',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Currency Selection */}
|
{/* Currency Selection */}
|
||||||
<div style={{ marginBottom: '16px' }}>
|
<div style={{ marginTop: '24px', marginBottom: '16px' }}>
|
||||||
<label style={{ display: 'block', marginBottom: '8px', fontSize: '14px', color: 'var(--muted)' }}>
|
<label style={{ display: 'block', marginBottom: '8px', fontSize: '14px', color: 'var(--muted)' }}>
|
||||||
<strong>Payment Currency:</strong>
|
<strong>Payment Currency:</strong>
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
79
cbd420.sql
79
cbd420.sql
@@ -3,7 +3,7 @@
|
|||||||
-- https://www.phpmyadmin.net/
|
-- https://www.phpmyadmin.net/
|
||||||
--
|
--
|
||||||
-- Host: localhost:3306
|
-- Host: localhost:3306
|
||||||
-- Generation Time: Dec 21, 2025 at 06:50 AM
|
-- Generation Time: Dec 21, 2025 at 09:44 AM
|
||||||
-- Server version: 10.11.14-MariaDB-0+deb12u2
|
-- Server version: 10.11.14-MariaDB-0+deb12u2
|
||||||
-- PHP Version: 8.2.29
|
-- PHP Version: 8.2.29
|
||||||
|
|
||||||
@@ -37,6 +37,20 @@ CREATE TABLE `buyers` (
|
|||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `buyer_data`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `buyer_data` (
|
||||||
|
`id` int(11) NOT NULL,
|
||||||
|
`buyer_id` int(11) NOT NULL,
|
||||||
|
`fullname` text NOT NULL,
|
||||||
|
`address` text NOT NULL,
|
||||||
|
`phone` varchar(15) NOT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Table structure for table `deliveries`
|
-- Table structure for table `deliveries`
|
||||||
--
|
--
|
||||||
@@ -78,10 +92,24 @@ CREATE TABLE `pending_orders` (
|
|||||||
`order_id` varchar(255) NOT NULL,
|
`order_id` varchar(255) NOT NULL,
|
||||||
`drop_id` int(11) NOT NULL,
|
`drop_id` int(11) NOT NULL,
|
||||||
`buyer_id` int(11) NOT NULL,
|
`buyer_id` int(11) NOT NULL,
|
||||||
|
`buyer_data_id` int(11) NOT NULL,
|
||||||
`size` int(11) NOT NULL,
|
`size` int(11) NOT NULL,
|
||||||
`price_amount` decimal(10,2) NOT NULL,
|
`price_amount` decimal(10,2) NOT NULL,
|
||||||
`price_currency` varchar(10) NOT NULL DEFAULT 'chf',
|
`price_currency` varchar(10) NOT NULL DEFAULT 'chf',
|
||||||
`created_at` datetime NOT NULL DEFAULT current_timestamp()
|
`created_at` datetime NOT NULL DEFAULT current_timestamp(),
|
||||||
|
`expires_at` datetime NOT NULL DEFAULT (current_timestamp() + interval 10 minute)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `referrals`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `referrals` (
|
||||||
|
`id` int(11) NOT NULL,
|
||||||
|
`referrer` int(11) NOT NULL,
|
||||||
|
`referree` int(11) NOT NULL
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||||
|
|
||||||
-- --------------------------------------------------------
|
-- --------------------------------------------------------
|
||||||
@@ -94,6 +122,7 @@ CREATE TABLE `sales` (
|
|||||||
`id` int(11) NOT NULL,
|
`id` int(11) NOT NULL,
|
||||||
`drop_id` int(11) NOT NULL,
|
`drop_id` int(11) NOT NULL,
|
||||||
`buyer_id` int(11) NOT NULL,
|
`buyer_id` int(11) NOT NULL,
|
||||||
|
`buyer_data_id` int(11) NOT NULL,
|
||||||
`size` int(11) NOT NULL DEFAULT 1,
|
`size` int(11) NOT NULL DEFAULT 1,
|
||||||
`payment_id` text NOT NULL DEFAULT '',
|
`payment_id` text NOT NULL DEFAULT '',
|
||||||
`created_at` datetime NOT NULL DEFAULT current_timestamp()
|
`created_at` datetime NOT NULL DEFAULT current_timestamp()
|
||||||
@@ -109,6 +138,12 @@ CREATE TABLE `sales` (
|
|||||||
ALTER TABLE `buyers`
|
ALTER TABLE `buyers`
|
||||||
ADD PRIMARY KEY (`id`);
|
ADD PRIMARY KEY (`id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `buyer_data`
|
||||||
|
--
|
||||||
|
ALTER TABLE `buyer_data`
|
||||||
|
ADD PRIMARY KEY (`id`);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Indexes for table `deliveries`
|
-- Indexes for table `deliveries`
|
||||||
--
|
--
|
||||||
@@ -130,7 +165,17 @@ ALTER TABLE `pending_orders`
|
|||||||
ADD UNIQUE KEY `payment_id` (`payment_id`),
|
ADD UNIQUE KEY `payment_id` (`payment_id`),
|
||||||
ADD UNIQUE KEY `order_id` (`order_id`),
|
ADD UNIQUE KEY `order_id` (`order_id`),
|
||||||
ADD KEY `drop_id` (`drop_id`),
|
ADD KEY `drop_id` (`drop_id`),
|
||||||
ADD KEY `buyer_id` (`buyer_id`);
|
ADD KEY `buyer_id` (`buyer_id`),
|
||||||
|
ADD KEY `idx_expires_at` (`expires_at`),
|
||||||
|
ADD KEY `buyer_data_id` (`buyer_data_id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `referrals`
|
||||||
|
--
|
||||||
|
ALTER TABLE `referrals`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `referree` (`referree`),
|
||||||
|
ADD KEY `referrer` (`referrer`);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Indexes for table `sales`
|
-- Indexes for table `sales`
|
||||||
@@ -138,7 +183,8 @@ ALTER TABLE `pending_orders`
|
|||||||
ALTER TABLE `sales`
|
ALTER TABLE `sales`
|
||||||
ADD PRIMARY KEY (`id`),
|
ADD PRIMARY KEY (`id`),
|
||||||
ADD KEY `drop_id` (`drop_id`),
|
ADD KEY `drop_id` (`drop_id`),
|
||||||
ADD KEY `buyer_id` (`buyer_id`);
|
ADD KEY `buyer_id` (`buyer_id`),
|
||||||
|
ADD KEY `buyer_data_id` (`buyer_data_id`);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- AUTO_INCREMENT for dumped tables
|
-- AUTO_INCREMENT for dumped tables
|
||||||
@@ -150,6 +196,12 @@ ALTER TABLE `sales`
|
|||||||
ALTER TABLE `buyers`
|
ALTER TABLE `buyers`
|
||||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `buyer_data`
|
||||||
|
--
|
||||||
|
ALTER TABLE `buyer_data`
|
||||||
|
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- AUTO_INCREMENT for table `deliveries`
|
-- AUTO_INCREMENT for table `deliveries`
|
||||||
--
|
--
|
||||||
@@ -168,6 +220,12 @@ ALTER TABLE `drops`
|
|||||||
ALTER TABLE `pending_orders`
|
ALTER TABLE `pending_orders`
|
||||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `referrals`
|
||||||
|
--
|
||||||
|
ALTER TABLE `referrals`
|
||||||
|
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- AUTO_INCREMENT for table `sales`
|
-- AUTO_INCREMENT for table `sales`
|
||||||
--
|
--
|
||||||
@@ -189,14 +247,23 @@ ALTER TABLE `deliveries`
|
|||||||
--
|
--
|
||||||
ALTER TABLE `pending_orders`
|
ALTER TABLE `pending_orders`
|
||||||
ADD CONSTRAINT `pending_orders_ibfk_1` FOREIGN KEY (`drop_id`) REFERENCES `drops` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
ADD CONSTRAINT `pending_orders_ibfk_1` FOREIGN KEY (`drop_id`) REFERENCES `drops` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
ADD CONSTRAINT `pending_orders_ibfk_2` FOREIGN KEY (`buyer_id`) REFERENCES `buyers` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
ADD CONSTRAINT `pending_orders_ibfk_2` FOREIGN KEY (`buyer_id`) REFERENCES `buyers` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
ADD CONSTRAINT `pending_orders_ibfk_3` FOREIGN KEY (`buyer_data_id`) REFERENCES `buyer_data` (`id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints for table `referrals`
|
||||||
|
--
|
||||||
|
ALTER TABLE `referrals`
|
||||||
|
ADD CONSTRAINT `referrals_ibfk_1` FOREIGN KEY (`referree`) REFERENCES `buyers` (`id`),
|
||||||
|
ADD CONSTRAINT `referrals_ibfk_2` FOREIGN KEY (`referrer`) REFERENCES `buyers` (`id`);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Constraints for table `sales`
|
-- Constraints for table `sales`
|
||||||
--
|
--
|
||||||
ALTER TABLE `sales`
|
ALTER TABLE `sales`
|
||||||
ADD CONSTRAINT `sales_ibfk_1` FOREIGN KEY (`drop_id`) REFERENCES `drops` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
ADD CONSTRAINT `sales_ibfk_1` FOREIGN KEY (`drop_id`) REFERENCES `drops` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
ADD CONSTRAINT `sales_ibfk_2` FOREIGN KEY (`buyer_id`) REFERENCES `buyers` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
ADD CONSTRAINT `sales_ibfk_2` FOREIGN KEY (`buyer_id`) REFERENCES `buyers` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
ADD CONSTRAINT `sales_ibfk_3` FOREIGN KEY (`buyer_data_id`) REFERENCES `buyer_data` (`id`);
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||||
|
|||||||
Reference in New Issue
Block a user