My application deals with user payments. In the company, this user has the following status:
How is the best way to deal with those rules in multiple places (and rules) inside the application?
Do I need a field like status_id
and a cron to update this every hour?
No status_id
field and write the SQL rule in every query that needs to show the status?
Load a User
model and call a ->status()
method that has the rule? In this case, how can I show "totals", like: We have 3000 overdue users, 15000 inactive users etc...
This is giving me headaches for months and I really need help haha. We currently have a solution but it's too complex to deal with it. As it seems to be something common within apps that deal with payment, there's must be a simplier way to do this :P
Thanks!
Notes
Interesting question, but also not one with a single answer.
I think the complexity here might come from the surrounding code, rather than the core business logic and requirements. I say this because three status types, all of which are derived from your internal application, isn't too bad.
One possible solution, and I am assuming some level of MVC or similar.
Given your model, user
, and extending an ORM like Eloquent (I will Eloquent from Laravel because I am most familiar with it, but any ORM will work):
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();