import { addDays, format, getDay } from 'date-fns' export interface RoomCategory { id: string name: string color: string // tailwind bg class textColor: string // tailwind text class basePrice: number extraPersonPrice: number maxPersons: number } export interface ChannelRate { channelId: string price: number // цена для этого канала } export interface PriceCell { price: number extraPerson: number minNights: number channelPrices: Record // channelId -> price closed: boolean // закрыто для продажи fromPeriod?: boolean // цена из ценового периода periodName?: string // название периода } export interface RatePeriod { id: string name: string startDate: string endDate: string notes?: string categoryPrices: Record // categoryId -> price channelMarkup: Record // channelId -> multiplier (1.15 = +15%) extraPersonPrice: number minNights: number daysOfWeek?: number[] // если задано — применяется только для этих дней (0=вс,1=пн...) } export const RATE_CHANNELS = [ { id: 'direct', name: 'Прямые', icon: '🏨', color: 'text-brand-600' }, { id: 'booking_com', name: 'Booking.com', icon: '🔵', color: 'text-blue-600' }, { id: 'airbnb', name: 'Airbnb', icon: '🔴', color: 'text-rose-600' }, { id: 'expedia', name: 'Expedia', icon: '🟡', color: 'text-amber-600' }, ] export const ROOM_CATEGORIES: RoomCategory[] = [ { id: 'standard', name: 'Стандарт', color: 'bg-slate-500', textColor: 'text-slate-600', basePrice: 3500, extraPersonPrice: 800, maxPersons: 2 }, { id: 'deluxe', name: 'Делюкс', color: 'bg-brand-500', textColor: 'text-brand-600', basePrice: 5200, extraPersonPrice: 1000, maxPersons: 3 }, { id: 'suite', name: 'Сюит', color: 'bg-violet-500', textColor: 'text-violet-600', basePrice: 8900, extraPersonPrice: 1500, maxPersons: 4 }, { id: 'junior_suite', name: 'Джуниор Сюит', color: 'bg-cyan-500', textColor: 'text-cyan-600', basePrice: 6800, extraPersonPrice: 1200, maxPersons: 4 }, { id: 'penthouse', name: 'Пентхаус', color: 'bg-amber-500', textColor: 'text-amber-600', basePrice: 18000, extraPersonPrice: 2500, maxPersons: 6 }, ] // Дефолтные мультипликаторы каналов (markup к базовой цене) export const DEFAULT_CHANNEL_MARKUP: Record = { direct: 1.00, booking_com: 1.00, // net price — Booking забирает свою комиссию сверху airbnb: 1.05, expedia: 1.03, } // Генерируем начальную сетку цен на 60 дней export function buildInitialPriceGrid(): Record> { const result: Record> = {} const today = new Date() for (const cat of ROOM_CATEGORIES) { result[cat.id] = {} for (let i = 0; i < 60; i++) { const d = addDays(today, i) const dateStr = format(d, 'yyyy-MM-dd') const dow = getDay(d) const isWeekend = dow === 5 || dow === 6 const basePrice = Math.round(cat.basePrice * (isWeekend ? 1.25 : 1.0)) const channelPrices: Record = {} for (const ch of RATE_CHANNELS) { channelPrices[ch.id] = Math.round(basePrice * DEFAULT_CHANNEL_MARKUP[ch.id]) } result[cat.id][dateStr] = { price: basePrice, extraPerson: cat.extraPersonPrice, minNights: 1, channelPrices, closed: false, } } } return result } // Демо-периоды export const DEMO_PERIODS: RatePeriod[] = [ { id: 'p1', name: 'Праздники 8 марта', startDate: '2026-03-06', endDate: '2026-03-10', categoryPrices: { standard: 4500, deluxe: 6500, suite: 11000, junior_suite: 8500, penthouse: 22000 }, channelMarkup: { direct: 1.0, booking_com: 1.0, airbnb: 1.05, expedia: 1.03 }, extraPersonPrice: 1200, minNights: 2, notes: 'Повышенный спрос на праздники', }, { id: 'p2', name: 'Майские праздники', startDate: '2026-04-30', endDate: '2026-05-10', categoryPrices: { standard: 5000, deluxe: 7200, suite: 12500, junior_suite: 9800, penthouse: 25000 }, channelMarkup: { direct: 1.0, booking_com: 1.0, airbnb: 1.08, expedia: 1.05 }, extraPersonPrice: 1500, minNights: 3, notes: 'Минимальный заезд 3 ночи', }, ]