formatting
This commit is contained in:
@@ -636,6 +636,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getDayWithOrdinal(date: CalendarDate): string {
|
||||||
|
const monthName = new Date(date.year, date.month - 1, date.day).toLocaleDateString('en-GB', {
|
||||||
|
month: 'long'
|
||||||
|
});
|
||||||
|
const day = date.day;
|
||||||
|
if (day > 3 && day < 21) return monthName + ' ' + day + 'th';
|
||||||
|
switch (day % 10) {
|
||||||
|
case 1:
|
||||||
|
return monthName + ' ' + day + 'st';
|
||||||
|
case 2:
|
||||||
|
return monthName + ' ' + day + 'nd';
|
||||||
|
case 3:
|
||||||
|
return monthName + ' ' + day + 'rd';
|
||||||
|
default:
|
||||||
|
return monthName + ' ' + day + 'th';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Use the formatted duration everywhere
|
// Use the formatted duration everywhere
|
||||||
const formattedTotalDuration = $derived(formatDuration(getTotalDuration()));
|
const formattedTotalDuration = $derived(formatDuration(getTotalDuration()));
|
||||||
|
|
||||||
@@ -823,6 +841,9 @@
|
|||||||
{#if (loadingWorkingHours || loadingAvailableHours) && selectedDate}
|
{#if (loadingWorkingHours || loadingAvailableHours) && selectedDate}
|
||||||
<div class="text-center text-sm text-gray-500">Loading available times...</div>
|
<div class="text-center text-sm text-gray-500">Loading available times...</div>
|
||||||
{:else if groupedTimeSlots.length > 0}
|
{:else if groupedTimeSlots.length > 0}
|
||||||
|
{#if selectedDate}
|
||||||
|
<div class="grid justify-center gap-2">{getDayWithOrdinal(selectedDate)}</div>
|
||||||
|
{/if}
|
||||||
<!-- Grouped Time Slots Grid - ORIGINAL STYLING BUT WITH GROUPED UNAVAILABLE SLOTS -->
|
<!-- Grouped Time Slots Grid - ORIGINAL STYLING BUT WITH GROUPED UNAVAILABLE SLOTS -->
|
||||||
<div class="grid gap-2">
|
<div class="grid gap-2">
|
||||||
{#each groupedTimeSlots as slot (slot.startTime)}
|
{#each groupedTimeSlots as slot (slot.startTime)}
|
||||||
|
|||||||
@@ -327,14 +327,19 @@ INSERT INTO business_settings (
|
|||||||
'Crussell Nail Art Studio',
|
'Crussell Nail Art Studio',
|
||||||
'Address',
|
'Address',
|
||||||
'+44 131 123 4567',
|
'+44 131 123 4567',
|
||||||
'Email',
|
'crussellnails@gmail.com',
|
||||||
NULL, -- Set this when you register for VAT
|
NULL, -- Set this when we register for VAT
|
||||||
FALSE, -- Set to TRUE when you register for VAT
|
FALSE, -- Set to TRUE when we register for VAT
|
||||||
20.00,
|
20.00,
|
||||||
'GBP',
|
'GBP',
|
||||||
'https://www.website.co.uk'
|
'https://www.website.co.uk'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_payments_booking_id_status ON payments(booking_id, status);
|
||||||
|
CREATE INDEX idx_bookings_start_time_status ON bookings(start_time, status);
|
||||||
|
CREATE INDEX idx_users_created_at ON users(created_at);
|
||||||
|
CREATE INDEX idx_payments_created_at_status ON payments(created_at, status);
|
||||||
|
|
||||||
-- =======================================
|
-- =======================================
|
||||||
-- GDPR COMPLIANCE FUNCTIONS
|
-- GDPR COMPLIANCE FUNCTIONS
|
||||||
-- =======================================
|
-- =======================================
|
||||||
@@ -425,7 +430,7 @@ BEGIN
|
|||||||
'account_role', account_role,
|
'account_role', account_role,
|
||||||
'loyalty_stamps', loyalty_stamps,
|
'loyalty_stamps', loyalty_stamps,
|
||||||
'data_retention_consent', data_retention_consent,
|
'data_retention_consent', data_retention_consent,
|
||||||
'data_consent_updated_at', consent_updated_at,
|
'data_consent_updated_at', data_consent_updated_at,
|
||||||
'created_at', created_at,
|
'created_at', created_at,
|
||||||
'updated_at', updated_at
|
'updated_at', updated_at
|
||||||
)
|
)
|
||||||
@@ -528,14 +533,26 @@ BEGIN
|
|||||||
COALESCE(SUM(p.amount), 0) as total_sales,
|
COALESCE(SUM(p.amount), 0) as total_sales,
|
||||||
COALESCE(SUM(
|
COALESCE(SUM(
|
||||||
CASE
|
CASE
|
||||||
WHEN p.vat_rate IS NOT NULL THEN p.vat_amount
|
-- If VAT is explicitly stored, use it
|
||||||
ELSE ROUND(p.amount - (p.amount / (1 + COALESCE(p.vat_rate, 20.00)/100)), 2)
|
WHEN p.vat_amount IS NOT NULL THEN p.vat_amount
|
||||||
|
-- If business is VAT registered but no VAT breakdown, calculate it
|
||||||
|
WHEN (SELECT is_vat_registered FROM business_settings WHERE id = 1) THEN
|
||||||
|
ROUND(p.amount - (p.amount / (1 + COALESCE(p.vat_rate,
|
||||||
|
(SELECT default_vat_rate FROM business_settings WHERE id = 1))/100)), 2)
|
||||||
|
-- Business not VAT registered = no VAT charged
|
||||||
|
ELSE 0
|
||||||
END
|
END
|
||||||
), 0) as total_vat_charged,
|
), 0) as total_vat_charged,
|
||||||
COALESCE(SUM(
|
COALESCE(SUM(
|
||||||
CASE
|
CASE
|
||||||
|
-- If net amount is explicitly stored, use it
|
||||||
WHEN p.net_amount IS NOT NULL THEN p.net_amount
|
WHEN p.net_amount IS NOT NULL THEN p.net_amount
|
||||||
ELSE ROUND(p.amount / 1.20, 2) -- Calculate net if not stored
|
-- If business is VAT registered but no net amount, calculate it
|
||||||
|
WHEN (SELECT is_vat_registered FROM business_settings WHERE id = 1) THEN
|
||||||
|
ROUND(p.amount / (1 + COALESCE(p.vat_rate,
|
||||||
|
(SELECT default_vat_rate FROM business_settings WHERE id = 1))/100), 2)
|
||||||
|
-- Business not VAT registered = gross amount is net amount
|
||||||
|
ELSE p.amount
|
||||||
END
|
END
|
||||||
), 0) as net_sales,
|
), 0) as net_sales,
|
||||||
COUNT(*) as transaction_count
|
COUNT(*) as transaction_count
|
||||||
@@ -543,7 +560,7 @@ BEGIN
|
|||||||
JOIN bookings b ON p.booking_id = b.id
|
JOIN bookings b ON p.booking_id = b.id
|
||||||
WHERE p.status = 'completed'
|
WHERE p.status = 'completed'
|
||||||
AND p.created_at::date BETWEEN start_date AND end_date
|
AND p.created_at::date BETWEEN start_date AND end_date
|
||||||
AND p.payment_type IN ('full', 'partial', 'balance'); -- Exclude deposits and tips for main sales
|
AND p.payment_type IN ('full', 'partial', 'balance');
|
||||||
END;
|
END;
|
||||||
$$ LANGUAGE plpgsql;
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
@@ -690,7 +707,7 @@ $$ LANGUAGE plpgsql;
|
|||||||
-- WHY: When crossing £90k threshold, must register for VAT and backfill existing data
|
-- WHY: When crossing £90k threshold, must register for VAT and backfill existing data
|
||||||
-- WHEN: One-time use when VAT registration becomes mandatory
|
-- WHEN: One-time use when VAT registration becomes mandatory
|
||||||
-- OUTPUT: Updates all historical payments with VAT breakdown + sets new defaults
|
-- OUTPUT: Updates all historical payments with VAT breakdown + sets new defaults
|
||||||
-- USE: Call once when you register for VAT - transforms business from non-VAT to VAT
|
-- USE: Call once when we register for VAT - transforms business from non-VAT to VAT
|
||||||
-- =======================================
|
-- =======================================
|
||||||
-- UTILITY FUNCTIONS
|
-- UTILITY FUNCTIONS
|
||||||
-- =======================================
|
-- =======================================
|
||||||
@@ -699,7 +716,7 @@ $$ LANGUAGE plpgsql;
|
|||||||
-- WHY: When crossing £90k threshold, must register for VAT and backfill existing data
|
-- WHY: When crossing £90k threshold, must register for VAT and backfill existing data
|
||||||
-- WHEN: One-time use when VAT registration becomes mandatory
|
-- WHEN: One-time use when VAT registration becomes mandatory
|
||||||
-- OUTPUT: Updates all historical payments with VAT breakdown + sets new defaults
|
-- OUTPUT: Updates all historical payments with VAT breakdown + sets new defaults
|
||||||
-- USE: Call once when you register for VAT - transforms business from non-VAT to VAT
|
-- USE: Call once when we register for VAT - transforms business from non-VAT to VAT
|
||||||
CREATE OR REPLACE FUNCTION enable_vat_registration(
|
CREATE OR REPLACE FUNCTION enable_vat_registration(
|
||||||
registration_date DATE DEFAULT CURRENT_DATE,
|
registration_date DATE DEFAULT CURRENT_DATE,
|
||||||
vat_rate NUMERIC(5,2) DEFAULT 20.00,
|
vat_rate NUMERIC(5,2) DEFAULT 20.00,
|
||||||
@@ -1022,7 +1039,7 @@ $$ LANGUAGE plpgsql;
|
|||||||
-- =======================================
|
-- =======================================
|
||||||
/*
|
/*
|
||||||
This summary organizes all database functions by their primary purpose, legal basis, and expected usage frequency—
|
This summary organizes all database functions by their primary purpose, legal basis, and expected usage frequency—
|
||||||
providing a clear guide for integration into your application, compliance workflows, and business operations.
|
providing a clear guide for integration into our application, compliance workflows, and business operations.
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
1. FINANCIAL & TAX COMPLIANCE
|
1. FINANCIAL & TAX COMPLIANCE
|
||||||
|
|||||||
Reference in New Issue
Block a user