<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\{Http,Hash,DB,Storage};
use App\Models\{User,Project,Plan,ServicePeriod,FormRevision,Correction,Payment,Order,Review,PointEntry,Ticket,Message,SmsOutbox,Attachment,OtpChallenge};
use App\Services\{Intake,ProjectFlow,Payments,Reviews,Dates,Settings};
class ClubTest extends TestCase {
 use RefreshDatabase;
 protected User $admin;protected User $customer;protected User $mentor;protected Plan $plan;protected Project $project;
 protected function setUp():void {parent::setUp();$this->seed();Http::preventStrayRequests();$this->admin=$this->user('admin','09111111111');$this->customer=$this->user('customer','09222222222');$this->mentor=$this->user('mentor','09333333333');$this->plan=Plan::where('kind','mentoring')->first();$this->plan->update(['price'=>1000000,'active'=>true]);$this->project=Project::create(['customer_id'=>$this->customer->id,'mentor_id'=>$this->mentor->id,'department_id'=>1,'plan_id'=>$this->plan->id,'name'=>'پروژه آزمایشی','status'=>'waiting_info','starts_at'=>now()->subDays(2),'expires_at'=>now()->addDays(14),'plan_snapshot'=>$this->plan->only(['id','name','days','price','quotas','version','features'])]);ServicePeriod::create(['project_id'=>$this->project->id,'starts_at'=>$this->project->starts_at,'expires_at'=>$this->project->expires_at,'snapshot'=>$this->project->plan_snapshot]);}
 private function user($role,$mobile):User{return User::create(['name'=>'کاربر آزمایشی '.$role,'mobile'=>$mobile,'password'=>'Testing-pass-1234','active'=>true,'role'=>$role,'department_id'=>1,'verified_at'=>now()]);}
 private function data():array{return ['business_name'=>'کسب‌وکار آزمایشی','site_title'=>'عنوان سایت','site_type'=>'store','contact_phone'=>'02112345678','products'=>[]];}
 public function test_public_auth_pages_render():void{foreach(['/login','/register','/verify']as $url)$this->get($url)->assertOk();$this->get('/')->assertRedirect('/login');}
 public function test_customer_and_admin_pages_render():void{
  foreach([$this->customer,$this->mentor,$this->admin]as $u){$this->actingAs($u);foreach(['/','/projects','/projects/'.$this->project->id,'/projects/'.$this->project->id.'/history','/tickets','/orders','/club','/account','/notifications','/plans?project='.$this->project->id]as $url)$this->get($url)->assertOk();}
  $this->actingAs($this->customer)->get('/projects/'.$this->project->id.'/intake')->assertOk();
  $this->actingAs($this->admin);foreach(['/admin','/admin/users','/admin/plans','/admin/sms','/admin/outbox','/admin/rules','/admin/missions','/admin/submissions','/admin/reviews','/admin/audit','/admin/settings','/admin/departments','/admin/export','/admin/users?edit='.$this->customer->id,'/admin/plans?edit='.$this->plan->id,'/admin/sms?edit=1','/admin/rules?edit=1']as $url)$this->get($url)->assertOk();
 }
 public function test_password_login_and_inactive_staff():void {$this->post('/login',['mobile'=>$this->customer->mobile,'password'=>'Testing-pass-1234'])->assertRedirect('/');$this->assertAuthenticatedAs($this->customer);$this->post('/logout');$this->mentor->update(['active'=>false]);$this->post('/login',['mobile'=>$this->mentor->mobile,'password'=>'Testing-pass-1234'])->assertSessionHasErrors('mobile');$this->actingAs($this->mentor)->get('/')->assertForbidden();}
 public function test_otp_single_use_attempt_limit_and_expiry():void {
  $code='123456';$o=OtpChallenge::create(['mobile'=>$this->customer->mobile,'code_hash'=>Hash::make($code),'expires_at'=>now()->addMinutes(3)]);
  $this->withSession(['otp_mobile'=>$o->mobile])->post('/verify',['code'=>'000000'])->assertSessionHasErrors('code');$this->assertEquals(1,$o->fresh()->attempts);
  $this->withSession(['otp_mobile'=>$o->mobile])->post('/verify',['code'=>$code])->assertRedirect('/');$this->assertNotNull($o->fresh()->consumed_at);$this->post('/logout');
  $this->withSession(['otp_mobile'=>$o->mobile])->post('/verify',['code'=>$code])->assertSessionHasErrors('code');
  $o->update(['consumed_at'=>null,'expires_at'=>now()->subSecond()]);$this->withSession(['otp_mobile'=>$o->mobile])->post('/verify',['code'=>$code])->assertSessionHasErrors('code');
  $o->update(['expires_at'=>now()->addMinutes(3),'attempts'=>5]);$this->withSession(['otp_mobile'=>$o->mobile])->post('/verify',['code'=>$code])->assertSessionHasErrors('code');
 }
 public function test_project_isolation_and_mentor_reassignment():void{$other=$this->user('customer','09444444444');$this->actingAs($other)->get('/projects/'.$this->project->id)->assertForbidden();$this->get('/projects/'.$this->project->id.'/history')->assertForbidden();$new=$this->user('mentor','09555555555');app(ProjectFlow::class)->assign($this->admin,$this->project,$new->id,'تغییر مسئول آزمایشی');$this->actingAs($this->mentor)->get('/projects/'.$this->project->id)->assertForbidden();$this->actingAs($new)->get('/projects/'.$this->project->id)->assertOk();}
 public function test_two_edits_and_stale_draft_do_not_burn_allowance():void{$service=app(Intake::class);$p=$service->submit($this->customer,$this->project,$this->data(),0);$this->assertEquals(0,$p->edits_used);foreach([1,2]as $i){$data=$this->data();$data['site_title']='عنوان ویرایش '.$i;$p=$service->submit($this->customer,$p,$data,$p->draft_version);$this->assertEquals($i,$p->edits_used);}$data['site_title']='ویرایش سوم';try{$service->submit($this->customer,$p,$data,$p->draft_version);$this->fail('Third edit accepted');}catch(\Illuminate\Validation\ValidationException $e){$this->assertEquals(2,$p->fresh()->edits_used);}$v=$service->draft($this->customer,$p,$data,$p->draft_version);try{$service->draft($this->customer,$p,$data,$v-1);$this->fail('Stale accepted');}catch(\Illuminate\Validation\ValidationException $e){$this->assertEquals(2,$p->fresh()->edits_used);}$this->assertEquals(3,FormRevision::count());}
 public function test_correction_scope_preserves_edit_limit():void{$s=app(Intake::class);$p=$s->submit($this->customer,$this->project,$this->data(),0);$p->update(['edits_used'=>2]);Correction::create(['project_id'=>$p->id,'user_id'=>$this->mentor->id,'fields'=>['site_title'],'reason'=>'عنوان کامل لازم است']);$d=$this->data();$d['site_title']='عنوان کامل';$p=$s->submit($this->customer,$p,$d,$p->draft_version);$this->assertEquals(2,$p->edits_used);$this->assertEquals('correction',FormRevision::latest('id')->first()->kind);}
 public function test_quota_and_expired_submission_rejected():void{$d=$this->data();$d['products']=array_fill(0,11,['name'=>'محصول']);try{app(Intake::class)->submit($this->customer,$this->project,$d,0);$this->fail('Quota bypass');}catch(\Illuminate\Validation\ValidationException $e){$this->assertEquals(0,FormRevision::count());}$this->project->update(['expires_at'=>now()]);$this->expectException(\Symfony\Component\HttpKernel\Exception\HttpException::class);app(Intake::class)->submit($this->customer,$this->project,$this->data(),0);}
 public function test_no_ticket_before_form_and_no_reply_after_expiry():void{$this->actingAs($this->customer);$payload=['subject'=>'گفت‌وگوی آزمایشی','kind'=>'mentoring','body'=>'پیام آزمایشی مشتری','project_id'=>$this->project->id,'request_key'=>(string)\Illuminate\Support\Str::uuid()];$this->post('/tickets',$payload)->assertUnprocessable();$this->project->update(['submitted_at'=>now(),'status'=>'delivered']);$this->post('/tickets',$payload)->assertRedirect();$t=Ticket::first();$this->get('/tickets/'.$t->id)->assertOk();$this->project->update(['expires_at'=>now()]);$payload['request_key']=(string)\Illuminate\Support\Str::uuid();$this->post('/tickets/'.$t->id.'/reply',$payload)->assertUnprocessable();$this->get('/tickets/'.$t->id)->assertOk();$this->assertNotEquals('resolved',$t->fresh()->status);}
 public function test_payment_amount_mismatch_and_idempotent_renewal():void {Settings::set('zibal_merchant','zibal',true);$s=app(Payments::class);$order=$s->order($this->customer,$this->project,$this->plan,'renewal');$old=$this->project->expires_at->copy();$pay=Payment::create(['order_id'=>$order->id,'track_id'=>'12345','amount'=>$order->amount]);Http::fake(['*/verify'=>Http::sequence()->push(['result'=>100,'amount'=>1,'refNumber'=>'REF'])->push(['result'=>100,'amount'=>$order->amount,'refNumber'=>'REF','orderId'=>$order->id])]);$s->verify($pay);$this->assertEquals('mismatch',$pay->fresh()->status);$this->assertEquals('pending',$order->fresh()->status);$s->verify($pay->fresh());$s->verify($pay->fresh());$this->assertEquals(2,ServicePeriod::count());$this->assertEquals($old->addDays($this->plan->days)->timestamp,$this->project->fresh()->expires_at->timestamp);$this->assertEquals('paid',$order->fresh()->status);$this->actingAs($this->customer)->get('/orders/'.$order->id)->assertOk();}
 public function test_paid_order_snapshot_and_paused_project():void{Settings::set('zibal_merchant','zibal',true);$s=app(Payments::class);$order=$s->order($this->customer,$this->project,$this->plan,'renewal');$this->plan->update(['price'=>9999999]);$this->assertEquals(1000000,$order->amount);$this->project->update(['paused_at'=>now()]);$p=Payment::create(['order_id'=>$order->id,'track_id'=>'333','amount'=>$order->amount]);Http::fake(['*/verify'=>Http::response(['result'=>100,'amount'=>$order->amount])]);$s->verify($p);$this->assertEquals('paid',$order->fresh()->status);$this->assertEquals('needs_review',$order->fresh()->fulfillment_status);$this->assertEquals(1,ServicePeriod::count());}
 public function test_review_invite_and_points_are_idempotent():void {$s=app(Reviews::class);$s->invite($this->project);$s->invite($this->project);$this->assertEquals(1,Review::count());$review=Review::first();$review->update(['kind'=>'text','body'=>'ناراضی از پاسخ‌گویی ولی نظر معتبر است','status'=>'pending','submitted_at'=>now(),'publish_consent'=>false]);$s->moderate($this->admin,$review,'accepted','نظر معتبر بدون رضایت انتشار');$s->moderate($this->admin,$review,'accepted','نظر معتبر بدون رضایت انتشار');$this->assertEquals(50,PointEntry::sum('points'));$review->update(['kind'=>'video','status'=>'pending']);$s->moderate($this->admin,$review,'accepted','ویدئوی معتبر تأیید می‌شود');$this->assertEquals(200,PointEntry::sum('points'));$this->assertEquals(2,PointEntry::count());$this->actingAs($this->customer)->get('/reviews/'.$review->id)->assertOk();}
 public function test_jalali_boundaries_and_invalid_dates():void{$this->assertEquals('2025-03-21 20:30',Dates::parse('۱۴۰۴/۰۱/۰۱',true)->format('Y-m-d H:i'));$this->expectException(\Illuminate\Validation\ValidationException::class);Dates::parse('۱۴۰۴/۱۲/۳۰');}
 public function test_secrets_are_encrypted_and_no_public_file_leak():void{$this->project->update(['credentials'=>['password'=>'private-wordpress-pass']]);$this->assertStringNotContainsString('private-wordpress-pass',DB::table('projects')->where('id',$this->project->id)->value('credentials'));$this->actingAs($this->customer)->get('/projects/'.$this->project->id)->assertDontSee('private-wordpress-pass');Storage::fake('private');Storage::disk('private')->put('test.txt','test');$a=Attachment::create(['user_id'=>$this->customer->id,'project_id'=>$this->project->id,'path'=>'test.txt','name'=>'test.txt','mime'=>'text/plain','size'=>4,'context'=>'form']);$other=$this->user('customer','09444444444');$this->actingAs($other)->get('/files/'.$a->id)->assertForbidden();}
 public function test_idle_view_does_not_reset_effective_activity():void{$this->project->update(['starts_at'=>now()->subDays(8)]);$this->assertEquals('warning',$this->project->health());$this->actingAs($this->mentor)->get('/projects/'.$this->project->id)->assertOk();$this->assertNull($this->project->fresh()->last_activity_at);}
 public function test_wizard_steps_and_product_editor_render_and_save():void {
  $this->actingAs($this->customer);
  $c=\Livewire\Livewire::test(\App\Livewire\IntakeWizard::class,['project'=>$this->project]);
  $c->set('data.site_type','company')->call('go',7)->assertSet('step',7)->call('go',6)->assertSet('step',5);
  $c->set('data.site_type','store')->call('go',7)->call('addItem','products')->set('data.products.0.name','محصول نمونه')->call('addVariant',0)->call('copyItem','products',0)->call('moveItem','products',1,-1)->call('go',10)->assertSee('محصول نمونه');
 }
 public function test_requested_project_activation_jalali_and_department_scope():void {
  $this->actingAs($this->customer)->post('/projects',['name'=>'درخواست مشتری'])->assertRedirect();$p=Project::latest('id')->first();$this->assertEquals('requested',$p->status);
  $this->actingAs($this->admin)->post('/projects/'.$p->id.'/activate',['mentor_id'=>$this->mentor->id,'plan_id'=>$this->plan->id,'start_date'=>'۱۴۰۵/۰۶/۱۶','end_date'=>'۱۴۰۵/۰۷/۱۶'])->assertRedirect();$this->assertEquals('waiting_info',$p->fresh()->status);$this->assertEquals(1,$p->periods()->count());
  $manager=$this->user('manager','09666666666');$dept=\App\Models\Department::create(['name'=>'بخش دوم']);$other=$this->user('customer','09777777777');$other->update(['department_id'=>$dept->id]);
  $this->actingAs($manager)->post('/projects',['name'=>'نام پروژه','customer_id'=>$other->id,'mentor_id'=>$this->mentor->id,'plan_id'=>$this->plan->id,'start_date'=>'۱۴۰۵/۰۶/۱۶','end_date'=>'۱۴۰۵/۰۷/۱۶'])->assertForbidden();
 }
 public function test_renewal_brief_is_separate_and_future_capacity_unavailable():void {
  $s=app(Payments::class);$o=$s->order($this->customer,$this->project,$this->plan,'renewal');$period=ServicePeriod::create(['project_id'=>$this->project->id,'order_id'=>$o->id,'starts_at'=>now()->addDay(),'expires_at'=>now()->addDays(15),'snapshot'=>$o->snapshot]);
  $this->actingAs($this->customer)->get('/periods/'.$period->id)->assertForbidden();$period->update(['starts_at'=>now()->subMinute()]);$this->get('/periods/'.$period->id)->assertOk();$this->project->update(['edits_used'=>2]);
  $a=app(\App\Services\Addenda::class)->save($this->customer,$period,['additional_notes'=>'صفحه جدید درباره خدمات'],0,true);$this->assertEquals(2,$this->project->fresh()->edits_used);$this->assertNotNull($a->submitted_at);$this->actingAs($this->mentor)->get('/periods/'.$period->id)->assertOk();
 }
 public function test_provider_201_recovers_only_from_verified_inquiry():void {Settings::set('zibal_merchant','zibal',true);$s=app(Payments::class);$o=$s->order($this->customer,$this->project,$this->plan,'renewal');$p=Payment::create(['order_id'=>$o->id,'track_id'=>'991','amount'=>$o->amount]);Http::fake(['*/verify'=>Http::response(['result'=>201]),'*/inquiry'=>Http::response(['result'=>100,'status'=>1,'amount'=>$o->amount,'orderId'=>$o->id,'refNumber'=>'BANKREF'])]);$s->verify($p);$this->assertEquals('verified',$p->fresh()->status);$this->assertEquals(2,ServicePeriod::count());}
 public function test_gateway_callback_does_not_trust_success_query():void {Settings::set('zibal_merchant','zibal',true);$s=app(Payments::class);$o=$s->order($this->customer,$this->project,$this->plan,'renewal');Payment::create(['order_id'=>$o->id,'track_id'=>'992','amount'=>$o->amount]);Http::fake(['*/verify'=>Http::response(['result'=>202])]);$this->get('/payments/callback?trackId=992&success=1&amount='.$o->amount)->assertRedirect();$this->assertEquals('pending',$o->fresh()->status);$this->assertEquals(1,ServicePeriod::count());}
 public function test_sms_outage_and_stale_expiry_do_not_repeat():void {Settings::set('ippanel_key','test',true);Settings::set('ippanel_from','+983000');$t=\App\Models\SmsTemplate::where('event','ending')->first();$t->update(['pattern_code'=>'test-pattern']);app(\App\Services\Notify::class)->event('ending',$this->project,[],'ending:once');$box=SmsOutbox::where('sms_template_id',$t->id)->first();$old=SmsOutbox::count();app(\App\Services\Notify::class)->event('ending',$this->project,[],'ending:once');$this->assertEquals($old,SmsOutbox::count());Http::fake(['*'=>Http::response([],503)]);(new \App\Jobs\SendSms($box->id))->handle(app(\App\Services\SmsGateway::class));$this->assertEquals('needs_review',$box->fresh()->status);$this->project->update(['expires_at'=>now()->addDays(45)]);$box->refresh()->update(['status'=>'pending']);(new \App\Jobs\SendSms($box->id))->handle(app(\App\Services\SmsGateway::class));$this->assertEquals('cancelled',$box->fresh()->status);}
 public function test_filament_and_review_media_access_are_scoped():void {$this->actingAs($this->customer)->get('/management/operations')->assertForbidden();$this->actingAs($this->admin)->get('/management/operations')->assertOk();$a=Attachment::create(['user_id'=>$this->customer->id,'project_id'=>$this->project->id,'context'=>'review','path'=>'review/private.mp4','name'=>'private.mp4','mime'=>'video/mp4','size'=>1]);$this->actingAs($this->mentor)->get('/files/'.$a->id)->assertForbidden();}
 public function test_livewire_refuses_variant_duplicates_and_unowned_files():void {$data=$this->data();$data['products']=[['name'=>'محصول','variants'=>[['option'=>'آبی','price'=>120],['option'=>'آبی','price'=>100]]]];try{app(Intake::class)->submit($this->customer,$this->project,$data,0);$this->fail('Duplicate combination accepted');}catch(\Illuminate\Validation\ValidationException $e){$this->assertEquals(0,FormRevision::count());}$data['products']=[['name'=>'محصول','image_file_id'=>999]];$this->expectException(\Symfony\Component\HttpKernel\Exception\HttpException::class);app(Intake::class)->submit($this->customer,$this->project,$data,0);}
 public function test_manual_gift_and_pause_resume_preserve_history():void {$flow=app(ProjectFlow::class);$old=$this->project->expires_at->copy();$flow->transition($this->admin,$this->project,'pause','توقف آزمایشی');$this->travel(2)->days();$flow->transition($this->admin,$this->project->fresh(),'resume','شروع دوباره');$this->assertEquals($old->addDays(2)->timestamp,$this->project->fresh()->expires_at->timestamp);$flow->gift($this->admin,$this->project->fresh(),3,'هدیه همراهی مشتری');$this->assertEquals(2,ServicePeriod::count());$this->assertEquals(0,Payment::count());}

 public function test_customer_followups_and_internal_notes_do_not_reset_reply_clock():void {
  $this->project->update(['submitted_at'=>now()]);$this->actingAs($this->customer)->post('/tickets',['subject'=>'منتظر پاسخ','kind'=>'mentoring','body'=>'اولین پیام مشتری','project_id'=>$this->project->id,'request_key'=>(string)\Illuminate\Support\Str::uuid()]);$t=Ticket::first();$since=$t->waiting_since->timestamp;
  $this->travel(2)->hours();$this->post('/tickets/'.$t->id.'/reply',['body'=>'پیگیری دوباره مشتری','request_key'=>(string)\Illuminate\Support\Str::uuid()])->assertRedirect();$this->assertEquals($since,$t->fresh()->waiting_since->timestamp);
  $this->actingAs($this->mentor)->post('/tickets/'.$t->id.'/reply',['body'=>'یادداشت برای همکاران','internal'=>1,'request_key'=>(string)\Illuminate\Support\Str::uuid()])->assertRedirect();$this->assertEquals('waiting_mentor',$t->fresh()->status);$this->assertEquals($since,$t->fresh()->waiting_since->timestamp);
 }
 public function test_financial_service_recovery_runs_once():void {
  Settings::set('zibal_merchant','zibal',true);$s=app(Payments::class);$order=$s->order($this->customer,$this->project,$this->plan,'renewal');$this->project->update(['paused_at'=>now()]);$payment=Payment::create(['order_id'=>$order->id,'track_id'=>'recover-1','amount'=>$order->amount]);Http::fake(['*/verify'=>Http::response(['result'=>100,'amount'=>$order->amount,'refNumber'=>'BANK-RECEIPT'])]);$s->verify($payment);$this->assertEquals('needs_review',$order->fresh()->fulfillment_status);$this->project->update(['paused_at'=>null]);$this->actingAs($this->admin)->post('/orders/'.$order->id.'/resolve',['action'=>'recover','reason'=>'مشکل پروژه رفع و پرداخت بررسی شد'])->assertRedirect();$this->assertEquals(2,ServicePeriod::count());$this->post('/orders/'.$order->id.'/resolve',['action'=>'recover','reason'=>'بررسی دوباره همان پرداخت'])->assertUnprocessable();$this->assertEquals(2,ServicePeriod::count());
 }

 public function test_registration_otp_creates_same_customer_and_pending_staff():void {
  $code=null;$gateway=\Mockery::mock(\App\Services\SmsGateway::class);$gateway->shouldReceive('send')->twice()->withArgs(function($template,$mobile,$data)use(&$code){$code=$data['otp'];return true;})->andReturn('test-outbox');$this->app->instance(\App\Services\SmsGateway::class,$gateway);
  foreach([['customer','09444444444'],['staff','09555555555']] as [$kind,$mobile]){
   $this->post('/register',['name'=>'عضو آزمایشی تازه','mobile'=>$mobile,'kind'=>$kind,'password'=>'Testing-pass-1234','password_confirmation'=>'Testing-pass-1234'])->assertRedirect('/verify');
   $this->assertDatabaseMissing('users',['mobile'=>$mobile]);$this->post('/verify',['code'=>$code])->assertRedirect($kind==='customer'?'/':'/login');$u=User::where('mobile',$mobile)->firstOrFail();$this->assertNotNull($u->verified_at);$this->assertEquals($kind==='customer',$u->active);$this->assertEquals($kind==='customer'?'customer':'mentor',$u->role);
   if($kind==='customer'){$this->assertAuthenticatedAs($u);$this->post('/logout');$this->post('/login',['mobile'=>$mobile,'password'=>'Testing-pass-1234'])->assertRedirect('/');$this->assertAuthenticatedAs($u);$this->post('/logout');}else{$this->assertGuest();}
  }
 }
 public function test_expired_renewal_begins_at_verification_and_logo_support_remains():void {
  $this->project->update(['expires_at'=>now()->subHour()]);Settings::set('zibal_merchant','zibal',true);$s=app(Payments::class);$o=$s->order($this->customer,$this->project,$this->plan,'renewal');$pay=Payment::create(['order_id'=>$o->id,'track_id'=>'expired-renewal','amount'=>$o->amount]);Http::fake(['*/verify'=>Http::response(['result'=>100,'amount'=>$o->amount,'refNumber'=>'REF'])]);$s->verify($pay);$period=ServicePeriod::where('order_id',$o->id)->firstOrFail();$this->assertEquals(now()->timestamp,$period->starts_at->timestamp);$this->assertEquals(now()->addDays($this->plan->days)->timestamp,$period->expires_at->timestamp);
  $this->project->update(['expires_at'=>now()->subHour()]);$logo=Plan::where('kind','logo')->first();$logo->update(['price'=>500000,'active'=>true]);$order=$s->order($this->customer,$this->project,$logo,'logo');$order->update(['status'=>'paid','fulfillment_status'=>'paid']);
  $this->actingAs($this->customer)->get('/orders/'.$order->id)->assertOk();$this->post('/orders/'.$order->id.'/logo',['action'=>'brief','description'=>'شرح برند برای طراحی لوگو'])->assertRedirect();$this->post('/tickets',['subject'=>'پشتیبانی لوگو','kind'=>'logo','body'=>'پیگیری فایل طراحی لوگو','project_id'=>$this->project->id,'request_key'=>(string)\Illuminate\Support\Str::uuid()])->assertRedirect();
 }

}
