mirror of https://github.com/kcal-app/kcal.git
Create JournalDate model for setting per-date goals
This commit is contained in:
parent
91fd85ef83
commit
dc4d7987e8
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* App\Models\JournalDate
|
||||
*
|
||||
* @property int $id
|
||||
* @property \datetime $date
|
||||
* @property int $user_id
|
||||
* @property int|null $goal_id
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read \App\Models\Goal|null $goal
|
||||
* @property-read \App\Models\User $user
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JournalDate newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JournalDate newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JournalDate query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JournalDate whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JournalDate whereDate($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JournalDate whereGoalId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JournalDate whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JournalDate whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JournalDate whereUserId($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
final class JournalDate extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected $fillable = [
|
||||
'date',
|
||||
];
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected $casts = [
|
||||
'date' => 'datetime:Y-m-d',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the Goal for this date.
|
||||
*/
|
||||
public function goal(): BelongsTo {
|
||||
return $this->belongsTo(Goal::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the User this journal date belongs to.
|
||||
*/
|
||||
public function user(): BelongsTo {
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Spatie\MediaLibrary\HasMedia;
|
||||
use Spatie\MediaLibrary\InteractsWithMedia;
|
||||
|
@ -50,6 +49,8 @@ use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
|||
* @method static \Illuminate\Database\Eloquent\Builder|User whereSlug($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|User withUniqueSlugConstraints(\Illuminate\Database\Eloquent\Model $model, string $attribute, array $config, string $slug)
|
||||
* @mixin \Eloquent
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\JournalDate[] $journalDates
|
||||
* @property-read int|null $journal_dates_count
|
||||
*/
|
||||
final class User extends Authenticatable implements HasMedia
|
||||
{
|
||||
|
@ -98,6 +99,13 @@ final class User extends Authenticatable implements HasMedia
|
|||
return $this->hasMany(Goal::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the User's journal dates.
|
||||
*/
|
||||
public function journalDates(): HasMany {
|
||||
return $this->hasMany(JournalDate::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the User's journal entries.
|
||||
*/
|
||||
|
@ -107,13 +115,36 @@ final class User extends Authenticatable implements HasMedia
|
|||
|
||||
/**
|
||||
* Get user's goal (if one exists) for a specific date.
|
||||
*
|
||||
* The primary use for a JournalDate entry right now is the goal so this
|
||||
* method also creates a JournalDate if one does not already exist.
|
||||
*/
|
||||
public function getGoalByDate(Carbon $date): ?Goal {
|
||||
/** @var \App\Models\JournalDate $journal_date */
|
||||
$journal_date = $this->journalDates()->whereDate('date', '=', $date)->first();
|
||||
if (empty($journal_date)) {
|
||||
$journal_date = JournalDate::make(['date' => $date])->user()->associate(Auth::user());
|
||||
}
|
||||
if ($journal_date->goal) {
|
||||
return $journal_date->goal;
|
||||
}
|
||||
|
||||
// Check for a goal based on day of week configurations.
|
||||
$day = Goal::days()->firstWhere('dow', $date->format('N'));
|
||||
if (!$day) {
|
||||
throw new \BadMethodCallException("No day with `dow` value {$date->format('N')}.");
|
||||
}
|
||||
return $this->goals()->whereRaw("(days & {$day['value']}) != 0")->get()->first();
|
||||
/** @var \App\Models\Goal $goal */
|
||||
$goal = $this->goals()->whereRaw("(days & {$day['value']}) != 0")->first();
|
||||
if (!empty($goal)) {
|
||||
$journal_date->goal()->associate($goal);
|
||||
}
|
||||
|
||||
if ($journal_date->hasChanges(['date', 'goal'])) {
|
||||
$journal_date->save();
|
||||
}
|
||||
|
||||
return $goal;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Database\Factories;
|
||||
|
||||
use App\Models\Goal;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class GoalFactory extends Factory
|
||||
|
@ -15,16 +16,18 @@ class GoalFactory extends Factory
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function definition()
|
||||
public function definition(): array
|
||||
{
|
||||
$from = $this->faker->dateTimeThisMonth;
|
||||
$to = $this->faker->dateTimeBetween($from, '+1 year');
|
||||
return [
|
||||
'from' => $this->faker->randomElement([$from, null]),
|
||||
'to' => $this->faker->randomElement([$to, null]),
|
||||
'frequency' => $this->faker->randomElement(Goal::$frequencyOptions)['value'],
|
||||
'name' => $this->faker->randomElement(Goal::getNameOptions())['value'],
|
||||
'goal' => $this->faker->numberBetween(0, 2000),
|
||||
'user_id' => User::factory(),
|
||||
'name' => $this->faker->words,
|
||||
'days' => $this->faker->randomElement(Goal::days()->pluck('value')->all()),
|
||||
'calories' => $this->faker->numberBetween(1600, 2500),
|
||||
'fat' => $this->faker->numberBetween(40, 90),
|
||||
'cholesterol' => $this->faker->numberBetween(0, 500),
|
||||
'sodium' => $this->faker->numberBetween(0, 3000),
|
||||
'carbohydrates' => $this->faker->numberBetween(50, 100),
|
||||
'protein' => $this->faker->numberBetween(90, 200),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\Goal;
|
||||
use App\Models\JournalDate;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class JournalDateFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $model = JournalDate::class;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'date' => $this->faker->dateTimeThisMonth,
|
||||
'user_id' => User::factory(),
|
||||
'goal_id' => Goal::factory(),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Goal;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateJournalDatesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('journal_dates', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->date('date')->useCurrent();
|
||||
$table->foreignIdFor(User::class)->constrained()->cascadeOnUpdate()->cascadeOnDelete();
|
||||
$table->foreignIdFor(Goal::class)->nullable()->constrained()->cascadeOnUpdate()->cascadeOnDelete();
|
||||
$table->timestamps();
|
||||
$table->unique(['date', 'user_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('journal_dates');
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue