Refactor to generic ERP base

Remove influencer-specific features (campaigns, TikTok, gifts, shadow ledger,
contracts, briefings) and consolidate into a clean ERP foundation with core
bookkeeping, invoicing, receipts, tax reporting, and calendar functionality.
Reorganize database migrations into a clean numbered sequence.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-02-13 15:39:13 +01:00
co-authored by Claude Opus 4.6
parent a25d10a528
commit 0aecf5b41c
184 changed files with 1418 additions and 24763 deletions
+3 -26
View File
@@ -61,9 +61,9 @@ export async function GET(
const endStr = endDate.toISOString().split('T')[0]
// Fetch relevant data based on feed options
const [deadlinesResult, invoicesResult, campaignsResult, exclusivitiesResult] = await Promise.all([
const [deadlinesResult, invoicesResult] = await Promise.all([
// Deadlines
(feed.include_tax_deadlines || feed.include_campaigns)
feed.include_tax_deadlines
? supabase
.from('deadlines')
.select('*')
@@ -83,25 +83,6 @@ export async function GET(
.lte('due_date', endStr)
.order('due_date')
: { data: [] },
// Campaigns with deliverables
feed.include_campaigns
? supabase
.from('campaigns')
.select('*, deliverables(*)')
.eq('user_id', feed.user_id)
.in('status', ['active', 'contracted', 'delivered'])
: { data: [] },
// Exclusivities
feed.include_exclusivity
? supabase
.from('exclusivities')
.select('*, campaign:campaigns(name)')
.eq('user_id', feed.user_id)
.gte('end_date', startStr)
.lte('start_date', endStr)
: { data: [] },
])
try {
@@ -109,21 +90,17 @@ export async function GET(
{
deadlines: deadlinesResult.data || [],
invoices: invoicesResult.data || [],
campaigns: campaignsResult.data || [],
exclusivities: exclusivitiesResult.data || [],
},
{
includeTaxDeadlines: feed.include_tax_deadlines,
includeInvoices: feed.include_invoices,
includeCampaigns: feed.include_campaigns,
includeExclusivity: feed.include_exclusivity,
}
)
return new NextResponse(icsContent, {
headers: {
'Content-Type': 'text/calendar; charset=utf-8',
'Content-Disposition': 'attachment; filename="influencer-biz.ics"',
'Content-Disposition': 'attachment; filename="erp-base.ics"',
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache',
'Expires': '0',
+4 -6
View File
@@ -27,7 +27,7 @@ export async function GET() {
}
// Generate the feed URL
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://app.influencer-biz.se'
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://app.erp-base.se'
if (feed) {
return NextResponse.json({
@@ -79,8 +79,6 @@ export async function POST() {
is_active: true,
include_tax_deadlines: true,
include_invoices: true,
include_campaigns: true,
include_exclusivity: false, // Avstängt som standard
})
.select()
.single()
@@ -89,7 +87,7 @@ export async function POST() {
return NextResponse.json({ error: error.message }, { status: 500 })
}
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://app.influencer-biz.se'
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://app.erp-base.se'
return NextResponse.json({
data: {
@@ -126,7 +124,7 @@ export async function PUT(request: Request) {
return NextResponse.json({ error: error.message }, { status: 500 })
}
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://app.influencer-biz.se'
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://app.erp-base.se'
return NextResponse.json({
data: {
@@ -166,7 +164,7 @@ export async function DELETE() {
return NextResponse.json({ error: error.message }, { status: 500 })
}
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://app.influencer-biz.se'
const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://app.erp-base.se'
return NextResponse.json({
data: {