Add January 2026 sales data import scripts
- process_daily_sales.py: Parse XLS sales reports and extract museum-by-museum data - january_2026_data.csv: Verified data for all 31 days, 4 museums (124 records) Data imported to NocoDB DailyStats table: - Qur'an Museum: 8,493 visits, 196,450 SAR - Revelation Museum: 68,449 visits, 1,637,290 SAR - Creation Story Museum: 32,926 visits, 697,225 SAR - The Best Of Creation: 15,110 visits, 263,783 SAR - Total: 124,978 visits, 2,794,748 SAR
This commit is contained in:
125
scripts/january_2026_data.csv
Normal file
125
scripts/january_2026_data.csv
Normal file
@@ -0,0 +1,125 @@
|
||||
date,museum,tickets,visits,revenue
|
||||
2026-01-01,Creation Story Museum,256,728,12877.00
|
||||
2026-01-01,Qur'an Museum,69,235,4355.00
|
||||
2026-01-01,Revelation Museum,549,2664,59313.00
|
||||
2026-01-01,The Best Of Creation,292,925,13927.00
|
||||
2026-01-02,Creation Story Museum,401,1241,24963.00
|
||||
2026-01-02,Qur'an Museum,67,181,4230.00
|
||||
2026-01-02,Revelation Museum,405,2183,50563.00
|
||||
2026-01-02,The Best Of Creation,185,616,8965.00
|
||||
2026-01-03,Creation Story Museum,413,1268,28280.00
|
||||
2026-01-03,Qur'an Museum,82,268,5265.00
|
||||
2026-01-03,Revelation Museum,500,2776,61780.00
|
||||
2026-01-03,The Best Of Creation,152,439,6880.00
|
||||
2026-01-04,Creation Story Museum,376,1157,24740.00
|
||||
2026-01-04,Qur'an Museum,112,312,7445.00
|
||||
2026-01-04,Revelation Museum,395,1991,41950.00
|
||||
2026-01-04,The Best Of Creation,105,323,4925.00
|
||||
2026-01-05,Creation Story Museum,318,952,20115.00
|
||||
2026-01-05,Qur'an Museum,82,604,13745.00
|
||||
2026-01-05,Revelation Museum,1661,3810,80080.00
|
||||
2026-01-05,The Best Of Creation,101,306,4810.00
|
||||
2026-01-06,Creation Story Museum,337,940,21421.00
|
||||
2026-01-06,Qur'an Museum,51,216,5045.00
|
||||
2026-01-06,Revelation Museum,278,2079,49440.00
|
||||
2026-01-06,The Best Of Creation,120,440,6750.00
|
||||
2026-01-07,Creation Story Museum,282,874,18657.00
|
||||
2026-01-07,Qur'an Museum,72,335,6990.00
|
||||
2026-01-07,Revelation Museum,284,1719,40995.00
|
||||
2026-01-07,The Best Of Creation,91,322,4830.00
|
||||
2026-01-08,Creation Story Museum,293,1009,22224.00
|
||||
2026-01-08,Qur'an Museum,73,410,8745.00
|
||||
2026-01-08,Revelation Museum,281,1841,45235.00
|
||||
2026-01-08,The Best Of Creation,170,529,8710.00
|
||||
2026-01-09,Creation Story Museum,324,1043,23915.00
|
||||
2026-01-09,Qur'an Museum,69,186,4835.00
|
||||
2026-01-09,Revelation Museum,344,1828,48225.00
|
||||
2026-01-09,The Best Of Creation,134,365,7485.00
|
||||
2026-01-10,Creation Story Museum,434,1598,33565.00
|
||||
2026-01-10,Qur'an Museum,107,396,9535.00
|
||||
2026-01-10,Revelation Museum,477,2737,70395.00
|
||||
2026-01-10,The Best Of Creation,237,602,11420.00
|
||||
2026-01-11,Creation Story Museum,506,1965,41442.00
|
||||
2026-01-11,Qur'an Museum,70,263,6735.00
|
||||
2026-01-11,Revelation Museum,533,2461,64686.00
|
||||
2026-01-11,The Best Of Creation,189,545,9940.00
|
||||
2026-01-12,Creation Story Museum,422,1657,34818.00
|
||||
2026-01-12,Qur'an Museum,83,323,7760.00
|
||||
2026-01-12,Revelation Museum,451,2019,53355.00
|
||||
2026-01-12,The Best Of Creation,177,534,10085.00
|
||||
2026-01-13,Creation Story Museum,481,1649,35934.00
|
||||
2026-01-13,Qur'an Museum,86,267,6295.00
|
||||
2026-01-13,Revelation Museum,408,2327,63150.00
|
||||
2026-01-13,The Best Of Creation,248,659,13414.00
|
||||
2026-01-14,Creation Story Museum,396,1397,31577.00
|
||||
2026-01-14,Qur'an Museum,85,299,7540.00
|
||||
2026-01-14,Revelation Museum,401,2508,63345.00
|
||||
2026-01-14,The Best Of Creation,236,595,12050.00
|
||||
2026-01-15,Creation Story Museum,408,1553,31680.00
|
||||
2026-01-15,Qur'an Museum,73,242,6120.00
|
||||
2026-01-15,Revelation Museum,531,2388,63245.00
|
||||
2026-01-15,The Best Of Creation,192,493,9805.00
|
||||
2026-01-16,Creation Story Museum,312,1202,26025.00
|
||||
2026-01-16,Qur'an Museum,85,299,7305.00
|
||||
2026-01-16,Revelation Museum,349,1863,45220.00
|
||||
2026-01-16,The Best Of Creation,215,615,11500.00
|
||||
2026-01-17,Creation Story Museum,297,1060,23257.00
|
||||
2026-01-17,Qur'an Museum,74,415,9290.00
|
||||
2026-01-17,Revelation Museum,349,3043,70793.00
|
||||
2026-01-17,The Best Of Creation,173,449,9262.00
|
||||
2026-01-18,Creation Story Museum,258,1023,21150.00
|
||||
2026-01-18,Qur'an Museum,60,259,5785.00
|
||||
2026-01-18,Revelation Museum,285,2366,54595.00
|
||||
2026-01-18,The Best Of Creation,215,539,10760.00
|
||||
2026-01-19,Creation Story Museum,280,1151,22505.00
|
||||
2026-01-19,Qur'an Museum,51,214,4740.00
|
||||
2026-01-19,Revelation Museum,274,2444,56395.00
|
||||
2026-01-19,The Best Of Creation,153,359,7265.00
|
||||
2026-01-20,Creation Story Museum,244,1115,22240.00
|
||||
2026-01-20,Qur'an Museum,55,211,4705.00
|
||||
2026-01-20,Revelation Museum,283,2472,56465.00
|
||||
2026-01-20,The Best Of Creation,162,407,7705.00
|
||||
2026-01-21,Creation Story Museum,223,774,16140.00
|
||||
2026-01-21,Qur'an Museum,67,474,10685.00
|
||||
2026-01-21,Revelation Museum,305,1869,44860.00
|
||||
2026-01-21,The Best Of Creation,218,526,8950.00
|
||||
2026-01-22,Creation Story Museum,266,938,19725.00
|
||||
2026-01-22,Qur'an Museum,61,247,6150.00
|
||||
2026-01-22,Revelation Museum,306,2017,51030.00
|
||||
2026-01-22,The Best Of Creation,168,475,8115.00
|
||||
2026-01-23,Creation Story Museum,212,727,15570.00
|
||||
2026-01-23,Qur'an Museum,44,175,4135.00
|
||||
2026-01-23,Revelation Museum,285,1589,39230.00
|
||||
2026-01-23,The Best Of Creation,229,542,8975.00
|
||||
2026-01-24,Creation Story Museum,214,838,16790.00
|
||||
2026-01-24,Qur'an Museum,82,255,6245.00
|
||||
2026-01-24,Revelation Museum,298,2660,61080.00
|
||||
2026-01-24,The Best Of Creation,240,512,8471.00
|
||||
2026-01-25,Creation Story Museum,200,828,16835.00
|
||||
2026-01-25,Qur'an Museum,42,222,4575.00
|
||||
2026-01-25,Revelation Museum,271,1841,42145.00
|
||||
2026-01-25,The Best Of Creation,165,361,6000.00
|
||||
2026-01-26,Creation Story Museum,194,619,13460.00
|
||||
2026-01-26,Qur'an Museum,52,273,6285.00
|
||||
2026-01-26,Revelation Museum,234,1989,40905.00
|
||||
2026-01-26,The Best Of Creation,140,337,5840.00
|
||||
2026-01-27,Creation Story Museum,259,725,15800.00
|
||||
2026-01-27,Qur'an Museum,85,251,5710.00
|
||||
2026-01-27,Revelation Museum,298,1742,44715.00
|
||||
2026-01-27,The Best Of Creation,161,391,6245.00
|
||||
2026-01-28,Creation Story Museum,193,615,13185.00
|
||||
2026-01-28,Qur'an Museum,57,171,3945.00
|
||||
2026-01-28,Revelation Museum,280,2006,46285.00
|
||||
2026-01-28,The Best Of Creation,152,465,7535.00
|
||||
2026-01-29,Creation Story Museum,235,640,14645.00
|
||||
2026-01-29,Qur'an Museum,56,204,4750.00
|
||||
2026-01-29,Revelation Museum,286,1943,48755.00
|
||||
2026-01-29,The Best Of Creation,153,468,7808.00
|
||||
2026-01-30,Creation Story Museum,218,672,15010.00
|
||||
2026-01-30,Qur'an Museum,56,129,3365.00
|
||||
2026-01-30,Revelation Museum,279,1670,39850.00
|
||||
2026-01-30,The Best Of Creation,231,609,9473.00
|
||||
2026-01-31,Creation Story Museum,242,968,18680.00
|
||||
2026-01-31,Qur'an Museum,62,157,4140.00
|
||||
2026-01-31,Revelation Museum,275,1604,39210.00
|
||||
2026-01-31,The Best Of Creation,134,362,5882.50
|
||||
|
101
scripts/process_daily_sales.py
Normal file
101
scripts/process_daily_sales.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import csv
|
||||
import os
|
||||
import re
|
||||
from collections import defaultdict
|
||||
|
||||
folder = '/tmp/jan2026_csv/'
|
||||
|
||||
# Museum name mapping - order matters! Check more specific patterns first
|
||||
def get_museum(ticket_name):
|
||||
# Some tickets have both "الوحي" and "القرآن" - prioritize based on actual content
|
||||
# Pattern: "معرض الوحي | متحف القرآن الكريم" = Revelation Exhibition ticket (القرآن is just venue)
|
||||
|
||||
ticket_lower = ticket_name.lower()
|
||||
|
||||
# Check Revelation first (الوحي or revelation) - this takes priority
|
||||
if 'الوحي' in ticket_name or 'revelation' in ticket_lower:
|
||||
return "Revelation Museum"
|
||||
|
||||
# Then Qur'an (only if الوحي not present)
|
||||
if 'holy qur' in ticket_lower or 'quraan' in ticket_lower or 'quran' in ticket_lower or 'القرآن' in ticket_name:
|
||||
return "Qur'an Museum"
|
||||
|
||||
# Best of Creation
|
||||
if 'best of creation' in ticket_lower or 'خير الخلق' in ticket_name:
|
||||
return "The Best Of Creation"
|
||||
|
||||
# Creation Story
|
||||
if 'creation story' in ticket_lower or 'قصة الخلق' in ticket_name:
|
||||
return "Creation Story Museum"
|
||||
|
||||
return None
|
||||
|
||||
results = []
|
||||
|
||||
for filename in os.listdir(folder):
|
||||
if not filename.endswith('.csv'):
|
||||
continue
|
||||
|
||||
filepath = os.path.join(folder, filename)
|
||||
|
||||
with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
# Extract date from line 5
|
||||
date_match = re.search(r'(\d+/\d+/\d+)', lines[4] if len(lines) > 4 else '')
|
||||
if not date_match:
|
||||
continue
|
||||
date_str = date_match.group(1)
|
||||
|
||||
# Parse as m/d/yyyy and convert to yyyy-mm-dd
|
||||
parts = date_str.split('/')
|
||||
date_iso = f"{parts[2]}-{int(parts[0]):02d}-{int(parts[1]):02d}"
|
||||
|
||||
# Daily aggregation by museum
|
||||
daily = defaultdict(lambda: {'tickets': 0, 'visits': 0, 'revenue': 0.0})
|
||||
|
||||
# Parse CSV rows
|
||||
reader = csv.reader(lines)
|
||||
rows = list(reader)
|
||||
|
||||
for row in rows:
|
||||
if len(row) < 6:
|
||||
continue
|
||||
|
||||
# Check if this is a ticket row (has site name and ticket name)
|
||||
site_name = row[0].strip() if row[0] else ''
|
||||
if 'Hiraa' not in site_name and 'Safiyyah' not in site_name:
|
||||
continue
|
||||
|
||||
ticket_name = row[2].strip() if len(row) > 2 else ''
|
||||
museum = get_museum(ticket_name)
|
||||
if not museum:
|
||||
continue
|
||||
|
||||
try:
|
||||
quantity = int(row[3].replace(',', '')) if row[3].strip() else 0
|
||||
people = int(row[4].replace(',', '')) if row[4].strip() else 0
|
||||
gross_sale = float(row[5].replace(',', '')) if row[5].strip() else 0.0
|
||||
except (ValueError, IndexError):
|
||||
continue
|
||||
|
||||
daily[museum]['tickets'] += quantity
|
||||
daily[museum]['visits'] += people
|
||||
daily[museum]['revenue'] += gross_sale
|
||||
|
||||
for museum, data in daily.items():
|
||||
results.append({
|
||||
'date': date_iso,
|
||||
'museum': museum,
|
||||
'tickets': data['tickets'],
|
||||
'visits': data['visits'],
|
||||
'revenue': data['revenue']
|
||||
})
|
||||
|
||||
# Sort by date and museum
|
||||
results.sort(key=lambda x: (x['date'], x['museum']))
|
||||
|
||||
# Output as CSV
|
||||
print("date,museum,tickets,visits,revenue")
|
||||
for r in results:
|
||||
print(f"{r['date']},{r['museum']},{r['tickets']},{r['visits']},{r['revenue']:.2f}")
|
||||
Reference in New Issue
Block a user