如何处理复杂的用户状态?
How to handle complex user status?
我的应用程序处理用户付款。在公司,该用户状态如下:
- 合规(用户支付了迄今为止的所有债务)
- overdue/default(用户注册至少 3 个月且未偿还至少 1 笔债务)
- 不活跃(用户注册不足3个月且未还清任何债务)
在应用程序内的多个位置(和规则)处理这些规则的最佳方式是什么?
我是否需要像 status_id
这样的字段和一个 cron 来每小时更新一次?
没有 status_id
字段并在每个需要显示状态的查询中写入 SQL 规则?
加载 User
模型并调用具有规则的 ->status()
方法?在这种情况下,我该如何显示 "totals",例如:我们有 3000 个过期用户,15000 个不活跃用户等...
这让我头疼了几个月,我真的需要帮助哈哈。我们目前有一个解决方案,但它太复杂而无法处理。由于这在处理支付的应用程序中似乎很常见,因此必须有一种更简单的方法来执行此操作:P
谢谢!
备注
- 应用程序当前有 90.000 个用户
- 我们需要这些实时信息。
- 此信息在报告中用于生成字符。
- 此信息显示在用户个人资料中。
- 此信息显示在列表中。
- 当用户在这些状态之间更改时(例如,当用户输入 "overdue" 时 "you have debts"),用户会收到通知。
- 此信息不由应用程序用户管理。
- 需要跟踪状态。
如果你在多个地方使用这个字段,那么你应该把状态存储在一个地方并适当地更新它(我也会保留状态的历史,但那是另一回事)。
如果状态因某些用户操作(例如正在处理的付款)而发生变化,则您可以对该操作使用触发器。但是,您的状态更改似乎是基于事件发生后的时间。在这种情况下,您应该 运行 定期安排的作业(作为 cron 作业或数据库事件)。
我有点不明白你为什么每小时都这样做。看来每天一次最合适。如果 "debts" 在任意时间支付,则支付过程应更新状态。状态降级的话,一天一个任务就够了。
有趣的问题,但也不是只有一个答案的问题。
我认为这里的复杂性可能来自于周边的代码,而不是核心的业务逻辑和需求。我这样说是因为三种状态类型(所有这些都来自您的内部应用程序)并不是 too 坏的。
一个可能的解决方案,我假设某种级别的 MVC 或类似的。
给定你的模型,user
,并扩展像 Eloquent 这样的 ORM(我将从 Laravel Eloquent 因为我最熟悉它,但是任何 ORM将工作):
use Illuminate\Database\Eloquent\Model;
use App\DebtCollector;
public class User extends Model
{
// Assuming model has the following fields
// id, status, registration_date, and a one to many
// relationship with debts
protected $fillable = [
'raw_status',
'registration_date',
];
public function debts()
{
return $this->hasMany(Debt::class);
}
public function refreshStatus()
{
$dc = new DebtCollector();
// Business logic inside the "DebtCollector" class
$this->raw_status = $dc->resolveStatus($this->debts, $this->registration_date);
// Save value to the underlying datebase
$this->save();
}
// If you fetch a status directly, it will refresh first,
// then return the value
//
public function getStatusAttribute()
{
$this->refreshStatus();
return $this->raw_status;
}
}
// Schedule task somewhere - ran nightly, or whenever
//
// This way you can refresh the status only on certain groups
// of data - for example, if the business flow means that once
// they become compliant, they can't go back, there is no need
// to refresh their status anymore
//
User::where('raw_status', '<>', 'compliant')->refreshStatus();
// Alternatively, the schedule could chunk results and do an update
// only to those not updated in the last 24 hours
//
$date = new DateTime;
$date->modify('-24 hours');
$formatted_date = $date->format('Y-m-d H:i:s');
User::where('last_updated', '>', $formatted_data)->refreshStatus();
我会说这个问题有多种解决方案。
我建议不要有任何定义的状态。据我所知,您总是可以 "figure out" 基于其他一些数据的当前状态。
例如 "user payed all debts so far"。这是您仅通过分析给定时间段内的所有变化就知道的事情。您可以汇总数据以找出您需要知道的所有信息。那么你根本不需要保存状态。它只是从特定时期内客户帐户发生的所有更改中得出的。
总计也是如此。您可以在数据库级别轻松完成此操作,甚至可以使用一些基于文档的数据库或 ElasticSearch。
当然,这假定您跟踪更改历史。如果你这样做 - 问题就解决了。如果不这样做 - 您必须将状态保存到数据库中,并且将无法获取历史数据。
我的应用程序处理用户付款。在公司,该用户状态如下:
- 合规(用户支付了迄今为止的所有债务)
- overdue/default(用户注册至少 3 个月且未偿还至少 1 笔债务)
- 不活跃(用户注册不足3个月且未还清任何债务)
在应用程序内的多个位置(和规则)处理这些规则的最佳方式是什么?
我是否需要像 status_id
这样的字段和一个 cron 来每小时更新一次?
没有 status_id
字段并在每个需要显示状态的查询中写入 SQL 规则?
加载 User
模型并调用具有规则的 ->status()
方法?在这种情况下,我该如何显示 "totals",例如:我们有 3000 个过期用户,15000 个不活跃用户等...
这让我头疼了几个月,我真的需要帮助哈哈。我们目前有一个解决方案,但它太复杂而无法处理。由于这在处理支付的应用程序中似乎很常见,因此必须有一种更简单的方法来执行此操作:P
谢谢!
备注
- 应用程序当前有 90.000 个用户
- 我们需要这些实时信息。
- 此信息在报告中用于生成字符。
- 此信息显示在用户个人资料中。
- 此信息显示在列表中。
- 当用户在这些状态之间更改时(例如,当用户输入 "overdue" 时 "you have debts"),用户会收到通知。
- 此信息不由应用程序用户管理。
- 需要跟踪状态。
如果你在多个地方使用这个字段,那么你应该把状态存储在一个地方并适当地更新它(我也会保留状态的历史,但那是另一回事)。
如果状态因某些用户操作(例如正在处理的付款)而发生变化,则您可以对该操作使用触发器。但是,您的状态更改似乎是基于事件发生后的时间。在这种情况下,您应该 运行 定期安排的作业(作为 cron 作业或数据库事件)。
我有点不明白你为什么每小时都这样做。看来每天一次最合适。如果 "debts" 在任意时间支付,则支付过程应更新状态。状态降级的话,一天一个任务就够了。
有趣的问题,但也不是只有一个答案的问题。
我认为这里的复杂性可能来自于周边的代码,而不是核心的业务逻辑和需求。我这样说是因为三种状态类型(所有这些都来自您的内部应用程序)并不是 too 坏的。
一个可能的解决方案,我假设某种级别的 MVC 或类似的。
给定你的模型,user
,并扩展像 Eloquent 这样的 ORM(我将从 Laravel Eloquent 因为我最熟悉它,但是任何 ORM将工作):
use Illuminate\Database\Eloquent\Model;
use App\DebtCollector;
public class User extends Model
{
// Assuming model has the following fields
// id, status, registration_date, and a one to many
// relationship with debts
protected $fillable = [
'raw_status',
'registration_date',
];
public function debts()
{
return $this->hasMany(Debt::class);
}
public function refreshStatus()
{
$dc = new DebtCollector();
// Business logic inside the "DebtCollector" class
$this->raw_status = $dc->resolveStatus($this->debts, $this->registration_date);
// Save value to the underlying datebase
$this->save();
}
// If you fetch a status directly, it will refresh first,
// then return the value
//
public function getStatusAttribute()
{
$this->refreshStatus();
return $this->raw_status;
}
}
// Schedule task somewhere - ran nightly, or whenever
//
// This way you can refresh the status only on certain groups
// of data - for example, if the business flow means that once
// they become compliant, they can't go back, there is no need
// to refresh their status anymore
//
User::where('raw_status', '<>', 'compliant')->refreshStatus();
// Alternatively, the schedule could chunk results and do an update
// only to those not updated in the last 24 hours
//
$date = new DateTime;
$date->modify('-24 hours');
$formatted_date = $date->format('Y-m-d H:i:s');
User::where('last_updated', '>', $formatted_data)->refreshStatus();
我会说这个问题有多种解决方案。
我建议不要有任何定义的状态。据我所知,您总是可以 "figure out" 基于其他一些数据的当前状态。 例如 "user payed all debts so far"。这是您仅通过分析给定时间段内的所有变化就知道的事情。您可以汇总数据以找出您需要知道的所有信息。那么你根本不需要保存状态。它只是从特定时期内客户帐户发生的所有更改中得出的。
总计也是如此。您可以在数据库级别轻松完成此操作,甚至可以使用一些基于文档的数据库或 ElasticSearch。
当然,这假定您跟踪更改历史。如果你这样做 - 问题就解决了。如果不这样做 - 您必须将状态保存到数据库中,并且将无法获取历史数据。