2847 lines
50 KiB
JavaScript
2847 lines
50 KiB
JavaScript
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const db = require('../models');
|
|
const Users = db.users;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const PollutionReports = db.pollution_reports;
|
|
|
|
const EcoActionLogs = db.eco_action_logs;
|
|
|
|
const CommunityChallenges = db.community_challenges;
|
|
|
|
const ChallengeParticipations = db.challenge_participations;
|
|
|
|
const RewardTransactions = db.reward_transactions;
|
|
|
|
const RewardsCatalog = db.rewards_catalog;
|
|
|
|
const EducationArticles = db.education_articles;
|
|
|
|
const ClimateAlerts = db.climate_alerts;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const PollutionReportsData = [
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"pollution_type": "burning_waste",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"latitude": -26.3052,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"longitude": 31.1367,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"location_text": "Near Mbabane River footbridge",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"description": "Small pile of mixed household waste near the riverbank.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"status": "resolved",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"is_offline_draft": true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"occurred_at": new Date('2026-03-18T14:10:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"submitted_at": new Date('2026-03-18T14:20:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"pollution_type": "illegal_dumping",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"latitude": -26.4972,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"longitude": 31.3802,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"location_text": "Behind Manzini market parking area",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"description": "Smoke from burning plastic and paper observed in open area.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"status": "rejected",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"is_offline_draft": true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"occurred_at": new Date('2026-03-19T09:30:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"submitted_at": new Date('2026-03-19T09:41:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"pollution_type": "burning_waste",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"latitude": -26.4575,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"longitude": 31.9526,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"location_text": "Stream near Siteki community fields",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"description": "Oily sheen and litter visible along stream edge.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"status": "rejected",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"is_offline_draft": true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"occurred_at": new Date('2026-03-20T12:05:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"submitted_at": new Date('2026-03-21T08:15:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"pollution_type": "water_pollution",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"latitude": -26.5438,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"longitude": 31.1832,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"location_text": "Roadside near Malkerns junction",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"description": "Construction rubble dumped in drainage channel.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"status": "rejected",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"is_offline_draft": true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"occurred_at": new Date('2026-03-15T17:50:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"submitted_at": new Date('2026-03-15T18:05:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
const EcoActionLogsData = [
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"log_date": new Date('2026-03-21T00:00:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"transport_type": "car",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"energy_use": "electricity",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"waste_disposal_method": "proper_bin",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"transport_points": 18,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"energy_points": 30,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"waste_points": 25,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"total_points": 73,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"eco_score": 73.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"notes": "Used shared taxi and avoided single-use plastics.",
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"log_date": new Date('2026-03-21T00:00:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"transport_type": "taxi",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"energy_use": "wood",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"waste_disposal_method": "burning",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"transport_points": 30,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"energy_points": 30,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"waste_points": 35,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"total_points": 95,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"eco_score": 95.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"notes": "Walked to shops and separated recyclables.",
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"log_date": new Date('2026-03-20T00:00:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"transport_type": "walk",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"energy_use": "electricity",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"waste_disposal_method": "proper_bin",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"transport_points": 10,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"energy_points": 12,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"waste_points": 25,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"total_points": 47,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"eco_score": 47.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"notes": "Needed car for errands; reduced waste at home.",
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"log_date": new Date('2026-03-19T00:00:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"transport_type": "walk",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"energy_use": "charcoal",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"waste_disposal_method": "recycle",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"transport_points": 18,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"energy_points": 15,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"waste_points": 5,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"total_points": 38,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"eco_score": 38.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"notes": "Used wood for cooking and disposed waste by burning.",
|
|
|
|
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
const CommunityChallengesData = [
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "Plant 50 Trees in March",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"summary": "Community tree planting across neighborhoods to improve shade and reduce erosion.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"challenge_type": "reduce_waste",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"status": "upcoming",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"start_at": new Date('2026-03-01T00:00:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"end_at": new Date('2026-03-31T23:59:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points_per_completion": 40,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"max_completions_per_user": 3,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"rules": "Log each planting day with a photo and location if possible.",
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "Weekend Litter Cleanup",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"summary": "Join a weekend cleanup around markets and taxi ranks to reduce dumping.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"challenge_type": "clean_environment",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"status": "completed",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"start_at": new Date('2026-03-15T00:00:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"end_at": new Date('2026-04-15T23:59:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points_per_completion": 25,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"max_completions_per_user": 6,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"rules": "Work in groups where possible; report hotspots after cleanup.",
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "Reduce Waste at Home",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"summary": "Cut household waste by reusing containers and separating recyclables.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"challenge_type": "plant_trees",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"status": "completed",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"start_at": new Date('2026-04-01T00:00:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"end_at": new Date('2026-04-30T23:59:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points_per_completion": 20,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"max_completions_per_user": 10,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"rules": "Track actions weekly; share one tip with the community.",
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "School Yard Greening",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"summary": "Support local schools with small tree planting and cleanup activities.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"challenge_type": "clean_environment",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"status": "active",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"start_at": new Date('2026-02-01T00:00:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"end_at": new Date('2026-02-28T23:59:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points_per_completion": 35,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"max_completions_per_user": 2,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"rules": "Coordinate with school contact; prioritize indigenous trees.",
|
|
|
|
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
const ChallengeParticipationsData = [
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"participation_status": "left",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"progress_count": 2,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points_earned": 80,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"joined_at": new Date('2026-03-05T10:00:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"completed_at": new Date('2026-03-20T11:30:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"participation_status": "completed",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"progress_count": 4,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points_earned": 100,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"joined_at": new Date('2026-03-16T08:10:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"completed_at": new Date('2026-03-23T09:45:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"participation_status": "completed",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"progress_count": 1,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points_earned": 25,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"joined_at": new Date('2026-03-18T07:20:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"completed_at": new Date('2026-03-18T07:20:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"participation_status": "left",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"progress_count": 1,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points_earned": 35,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"joined_at": new Date('2026-02-10T12:00:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"completed_at": new Date('2026-02-20T13:05:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
const RewardTransactionsData = [
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"source_type": "challenge_completion",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points": 30,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"source_reference": "pollution_reports:1",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"note": "Points for verified report submission.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"earned_at": new Date('2026-03-18T14:25:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"source_type": "pollution_report",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points": 100,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"source_reference": "challenge_participations:2",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"note": "Completed Weekend Litter Cleanup milestones.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"earned_at": new Date('2026-03-23T10:00:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"source_type": "challenge_completion",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points": 80,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"source_reference": "challenge_participations:1",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"note": "Tree planting progress logged.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"earned_at": new Date('2026-03-20T12:00:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// type code here for "relation_one" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"source_type": "pollution_report",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points": 20,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"source_reference": "pollution_reports:3",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"note": "Submitted water pollution report (offline sync).",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"earned_at": new Date('2026-03-21T08:20:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
const RewardsCatalogData = [
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "Reusable Shopping Bag",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"description": "Durable bag to reduce single-use plastic usage.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points_cost": 120,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"availability_status": "limited",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"terms": "Limited to one per user per month.",
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "Tree Seedling Voucher",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"description": "Voucher redeemable for one indigenous tree seedling.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points_cost": 200,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"availability_status": "limited",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"terms": "Redeem at partner nursery locations while stock lasts.",
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "Water Bottle",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"description": "Refillable bottle to encourage reducing plastic waste.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points_cost": 180,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"availability_status": "limited",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"terms": "Colors may vary based on availability.",
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "Community Recognition Badge",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"description": "Digital badge displayed on your profile for consistent eco actions.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"points_cost": 75,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"availability_status": "limited",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"terms": "Badge is non-transferable and appears after redemption.",
|
|
|
|
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
const EducationArticlesData = [
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "Simple Ways to Reduce Household Waste",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"category": "soil_erosion_prevention",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"excerpt": "Small daily changes can significantly cut waste at home.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"content": "Start by separating recyclables, reusing containers, and choosing products with less packaging. Keep a small sorting area and set a weekly routine for disposal.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"publish_status": "draft",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"published_at": new Date('2026-03-10T08:00:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "Preventing Soil Erosion in Your Yard",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"category": "pollution_reduction",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"excerpt": "Protect soil with plants, mulch, and smart water flow control.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"content": "Plant ground cover, add mulch, and create gentle terraces on slopes. Direct runoff with small channels and avoid leaving bare soil exposed during heavy rains.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"publish_status": "published",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"published_at": new Date('2026-03-12T09:30:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "Climate Awareness: Heat Safety Tips",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"category": "pollution_reduction",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"excerpt": "Prepare for high heat with hydration and shade.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"content": "Drink water regularly, avoid peak sun hours, and check on vulnerable neighbors. Use light clothing and keep indoor spaces ventilated when possible.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"publish_status": "published",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"published_at": new Date('2026-03-14T06:45:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "How to Report Pollution Safely",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"category": "soil_erosion_prevention",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"excerpt": "Report issues without putting yourself at risk.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"content": "Keep a safe distance, avoid handling hazardous waste, and capture a clear photo and location. Submit the report and encourage community action through challenges.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type code here for "images" field
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"publish_status": "published",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"published_at": new Date('2026-03-16T11:15:00Z'),
|
|
|
|
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
const ClimateAlertsData = [
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "High Heat Expected",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"message": "Temperatures will be high this week. Stay hydrated and avoid outdoor work during midday.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"severity": "warning",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"alert_type": "heavy_rains",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"starts_at": new Date('2026-03-24T00:00:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"ends_at": new Date('2026-03-28T23:59:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"is_active": true,
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "Heavy Rains Coming",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"message": "Heavy rains expected in some areas. Clear drains and avoid crossing flooded roads.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"severity": "info",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"alert_type": "general",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"starts_at": new Date('2026-03-26T00:00:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"ends_at": new Date('2026-03-27T23:59:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"is_active": true,
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "Warm Afternoons",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"message": "Afternoon temperatures slightly above average. Plan outdoor activities early.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"severity": "critical",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"alert_type": "heavy_rains",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"starts_at": new Date('2026-03-20T00:00:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"ends_at": new Date('2026-03-22T23:59:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"is_active": false,
|
|
|
|
|
|
|
|
},
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
"title": "Localized Showers",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"message": "Short showers possible in the evenings. Keep waste secured to prevent runoff.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"severity": "warning",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"alert_type": "general",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"starts_at": new Date('2026-03-18T00:00:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"ends_at": new Date('2026-03-19T23:59:00Z'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"is_active": false,
|
|
|
|
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Similar logic for "relation_many"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function associatePollutionReportWithReporter() {
|
|
|
|
const relatedReporter0 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const PollutionReport0 = await PollutionReports.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 0
|
|
});
|
|
if (PollutionReport0?.setReporter)
|
|
{
|
|
await
|
|
PollutionReport0.
|
|
setReporter(relatedReporter0);
|
|
}
|
|
|
|
const relatedReporter1 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const PollutionReport1 = await PollutionReports.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 1
|
|
});
|
|
if (PollutionReport1?.setReporter)
|
|
{
|
|
await
|
|
PollutionReport1.
|
|
setReporter(relatedReporter1);
|
|
}
|
|
|
|
const relatedReporter2 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const PollutionReport2 = await PollutionReports.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 2
|
|
});
|
|
if (PollutionReport2?.setReporter)
|
|
{
|
|
await
|
|
PollutionReport2.
|
|
setReporter(relatedReporter2);
|
|
}
|
|
|
|
const relatedReporter3 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const PollutionReport3 = await PollutionReports.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 3
|
|
});
|
|
if (PollutionReport3?.setReporter)
|
|
{
|
|
await
|
|
PollutionReport3.
|
|
setReporter(relatedReporter3);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function associateEcoActionLogWithUser() {
|
|
|
|
const relatedUser0 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const EcoActionLog0 = await EcoActionLogs.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 0
|
|
});
|
|
if (EcoActionLog0?.setUser)
|
|
{
|
|
await
|
|
EcoActionLog0.
|
|
setUser(relatedUser0);
|
|
}
|
|
|
|
const relatedUser1 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const EcoActionLog1 = await EcoActionLogs.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 1
|
|
});
|
|
if (EcoActionLog1?.setUser)
|
|
{
|
|
await
|
|
EcoActionLog1.
|
|
setUser(relatedUser1);
|
|
}
|
|
|
|
const relatedUser2 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const EcoActionLog2 = await EcoActionLogs.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 2
|
|
});
|
|
if (EcoActionLog2?.setUser)
|
|
{
|
|
await
|
|
EcoActionLog2.
|
|
setUser(relatedUser2);
|
|
}
|
|
|
|
const relatedUser3 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const EcoActionLog3 = await EcoActionLogs.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 3
|
|
});
|
|
if (EcoActionLog3?.setUser)
|
|
{
|
|
await
|
|
EcoActionLog3.
|
|
setUser(relatedUser3);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function associateChallengeParticipationWithChallenge() {
|
|
|
|
const relatedChallenge0 = await CommunityChallenges.findOne({
|
|
offset: Math.floor(Math.random() * (await CommunityChallenges.count())),
|
|
});
|
|
const ChallengeParticipation0 = await ChallengeParticipations.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 0
|
|
});
|
|
if (ChallengeParticipation0?.setChallenge)
|
|
{
|
|
await
|
|
ChallengeParticipation0.
|
|
setChallenge(relatedChallenge0);
|
|
}
|
|
|
|
const relatedChallenge1 = await CommunityChallenges.findOne({
|
|
offset: Math.floor(Math.random() * (await CommunityChallenges.count())),
|
|
});
|
|
const ChallengeParticipation1 = await ChallengeParticipations.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 1
|
|
});
|
|
if (ChallengeParticipation1?.setChallenge)
|
|
{
|
|
await
|
|
ChallengeParticipation1.
|
|
setChallenge(relatedChallenge1);
|
|
}
|
|
|
|
const relatedChallenge2 = await CommunityChallenges.findOne({
|
|
offset: Math.floor(Math.random() * (await CommunityChallenges.count())),
|
|
});
|
|
const ChallengeParticipation2 = await ChallengeParticipations.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 2
|
|
});
|
|
if (ChallengeParticipation2?.setChallenge)
|
|
{
|
|
await
|
|
ChallengeParticipation2.
|
|
setChallenge(relatedChallenge2);
|
|
}
|
|
|
|
const relatedChallenge3 = await CommunityChallenges.findOne({
|
|
offset: Math.floor(Math.random() * (await CommunityChallenges.count())),
|
|
});
|
|
const ChallengeParticipation3 = await ChallengeParticipations.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 3
|
|
});
|
|
if (ChallengeParticipation3?.setChallenge)
|
|
{
|
|
await
|
|
ChallengeParticipation3.
|
|
setChallenge(relatedChallenge3);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function associateChallengeParticipationWithUser() {
|
|
|
|
const relatedUser0 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const ChallengeParticipation0 = await ChallengeParticipations.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 0
|
|
});
|
|
if (ChallengeParticipation0?.setUser)
|
|
{
|
|
await
|
|
ChallengeParticipation0.
|
|
setUser(relatedUser0);
|
|
}
|
|
|
|
const relatedUser1 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const ChallengeParticipation1 = await ChallengeParticipations.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 1
|
|
});
|
|
if (ChallengeParticipation1?.setUser)
|
|
{
|
|
await
|
|
ChallengeParticipation1.
|
|
setUser(relatedUser1);
|
|
}
|
|
|
|
const relatedUser2 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const ChallengeParticipation2 = await ChallengeParticipations.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 2
|
|
});
|
|
if (ChallengeParticipation2?.setUser)
|
|
{
|
|
await
|
|
ChallengeParticipation2.
|
|
setUser(relatedUser2);
|
|
}
|
|
|
|
const relatedUser3 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const ChallengeParticipation3 = await ChallengeParticipations.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 3
|
|
});
|
|
if (ChallengeParticipation3?.setUser)
|
|
{
|
|
await
|
|
ChallengeParticipation3.
|
|
setUser(relatedUser3);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function associateRewardTransactionWithUser() {
|
|
|
|
const relatedUser0 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const RewardTransaction0 = await RewardTransactions.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 0
|
|
});
|
|
if (RewardTransaction0?.setUser)
|
|
{
|
|
await
|
|
RewardTransaction0.
|
|
setUser(relatedUser0);
|
|
}
|
|
|
|
const relatedUser1 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const RewardTransaction1 = await RewardTransactions.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 1
|
|
});
|
|
if (RewardTransaction1?.setUser)
|
|
{
|
|
await
|
|
RewardTransaction1.
|
|
setUser(relatedUser1);
|
|
}
|
|
|
|
const relatedUser2 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const RewardTransaction2 = await RewardTransactions.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 2
|
|
});
|
|
if (RewardTransaction2?.setUser)
|
|
{
|
|
await
|
|
RewardTransaction2.
|
|
setUser(relatedUser2);
|
|
}
|
|
|
|
const relatedUser3 = await Users.findOne({
|
|
offset: Math.floor(Math.random() * (await Users.count())),
|
|
});
|
|
const RewardTransaction3 = await RewardTransactions.findOne({
|
|
order: [['id', 'ASC']],
|
|
offset: 3
|
|
});
|
|
if (RewardTransaction3?.setUser)
|
|
{
|
|
await
|
|
RewardTransaction3.
|
|
setUser(relatedUser3);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
module.exports = {
|
|
up: async (queryInterface, Sequelize) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await PollutionReports.bulkCreate(PollutionReportsData);
|
|
|
|
|
|
|
|
|
|
await EcoActionLogs.bulkCreate(EcoActionLogsData);
|
|
|
|
|
|
|
|
|
|
await CommunityChallenges.bulkCreate(CommunityChallengesData);
|
|
|
|
|
|
|
|
|
|
await ChallengeParticipations.bulkCreate(ChallengeParticipationsData);
|
|
|
|
|
|
|
|
|
|
await RewardTransactions.bulkCreate(RewardTransactionsData);
|
|
|
|
|
|
|
|
|
|
await RewardsCatalog.bulkCreate(RewardsCatalogData);
|
|
|
|
|
|
|
|
|
|
await EducationArticles.bulkCreate(EducationArticlesData);
|
|
|
|
|
|
|
|
|
|
await ClimateAlerts.bulkCreate(ClimateAlertsData);
|
|
|
|
|
|
await Promise.all([
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Similar logic for "relation_many"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await associatePollutionReportWithReporter(),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await associateEcoActionLogWithUser(),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await associateChallengeParticipationWithChallenge(),
|
|
|
|
|
|
|
|
|
|
await associateChallengeParticipationWithUser(),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await associateRewardTransactionWithUser(),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
]);
|
|
|
|
},
|
|
|
|
down: async (queryInterface, Sequelize) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await queryInterface.bulkDelete('pollution_reports', null, {});
|
|
|
|
|
|
await queryInterface.bulkDelete('eco_action_logs', null, {});
|
|
|
|
|
|
await queryInterface.bulkDelete('community_challenges', null, {});
|
|
|
|
|
|
await queryInterface.bulkDelete('challenge_participations', null, {});
|
|
|
|
|
|
await queryInterface.bulkDelete('reward_transactions', null, {});
|
|
|
|
|
|
await queryInterface.bulkDelete('rewards_catalog', null, {});
|
|
|
|
|
|
await queryInterface.bulkDelete('education_articles', null, {});
|
|
|
|
|
|
await queryInterface.bulkDelete('climate_alerts', null, {});
|
|
|
|
|
|
},
|
|
}; |