Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/#1 Base migrations and models for Feedback #8

Merged
merged 8 commits into from
Feb 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions config/feedback.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,13 @@

return [

/**
* Model class references
*/
'model_class' => [
'participant' => \App\Models\Participant::class,

'location' => \App\Models\Location::class,
]

];
125 changes: 125 additions & 0 deletions database/factories/FeedbackFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<?php

namespace Database\Factories;

use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\Factories\Factory;
use Tipoff\Feedback\Models\Feedback;

class FeedbackFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Feedback::class;

/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
$actiondate = $this->faker->dateTimeBetween('-1 months', 'now');
if ($this->faker->boolean) {
$messagetext = $this->faker->sentences(5, true);
$submitted = $actiondate;
} else {
$messagetext = null;
$submitted = null;
}

if ($this->faker->boolean) {
// Opened Email
$opened_at = $actiondate;
$clicked_negative_at = null;
$clicked_semi_negative_at = null;
$clicked_positive_at = null;
$clicked_semi_positive_at = null;
$clicked_review_at = null;
$redirected_at = null;
$message = null;
if ($this->faker->boolean) {
// Positive
if ($this->faker->boolean) {
// Positive
$opened_at = $actiondate;
$clicked_negative_at = null;
$clicked_semi_negative_at = null;
$clicked_positive_at = $actiondate;
$clicked_semi_positive_at = null;
$clicked_review_at = $actiondate;
$redirected_at = $actiondate;
$message = null;
$submitted_at = null;
} else {
// Semi Positive
$opened_at = $actiondate;
$clicked_negative_at = null;
$clicked_semi_negative_at = null;
$clicked_positive_at = null;
$clicked_semi_positive_at = $actiondate;
$clicked_review_at = null;
$redirected_at = null;
$message = $messagetext;
$submitted_at = $submitted;
}
} else {
// Negative
if ($this->faker->boolean) {
// Negative
$opened_at = $actiondate;
$clicked_negative_at = $actiondate;
$clicked_semi_negative_at = null;
$clicked_positive_at = null;
$clicked_semi_positive_at = null;
$clicked_review_at = null;
$redirected_at = null;
$message = $messagetext;
$submitted_at = $submitted;
} else {
// Semi Negative
$opened_at = $actiondate;
$clicked_negative_at = null;
$clicked_semi_negative_at = $actiondate;
$clicked_positive_at = null;
$clicked_semi_positive_at = null;
$clicked_review_at = null;
$redirected_at = null;
$message = $messagetext;
$submitted_at = $submitted;
}
}
} else {
// Not responded
$opened_at = null;
$clicked_negative_at = null;
$clicked_semi_negative_at = null;
$clicked_positive_at = null;
$clicked_semi_positive_at = null;
$clicked_review_at = null;
$redirected_at = null;
$message = null;
$submitted_at = null;
}

return [
'participant_id' => randomOrCreate(config('feedback.model_class.participant'), 'participant_id'),
'location_id' => randomOrCreate(config('feedback.model_class.location'), 'location_id'),
'date' => $this->faker->date(), // Should be a day less than emailed_at
'emailed_at' => $this->faker->dateTimeBetween('-3 months', '-1 months'),
'email_identifier' => Str::random(100),
'opened_at' => $opened_at,
'clicked_negative_at' => $clicked_negative_at,
'clicked_semi_negative_at' => $clicked_semi_negative_at,
'clicked_semi_positive_at' => $clicked_semi_positive_at,
'clicked_positive_at' => $clicked_positive_at,
'clicked_review_at' => $clicked_review_at,
'redirected_at' => $redirected_at,
'message' => $message,
'submitted_at' => $submitted_at,
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateFeedbacksTable extends Migration
{
public function up()
{
Schema::create('feedbacks', function (Blueprint $table) {
$participantModel = config('feedback.model_class.participant');
$participantTable = (new $participantModel)->getTable();

$locationModel = config('feedback.model_class.location');
$locationTable = (new $locationModel)->getTable();

$table->id();
$table->string('token')->index()->unique(); // unique hash for the feedback so can use in links instead of the id
$table->foreignId('participant_id')->index()->references('id')->on($participantTable);
$table->foreignId('location_id')->index()->references('id')->on($locationTable);
$table->date('date')->index(); // date the escape room game was played
$table->dateTime('emailed_at')->nullable();
$table->string('email_identifier')->nullable()->unique(); // "MessageID" from Postmark or email service needed to track opens since multiple feedbacks could exist and can't track opens to the participant
$table->dateTime('opened_at')->nullable();
$table->dateTime('clicked_negative_at')->nullable();
$table->dateTime('clicked_semi_negative_at')->nullable();
$table->dateTime('clicked_semi_positive_at')->nullable();
$table->dateTime('clicked_positive_at')->nullable();
$table->dateTime('clicked_review_at')->nullable();
$table->dateTime('redirected_at')->nullable();
$table->text('message')->nullable();
$table->dateTime('submitted_at')->nullable(); // message submitted datetime
$table->softDeletes(); // Soft delete if email bounces. Also need to soft delete the Participant & update the waiver signature.
$table->timestamps();
});
}

public function down()
{
Schema::dropIfExists('feedbacks');
}
}
17 changes: 16 additions & 1 deletion src/FeedbackServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,22 @@ public function configurePackage(Package $package): void
->name('feedback')
->hasConfigFile()
->hasViews()
->hasMigration('create_feedback_table')
->hasMigration('2020_05_11_130000_create_feedbacks_table')
->hasCommand(FeedbackCommand::class);
}

/**
* Using packageBooted lifecycle hooks to override the migration file name.
* We want to keep the old filename for now.
*/
public function packageBooted()
{
foreach ($this->package->migrationFileNames as $migrationFileName) {
if (! $this->migrationFileExists($migrationFileName)) {
$this->publishes([
$this->package->basePath("/../database/migrations/{$migrationFileName}.php.stub") => database_path('migrations/' . Str::finish($migrationFileName, '.php')),
], "{$this->package->name}-migrations");
}
}
}
}
54 changes: 54 additions & 0 deletions src/Models/Feedback.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace Tipoff\Feedback\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Tipoff\Support\Models\BaseModel;

class Feedback extends BaseModel
{
use HasFactory;
use SoftDeletes;

protected $guarded = ['id'];

protected $casts = [
'emailed_at' => 'datetime',
'opened_at' => 'datetime',
'clicked_negative_at' => 'datetime',
'clicked_semi_negative_at' => 'datetime',
'clicked_semi_positive_at' => 'datetime',
'clicked_positive_at' => 'datetime',
'redirected_at' => 'datetime',
'clicked_review_at' => 'datetime',
'submitted_at' => 'datetime',
'date' => 'date',
];

protected static function boot()
{
parent::boot();

static::creating(function ($feedback) {
if (empty($feedback->token)) {
$feedback->token = $feedback->location_id . 'L' . mt_rand(1000, 9999) . 'TGER' . mt_rand(1, 999999);
}
});
}

public function getRouteKeyName()
{
return 'token';
}

public function participant()
{
return $this->belongsTo(config('feedback.model_class.participant'), 'participant_id');
}

public function location()
{
return $this->belongsTo(config('feedback.model_class.location'), 'location_id');
}
}