Browse Source

Merge branch 'mohammad' of https://gitea.hooradev.ir/mahdihty/liwo

pull/2/head
masoud 4 years ago
parent
commit
49d504538f
  1. 5
      .env.example
  2. 203
      app/Console/Commands/CostCommand.php
  3. 38
      app/Events/ModelSaved.php
  4. 110
      app/Http/Controllers/ActivityController.php
  5. 1
      app/Http/Controllers/AuthController.php
  6. 2
      app/Http/Resources/TaskResource.php
  7. 73
      app/Listeners/ActivityRegistration.php
  8. 31
      app/Models/Activity.php
  9. 33
      app/Models/Model.php
  10. 2
      app/Models/Task.php
  11. 4
      app/Models/User.php
  12. 5
      app/Providers/EventServiceProvider.php
  13. 5
      composer.json
  14. 2
      config/app.php
  15. 2
      database/factories/BusinessFactory.php
  16. 4
      database/migrations/2020_08_18_085017_fingerprints.php
  17. 2
      database/migrations/2020_08_18_085018_create_businesses_table.php
  18. 45
      database/migrations/2021_03_06_085855_create_activities_table.php
  19. 36
      database/migrations/2021_03_06_114918_create_failed_jobs_table.php
  20. 5
      routes/api.php

5
.env.example

@ -25,8 +25,9 @@ SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1 MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_HOST=redis
REDIS_PASSWORD=root
REDIS_USER=root
REDIS_PORT=6379 REDIS_PORT=6379
MAIL_MAILER=smtp MAIL_MAILER=smtp

203
app/Console/Commands/CostCommand.php

@ -2,9 +2,12 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use DB;
use Throwable;
use Carbon\Carbon;
use App\Models\Business; use App\Models\Business;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Morilog\Jalali\CalendarUtils;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
class CostCommand extends Command class CostCommand extends Command
@ -28,109 +31,143 @@ class CostCommand extends Command
public function handle() public function handle()
{ {
// infinte loop
while (true) { while (true) {
// to baghali ha
$recorded_month = jdate($business->calculated_at)->format("Y-m-01");
$calculated_at = Cache::get('calculated_at');
if ($calculated_at === null) {
$business = Business::orderBy('calculated_at')->first()->load('users', 'cost');
$calculated_at = $business->calculated_at;
$until_now = jdate()->getMonth() > jdate($business->calculated_at)->getMonth()
? jdate($business->calculated_at)->toCarbon()->setTime("00", "00", "00")
: \Carbon\Carbon::now();
Cache::put('calculated_at', $until_now, 60);
$business = Business::find(221);
if ($business === null) {
continue;
}
$year = jdate()->getYear();
$month = jdate()->getMonth();
$day = jdate()->getDay();
$hour = jdate()->getHour();
$minute = jdate()->getMinute();
$second = jdate()->getSecond();
if (jdate()->getYear() > jdate($business->calculated_at)->getYear()) {
$year = jdate()->getYear();
$month = 1;
$day = 1;
} }
if (
jdate()->getYear() > jdate($business->calculated_at)->getYear()
&&
jdate()->getMonth() > jdate($business->calculated_at)->getMonth()
) {
$year = jdate()->getYear();
$month = jdate()->getMonth();
$day = 1;
}
$gDate = CalendarUtils::toGregorian($year, $month, $day);
$carbon = Carbon::createFromDate($gDate[0], $gDate[1], $gDate[2]);
$carbon->setTime($hour, $minute, $second);
$now = $carbon;
// if calculated_at less than an hour stop // if calculated_at less than an hour stop
if (\Carbon\Carbon::now()->diffInMinutes($until_now) <= 60) {
$this->info('nothing to cost');
if ($now->diffInMinutes($business->calculated_at)) {
$this->info('Must be one hour after the last audit.');
continue; continue;
} }
try { try {
DB::beginTransaction(); DB::beginTransaction();
// Fixed amounts of expenses
$business->load('users', 'cost');
// business order by last_calculated_at take first
if (!isset($business)) {
$business = Business::orderBy('calculated_at')->first()->load('users', 'cost');
}
$user_fee = enum('business.fee.user');
// get business employee
$users_cost = $business->cost
->where('type', '=', 'users')
->where('fee', '=', $user_fee)
->where('month', '=', $recorded_month)
->where('amount', '=', $business->users->count())
->first();
if ($users_cost === null) {
$business->cost()->create([
'type' => 'users',
'month' => $recorded_month,
'amount' => $business->users->count(),
'fee' => $user_fee,
'duration' => $duration = $until_now->diffInSeconds($calculated_at), // from the created_at time of the newset fifth user
'additional' => $business->users->pluck('id')->toArray(),
]);
} else {
$users_cost->update([
'duration' => $duration = $until_now->diffInMinutes($calculated_at), // last calc - (current month - now else last calc - end of the past month),
'additional' => $business->users->pluck('id')->toArray(),
]);
}
$costs = $user_fee * $duration;
// do the math in php
if (intdiv($business->files_volume, 200) === 0) {
$pads = 0;
} else {
$pads = intdiv($business->files_volume, 200) - 1;
}
$file_fee = enum('business.fee.file');
$files = $business->cost
->where('type', '=', 'files')
->where('fee', '=', $file_fee)
->where('month', '=', $recorded_month)
->where('amount', '=', $business->files_volume)
->first();
if ($files === null) {
$business->cost()->create([
'type' => 'files',
'month' => $recorded_month,
'amount' => $pads,
'fee' => $file_fee,
'duration' => $duration = $until_now->diffInMinutes($calculated_at), // how to determine the file?,
]);
} else {
$files->update([
'duration' => $duration = $until_now->diffInMinutes($calculated_at), // last calc - (current month - now else last calc - end of the past month),,
]);
}
$costs += $file_fee * $duration;
$costs = 0;
$costs += $this->calculateCostOfBusinessUsers($business, $now);
$costs += $this->calculateCostOfBusinessFiles($business, $now);
// increment and decrement of wallet in php // increment and decrement of wallet in php
// deduct costs from your business wallet // deduct costs from your business wallet
// make sure save the calculated_at // make sure save the calculated_at
$business->update([ $business->update([
'wallet' => $business->wallet - $costs, 'wallet' => $business->wallet - $costs,
'calculated_at' => \Carbon\Carbon::now(),
'calculated_at' => Carbon::now(),
]); ]);
DB::commit(); DB::commit();
} catch (Throwable $thr) {
} catch (Throwable $throwable) {
DB::rollback(); DB::rollback();
throw $thr;
report($throwable);
continue; continue;
} }
} }
} }
public function calculateCostOfBusinessUsers($business, $until_now)
{
$user_fee = enum('business.fee.user');
$calculated_at = $business->calculated_at;
$recorded_month = jdate($business->calculated_at)->format("Y-m-01");
// get business employee
$users_cost = $business->cost
->where('type', '=', 'users')
->where('fee', '=', $user_fee)
->where('month', '=', $recorded_month)
->where('amount', '=', $business->users->count())
->first();
if ($users_cost === null) {
$business->cost()->create([
'type' => 'users',
'month' => $recorded_month,
'amount' => $business->users->count(),
'fee' => $user_fee,
'duration' => $duration = $until_now->diffInSeconds($calculated_at), // from the created_at time of the newset fifth user
'additional' => $business->users->pluck('id')->toArray(),
]);
} else {
$users_cost->update([
'duration' => $duration = $until_now->diffInMinutes($calculated_at) + $users_cost->duration, // last calc - (current month - now else last calc - end of the past month),
'additional' => $business->users->pluck('id')->toArray(),
]);
}
return $user_fee * $duration;
}
public function calculateCostOfBusinessFiles($business, $until_now)
{
$file_fee = enum('business.fee.file');
$calculated_at = $business->calculated_at;
$recorded_month = jdate($business->calculated_at)->format("Y-m-01");
// do the math in php
if (intdiv($business->files_volume, 200) === 0) {
$pads = 0;
} else {
$pads = intdiv($business->files_volume, 200) - 1;
}
$files = $business->cost
->where('type', '=', 'files')
->where('fee', '=', $file_fee)
->where('month', '=', $recorded_month)
->where('amount', '=', $business->files_volume)
->first();
if ($files === null) {
$business->cost()->create([
'type' => 'files',
'month' => $recorded_month,
'amount' => $pads,
'fee' => $file_fee,
'duration' => $duration = $until_now->diffInMinutes($calculated_at), // how to determine the file?,
]);
} else {
$files->update([
'duration' => $duration = $until_now->diffInMinutes($calculated_at) + $files->duration, // last calc - (current month - now else last calc - end of the past month),,
]);
}
return $file_fee * $duration;
}
} }

38
app/Events/ModelSaved.php

@ -0,0 +1,38 @@
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class ModelSaved
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($message)
{
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}

110
app/Http/Controllers/ActivityController.php

@ -0,0 +1,110 @@
<?php
namespace App\Http\Controllers;
use App\Models\Activity;
use App\Rules\MaxBound;
use Illuminate\Http\Request;
use Spatie\QueryBuilder\AllowedFilter;
use Spatie\QueryBuilder\QueryBuilder;
class ActivityController extends Controller
{
public function index($business, Request $request)
{
permit('businessAccess');
$this->indexValidation($request);
$per_page = $request->limit > 100 ? 10 : $request->limit;
return $this->indexFiltering($business)->paginate($per_page);
}
public function indexValidation($request)
{
$bound = 10;
$this->validate($request, [
'filter.project_id' => [new MaxBound($bound)] ,
'filter.system_id' => [new MaxBound($bound)] ,
'filter.workflow_id' => [new MaxBound($bound)] ,
'filter.status_id' => [new MaxBound($bound)] ,
'filter.sprint_id' => [new MaxBound($bound)] ,
'filter.actor_id' => [new MaxBound($bound)] ,
'filter.user_id' => [new MaxBound($bound)] ,
'filter.subject_id' => [new MaxBound($bound)] ,
//todo: validation for crud_id and table_id
'filter.creates_before' => 'bail|nullable|date|date_format:Y-m-d' ,
'filter.creates_after' => 'bail|nullable|date|date_format:Y-m-d' ,
'filter.creates_in' => 'bail|nullable|numeric|max:90' ,
]);
}
public function indexFiltering($business)
{
$query = Activity::where('business_id', $business);
$activityQ = QueryBuilder::for($query)
->allowedFilters([
AllowedFilter::exact('project_id'),
AllowedFilter::exact('system_id'),
AllowedFilter::exact('workflow_id'),
AllowedFilter::exact('status_id'),
AllowedFilter::exact('sprint_id'),
AllowedFilter::exact('task_id'),
AllowedFilter::exact('actor_id'),
AllowedFilter::exact('user_id'),
AllowedFilter::exact('crud_id'),
AllowedFilter::exact('table_id'),
AllowedFilter::exact('subject_id'),
AllowedFilter::scope('creates_before'),
AllowedFilter::scope('creates_after'),
AllowedFilter::scope('creates_in'),
])
->defaultSort('-id')
->allowedSorts('id', 'created_at');
if (\request('_business_info')['info']['users'][\auth()->id()]['level'] != enum('levels.owner.id')) {
$requested_projects = isset(\request('filter')['project_id']) ?
array_unique(explode(',',\request('filter')['project_id'] ?? null )) :
null;
$requested_projects = collect($requested_projects)->keyBy(null)->toArray();
$project_ids = $this->myStateProjects($requested_projects);
$activityQ->where(function ($q) use ($project_ids) {
$q->whereIn('project_id', $project_ids['non_guest_ids'])
->orWhere(function ($q) use ($project_ids) {
$q->whereIn('project_id', $project_ids['guest_ids'])
->where('user_id', auth()->id());
});
});
}
return $activityQ;
}
public function myStateProjects($requested_projects)
{
$non_guest_ids = [];
$guest_ids = [];
$is_empty = empty($requested_projects);
foreach (\request('_business_info')['info']['projects'] as $p_id => $p) {
$level = \request('_business_info')['info']['projects'][$p_id]['members'][\auth()->id()]['level'];
if (( $is_empty || isset($requested_projects[$p_id]))
&& $level > enum('levels.guest.id')) {
array_push($non_guest_ids, $p_id);
}
if (( $is_empty || isset($requested_projects[$p_id]))
&& $level == enum('levels.guest.id')) {
array_push($guest_ids, $p_id);
}
}
return ['non_guest_ids' => $non_guest_ids, 'guest_ids' => $guest_ids];
}
public function store($business, Request $request)
{
return Activity::create($request->merge(['business_id' => $business])->all());
}
public function delete()
{
}
}

1
app/Http/Controllers/AuthController.php

@ -13,7 +13,6 @@ use App\Http\Resources\UserResource;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Laravel\Lumen\Routing\Controller;
use Laravel\Socialite\Facades\Socialite; use Laravel\Socialite\Facades\Socialite;
use Illuminate\Session\TokenMismatchException; use Illuminate\Session\TokenMismatchException;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;

2
app/Http/Resources/TaskResource.php

@ -21,7 +21,7 @@ class TaskResource extends JsonResource
} }
} }
$resource['tags'] = $this->tags;
$resource['tags'] = $this->tags()->pluck('tag_id')->toArray();
$resource['works'] = $this->works; $resource['works'] = $this->works;
$resource['comments'] = $this->comments; $resource['comments'] = $this->comments;

73
app/Listeners/ActivityRegistration.php

@ -0,0 +1,73 @@
<?php
namespace App\Listeners;
use App\Events\ModelSaved;
use App\Models\Activity;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
class ActivityRegistration implements ShouldQueue
{
/**
* If your queue connection's after_commit configuration option is set to true,
* indicate that a particular queued listener should be dispatched after all database transactions closed
*
* @var boolean
*/
public $afterCommit = true;
/**
* The name of the connection the job should be sent to.
*
* @var string|null
*/
public $connection = 'redis';
/**
* The name of the queue the job should be sent to.
* It's just a name and if don't set it, laravel use default queue name in the connection
*
* @var string|null
*/
public $queue = 'activities';
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param ModelSaved $event
* @return void
*/
public function handle(ModelSaved $event)
{
Log::info('listener:'. json_encode($event->message));
$message = json_decode($event->message);
Activity::create([
'business_id' => $message->business,
'project_id' => $message->project,
'actor_id' => $message->auth,
'system_id' => $message->data->system_id,
'workflow_id' => $message->data->workflow_id,
'status_id' => $message->data->status_id,
'sprint_id' => $message->data->sprint_id,
'task_id' => $message->data->task_id ?? null,
'subject_id' => $message->data->subject_id ?? null,
'user_id' => $message->data->user_id,
'crud_id' => $message->data->crud_id,
'table_id' => enum('tables.'.$message->data->table_name.'.id'),
'original' => $message->data->original,
'diff' => $message->data->diff,
]);
}
}

31
app/Models/Activity.php

@ -2,8 +2,37 @@
namespace App\Models; namespace App\Models;
use App\Models\Model;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Activity extends Model class Activity extends Model
{ {
use HasFactory;
protected $fillable = [
'business_id', 'project_id', 'system_id', 'workflow_id', 'status_id', 'sprint_id',
'actor_id', 'task_id', 'subject_id', 'user_id', 'crud_id', 'table_id', 'original', 'diff'
];
public $casts = [
'original' => 'array',
'diff' => 'array',
];
public function scopeCreatesBefore($query, $date)
{
return $query->whereDate('created_at', '<=', Carbon::parse($date));
}
public function scopeCreatesAfter($query, $date)
{
return $query->whereDate('created_at', '>=', Carbon::parse($date));
}
public function scopeCreatesIn($query, $days)
{
return $days != "" ?
$query->whereDate('created_at', '>=', Carbon::now()->modify('-'.$days.' day')->toDate()) :
$query;
}
} }

33
app/Models/Model.php

@ -2,10 +2,7 @@
namespace App\Models; namespace App\Models;
use Anik\Amqp\Exchange;
use Anik\Amqp\Facades\Amqp;
use PhpAmqpLib\Wire\AMQPTable;
use Anik\Amqp\PublishableMessage;
use App\Events\ModelSaved;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
@ -194,21 +191,23 @@ class Model extends EloquentModel
'from' => env('CONTAINER_NAME'), 'from' => env('CONTAINER_NAME'),
]; ];
$message = new PublishableMessage(json_encode($payload));
// $message = new PublishableMessage(json_encode($payload));
$routers = [
"activity_exchange" => ["name" => "activity",],
"notif_exchange" => ["name" => "notif",],
"socket_exchange" => ["name" => "socket",],
];
foreach ($routers as $exchange => $properties) {
$message->setProperties(["application_headers" => new AMQPTable($properties)]);
$message->setExchange(new Exchange($exchange));
ModelSaved::dispatch(json_encode($payload));
Amqp::publish($message, "");
}
// $routers = [
// "activity_exchange" => ["name" => "activity",],
// "notif_exchange" => ["name" => "notif",],
// "socket_exchange" => ["name" => "socket",],
// ];
//
// foreach ($routers as $exchange => $properties) {
// $message->setProperties(["application_headers" => new AMQPTable($properties)]);
//
// $message->setExchange(new Exchange($exchange));
//
// Amqp::publish($message, "");
// }
} }
/** /**

2
app/Models/Task.php

@ -73,7 +73,7 @@ class Task extends Model
'title' => 'required|string|min:3|max:254', 'title' => 'required|string|min:3|max:254',
'description' => 'nullable|string|min:2|max:1000', 'description' => 'nullable|string|min:2|max:1000',
'priority' => 'nullable|numeric|between:1,10', 'priority' => 'nullable|numeric|between:1,10',
'estimated_time' => 'nullable|numeric|min:30',
'estimated_time' => 'bail|nullable|numeric',
'due_date' => 'bail|nullable|date|date_format:Y-m-d|after_or_equal:'. 'due_date' => 'bail|nullable|date|date_format:Y-m-d|after_or_equal:'.
((request()->method() === 'POST') ? date('yy-m-d') : $this->created_at->toDateString()), ((request()->method() === 'POST') ? date('yy-m-d') : $this->created_at->toDateString()),
'tags' => 'nullable|array', 'tags' => 'nullable|array',

4
app/Models/User.php

@ -5,13 +5,13 @@ namespace App\Models;
use App\Models\File; use App\Models\File;
use App\Models\Model; use App\Models\Model;
use App\Models\SoftDeletes; use App\Models\SoftDeletes;
use App\Models\ReportableRelation;
use Illuminate\Validation\Rule; use Illuminate\Validation\Rule;
use Illuminate\Http\UploadedFile; use Illuminate\Http\UploadedFile;
use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\HasMedia;
use App\Models\ReportableRelation;
use Illuminate\Auth\Authenticatable; use Illuminate\Auth\Authenticatable;
use Laravel\Lumen\Auth\Authorizable;
use Spatie\MediaLibrary\InteractsWithMedia; use Spatie\MediaLibrary\InteractsWithMedia;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Spatie\MediaLibrary\MediaCollections\Models\Media; use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;

5
app/Providers/EventServiceProvider.php

@ -2,6 +2,8 @@
namespace App\Providers; namespace App\Providers;
use App\Events\ModelSaved;
use App\Listeners\ActivityRegistration;
use Illuminate\Auth\Events\Registered; use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
@ -18,6 +20,9 @@ class EventServiceProvider extends ServiceProvider
Registered::class => [ Registered::class => [
SendEmailVerificationNotification::class, SendEmailVerificationNotification::class,
], ],
ModelSaved::class => [
ActivityRegistration::class
]
]; ];
/** /**

5
composer.json

@ -20,11 +20,6 @@
"jenssegers/agent": "^2.6", "jenssegers/agent": "^2.6",
"laravel/socialite": "^5.1", "laravel/socialite": "^5.1",
"laravel/framework": "^8.12", "laravel/framework": "^8.12",
"guzzlehttp/guzzle": "^7.0.1",
"laravel/legacy-factories": "^1",
"fruitcake/laravel-cors": "^2.0",
"laravel/lumen-framework": "^8.0",
"illuminate/notifications": "^8.0",
"league/flysystem-aws-s3-v3": "~1.0", "league/flysystem-aws-s3-v3": "~1.0",
"spatie/laravel-medialibrary": "^9.0", "spatie/laravel-medialibrary": "^9.0",
"spatie/laravel-query-builder": "^3.3", "spatie/laravel-query-builder": "^3.3",

2
config/app.php

@ -12,7 +12,7 @@ return [
'asset_url' => env('ASSET_URL', null), 'asset_url' => env('ASSET_URL', null),
'timezone' => 'UTC',
'timezone' => 'Asia/Tehran',
'locale' => 'fa', 'locale' => 'fa',

2
database/factories/BusinessFactory.php

@ -12,6 +12,6 @@ $factory->define(Business::class, function (Faker $faker) {
'slug' => Str::slug($name) . $faker->numberBetween(1, 100), 'slug' => Str::slug($name) . $faker->numberBetween(1, 100),
'wallet' => random_int(111111, 999999), 'wallet' => random_int(111111, 999999),
'color' => $faker->colorName, 'color' => $faker->colorName,
'calculated_at' => \Carbon\Carbon::now()->subMinutes(random_int(1, 1000)),
'calculated_at' => \Carbon\Carbon::now()->subDays(random_int(1, 31)),
]; ];
}); });

4
database/migrations/2020_08_18_085017_fingerprints.php

@ -19,8 +19,8 @@ class Fingerprints extends Migration
$table->string('agent'); $table->string('agent');
$table->ipAddress('ip'); $table->ipAddress('ip');
$table->string('os'); $table->string('os');
$table->decimal('latitude', 10, 2);
$table->decimal('longitude', 11, 2);
$table->decimal('latitude', 10, 4);
$table->decimal('longitude', 11, 4);
$table->char('token', 60)->unique(); $table->char('token', 60)->unique();
$table->timestamps(); $table->timestamps();
}); });

2
database/migrations/2020_08_18_085018_create_businesses_table.php

@ -23,7 +23,7 @@ class CreateBusinessesTable extends Migration
$table->string('description')->nullable(); $table->string('description')->nullable();
$table->json('cache')->nullable(); $table->json('cache')->nullable();
$table->boolean('has_avatar')->default(false); $table->boolean('has_avatar')->default(false);
$table->timestamp('calculated_at')->nullable();
$table->timestamp('calculated_at')->nullable()->index();
$table->timestamp('created_at')->nullable(); $table->timestamp('created_at')->nullable();
$table->timestamp('updated_at')->nullable(); $table->timestamp('updated_at')->nullable();
$table->timestamp('deleted_at')->nullable(); $table->timestamp('deleted_at')->nullable();

45
database/migrations/2021_03_06_085855_create_activities_table.php

@ -0,0 +1,45 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateActivitiesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('activities', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('business_id');
$table->unsignedBigInteger('project_id')->nullable();
$table->unsignedBigInteger('system_id')->nullable();
$table->unsignedBigInteger('workflow_id')->nullable();
$table->unsignedBigInteger('status_id')->nullable();
$table->unsignedBigInteger('sprint_id')->nullable();
$table->unsignedBigInteger('task_id')->nullable();
$table->unsignedBigInteger('subject_id')->nullable();//row id
$table->unsignedBigInteger('actor_id');
$table->unsignedBigInteger('user_id')->nullable();
$table->unsignedBigInteger('crud_id')->nullable();
$table->unsignedBigInteger('table_id')->nullable();
$table->json('original')->nullable(); // a unique identifier that represent the type of action
$table->json('diff')->nullable(); // all data that has been changed
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('activities');
}
}

36
database/migrations/2021_03_06_114918_create_failed_jobs_table.php

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateFailedJobsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('failed_jobs');
}
}

5
routes/api.php

@ -182,6 +182,11 @@ $router->group(['prefix' => 'businesses', 'middleware' => 'auth:api'], function
$router->delete('/', 'BusinessController@deleteUser'); $router->delete('/', 'BusinessController@deleteUser');
}); });
}); });
$router->group(['prefix' => 'activities'], function () use ($router) {
$router->post('/', 'ActivityController@store');
$router->get('/', 'ActivityController@index');
});
}); });
}); });

Loading…
Cancel
Save