SELECT
v.id AS voyageId,
s.name AS shipName,
CONCAT(DATE_FORMAT(v.boarding_time, '%Y-%m-%d'), ' ', CASE WHEN r.direction = 1 THEN '上水' ELSE '下水' END) AS voyageInfo,
GREATEST(DATEDIFF(DATE(v.boarding_time), CURDATE()), 0) AS countdown,
528 AS capacity,
COALESCE(room_stats.totalRooms, 0) AS totalRooms,
COALESCE(room_stats.paidRooms, 0) AS paidRooms,
COALESCE(room_stats.reservedRooms, 0) AS reservedRooms,
COALESCE(visitor_stats.totalPassengers, 0) AS totalPassengers,
COALESCE(visitor_stats.ticketedPassengers, 0) AS ticketedPassengers,
COALESCE(free_stats.freePassengers, 0) AS freePassengers,
COALESCE(estimated_stats.estimatedPassengers, 0) AS estimatedPassengers,
COALESCE(finance_stats.receivableAmount, 0) AS receivableAmount,
COALESCE(finance_stats.receivedAmount, 0) AS receivedAmount,
COALESCE(finance_stats.receivableAmount, 0) - COALESCE(finance_stats.receivedAmount, 0) AS unreceivedAmount,
CASE WHEN COALESCE(visitor_stats.ticketedPassengers, 0) > 0
THEN ROUND(COALESCE(finance_stats.receivableAmount, 0) / visitor_stats.ticketedPassengers, 2)
ELSE 0 END AS avgPrice,
COALESCE(visitor_stats.adultCount, 0) AS adultCount,
COALESCE(visitor_stats.childCount, 0) AS childCount,
COALESCE(visitor_stats.infantCount, 0) AS infantCount,
COALESCE(visitor_stats.companionLeaderCount, 0) AS companionLeaderCount,
COALESCE(team_stats.groupCount, 0) AS groupCount,
COALESCE(team_stats.individualCount, 0) AS individualCount,
COALESCE(nationality_stats.domesticCount, 0) AS domesticCount,
COALESCE(nationality_stats.overseasCount, 0) AS overseasCount
FROM product_voyage v
INNER JOIN resource_ship s ON v.ship_id = s.id AND s.deleted = 0
INNER JOIN resource_route r ON v.route_id = r.id AND r.deleted = 0
LEFT JOIN (
SELECT
o.voyage_id,
SUM(COALESCE(tot.use_room_num, 0)) AS totalRooms,
SUM(CASE WHEN o.order_status = 1 or o.order_status = 6 THEN COALESCE(tot.use_room_num, 0) ELSE 0 END) AS paidRooms,
SUM(CASE WHEN o.order_status = 14 THEN COALESCE(tot.use_room_num, 0) ELSE 0 END) AS reservedRooms
FROM trade_order_room_model tot
LEFT JOIN trade_order o ON o.id = tot.order_id AND tot.deleted = 0
WHERE o.deleted = 0 AND o.order_status IN (14,6,1)
GROUP BY o.voyage_id
) room_stats ON v.id = room_stats.voyage_id
LEFT JOIN (
SELECT
o.voyage_id,
COUNT(tv.id) AS totalPassengers,
SUM(CASE WHEN o.order_status IN (6) THEN 1 ELSE 0 END) AS ticketedPassengers,
SUM(CASE WHEN tv.type IN ('adultTake', 'adultPlus') THEN 1 ELSE 0 END) AS adultCount,
SUM(CASE WHEN tv.type IN ('childTake', 'childPlus', 'childNonTake') THEN 1 ELSE 0 END) AS childCount,
SUM(CASE WHEN tv.type IN ('babyTake', 'babyPlus', 'babyNonTake') THEN 1 ELSE 0 END) AS infantCount,
SUM(CASE WHEN tv.type IN ('with', 'leader') THEN 1 ELSE 0 END) AS companionLeaderCount
FROM trade_order o
INNER JOIN trade_visitor tv ON o.id = tv.order_id AND tv.deleted = 0
WHERE o.deleted = 0 AND o.order_status IN (15, 13, 10, 12, 9, 8, 7, 6, 5, 4, 3, 1, 0)
GROUP BY o.voyage_id
) visitor_stats ON v.id = visitor_stats.voyage_id
LEFT JOIN (
SELECT
o.voyage_id,
CASE WHEN o.order_status = 1 or o.order_status = 14 THEN SUM(COALESCE(tot.adult_total_num, 0) + COALESCE(tot.child_total_num, 0)
+ COALESCE(tot.baby_total_num, 0) + COALESCE(tot.with_total_num, 0)
+ COALESCE(tot.leader_total_num, 0)) ELSE 0 END AS estimatedPassengers
FROM trade_order o
LEFT JOIN trade_order_total tot ON o.id = tot.old_order_id AND tot.deleted = 0
WHERE o.deleted = 0 AND o.order_status IN (15, 14, 13, 10, 12, 9, 8, 7, 6, 5, 4, 3, 1, 0)
GROUP BY o.voyage_id
) estimated_stats ON v.id = estimated_stats.voyage_id
LEFT JOIN (
SELECT
o.voyage_id,
SUM(CASE WHEN od.name LIKE '免票%' THEN 1 ELSE 0 END) AS freePassengers
FROM trade_order o
INNER JOIN trade_visitor tv ON o.id = tv.order_id AND tv.deleted = 0
LEFT JOIN ota_distributor od ON o.source_id = od.id AND od.deleted = 0
WHERE o.deleted = 0 AND o.order_status IN (15, 14, 13, 10, 12, 9, 8, 7, 6, 5, 4, 3, 1, 0)
GROUP BY o.voyage_id
) free_stats ON v.id = free_stats.voyage_id
LEFT JOIN (
SELECT
o.voyage_id,
SUM(o.pay_amount) AS receivableAmount,
SUM(CASE WHEN o.pay_status = 1 THEN COALESCE(p.pay_amount, o.real_pay_amount)
ELSE COALESCE(o.real_pay_amount, 0) END) AS receivedAmount
FROM trade_order o
LEFT JOIN (
SELECT order_id, SUM(pay_amount) AS pay_amount
FROM trade_order_pay
WHERE deleted = 0 AND pay_status = 1
GROUP BY order_id
) p ON o.pay_status = 1 AND p.order_id = o.id
WHERE o.deleted = 0 AND o.order_status IN (15, 14, 13, 10, 12, 9, 8, 7, 6, 5, 4, 3, 1, 0)
GROUP BY o.voyage_id
) finance_stats ON v.id = finance_stats.voyage_id
LEFT JOIN (
SELECT
o.voyage_id,
SUM(CASE WHEN visitor_cnt.cnt >= 10 THEN visitor_cnt.cnt ELSE 0 END) AS groupCount,
SUM(CASE WHEN visitor_cnt.cnt < 10 THEN visitor_cnt.cnt ELSE 0 END) AS individualCount
FROM trade_order o
INNER JOIN (
SELECT order_id, COUNT(id) AS cnt
FROM trade_visitor
WHERE deleted = 0
GROUP BY order_id
) visitor_cnt ON o.id = visitor_cnt.order_id
WHERE o.deleted = 0 AND o.order_status IN (15, 13, 10, 12, 9, 8, 7, 6, 5, 4, 3, 1, 0)
GROUP BY o.voyage_id
) team_stats ON v.id = team_stats.voyage_id
LEFT JOIN (
SELECT
o.voyage_id,
SUM(CASE WHEN tv.nationality = '1' OR tv.nationality IS NULL OR tv.nationality = '' THEN 1 ELSE 0 END) AS domesticCount,
SUM(CASE WHEN tv.nationality != '1' AND tv.nationality IS NOT NULL AND tv.nationality != '' THEN 1 ELSE 0 END) AS overseasCount
FROM trade_order o
INNER JOIN trade_visitor tv ON o.id = tv.order_id AND tv.deleted = 0
WHERE o.deleted = 0 AND o.order_status IN (15, 13, 10, 12, 9, 8, 7, 6, 5, 4, 3, 1, 0)
GROUP BY o.voyage_id
) nationality_stats ON v.id = nationality_stats.voyage_id
WHERE v.deleted = 0
AND v.id IN
#{id}
AND v.ship_id = #{vo.shipId}
AND v.start_time >= #{vo.startDate}
AND v.start_time < DATE_ADD(#{vo.endDate}, INTERVAL 1 DAY)
ORDER BY v.start_time ASC, s.name ASC