如何在Kotlin预约服务应用中实现每日用户提交配额限制
解决方案:实现每日预约配额限制
要实现用户每日预约提交的配额限制,核心是在提交前检查当日已提交次数,并用事务保证操作的原子性(避免并发提交导致配额计数错误),以下是具体实现步骤:
1. 配置Firestore配额存储
在Firestore中新增一个UserQuotas集合,每个用户对应一个文档(文档ID使用用户的nama,和你现有预约数据的文档ID保持一致),文档包含3个字段:
dailyQuota: 整数,设置每日允许的预约上限(比如设为3)todayBookings: 整数,记录用户当日已提交的预约数lastResetDate: 字符串,格式为yyyy-MM-dd,记录配额上次重置的日期
2. 编写带配额检查的提交逻辑
用Firestore事务来整合「配额检查→提交预约→更新计数」的流程,确保这一系列操作不会被并发请求打断:
// 1. 格式化当前日期(用于配额重置判断) val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) val today = dateFormat.format(Date()) // 2. 启动Firestore事务 database.runTransaction { transaction -> // 获取用户的配额文档引用 val quotaDocRef = database.collection("UserQuotas").document(nama) val quotaDoc = transaction.get(quotaDocRef) // 初始化默认配额(如果用户是第一次提交) var dailyQuota = 3 // 这里可以改成你需要的每日上限 var todayBookings = 0 var lastResetDate = today if (quotaDoc.exists()) { dailyQuota = quotaDoc.getLong("dailyQuota")?.toInt() ?: 3 todayBookings = quotaDoc.getLong("todayBookings")?.toInt() ?: 0 lastResetDate = quotaDoc.getString("lastResetDate") ?: today } // 3. 重置当日配额(如果不是今天的记录) if (lastResetDate != today) { todayBookings = 0 lastResetDate = today } // 4. 检查配额是否用尽 if (todayBookings >= dailyQuota) { // 配额不足,抛出异常终止事务 throw FirebaseFirestoreException( "今日预约配额已用尽,请明日再试", FirebaseFirestoreException.Code.ABORTED ) } // 5. 配额充足,提交预约数据 val Modeldatabase = ModelDatabase(platnomor, tahunkendaraan, serieskendaraan, nama, alamat, nomorhp, tanggalservice, keluhane) val bookingDocRef = database.collection("Data Booking").document(nama) transaction.set(bookingDocRef, Modeldatabase) // 6. 更新当日预约计数 transaction.set(quotaDocRef, hashMapOf( "dailyQuota" to dailyQuota, "todayBookings" to (todayBookings + 1), "lastResetDate" to lastResetDate )) return@runTransaction null }.addOnSuccessListener { // 提交成功,清空表单并提示 pltnomor.text?.clear() thnkendaraan.text?.clear() srskendaraan.text?.clear() namapmlk.text?.clear() alamatpmlk.text?.clear() nohpe.text?.clear() tglbooking.text?.clear() keluhankerusakan.text?.clear() Toast.makeText(this, "Booking Sukses!", Toast.LENGTH_SHORT).show() }.addOnFailureListener { e -> // 根据异常类型提示不同信息 val message = if (e.message == "今日预约配额已用尽,请明日再试") { e.message } else { "Booking Gagal!" } Toast.makeText(this, message, Toast.LENGTH_SHORT).show() }
3. 额外注意事项
- 如果需要动态调整用户的每日配额,可以直接修改
UserQuotas文档里的dailyQuota字段,无需修改代码 - 日期格式化建议用
DateTimeFormatter(Android API 26+)替代SimpleDateFormat,避免线程安全问题:val dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.getDefault()) val today = LocalDate.now().format(dateFormatter) - 确保用户的
nama是唯一标识,避免不同用户用相同名字导致配额混淆
内容的提问来源于stack exchange,提问作者sandwich
相关产品推荐
相关产品推荐

