Invoicing Feature Complete #8
|
|
@ -2,13 +2,20 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
use App\Services\Invoice\InvoiceDataService;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use function dd;
|
|
||||||
use function redirect;
|
use function redirect;
|
||||||
|
|
||||||
class DashboardController extends Controller
|
class DashboardController extends Controller
|
||||||
{
|
{
|
||||||
|
protected InvoiceDataService $invoiceService;
|
||||||
|
|
||||||
|
public function __construct(InvoiceDataService $invoiceService)
|
||||||
|
{
|
||||||
|
$this->invoiceService = $invoiceService;
|
||||||
|
}
|
||||||
|
|
||||||
public function profile()
|
public function profile()
|
||||||
{
|
{
|
||||||
return view('dashboard.profile');
|
return view('dashboard.profile');
|
||||||
|
|
@ -25,7 +32,20 @@ class DashboardController extends Controller
|
||||||
return redirect('/schools/'.Auth::user()->school->id);
|
return redirect('/schools/'.Auth::user()->school->id);
|
||||||
}
|
}
|
||||||
$possibilities = Auth::user()->possibleSchools();
|
$possibilities = Auth::user()->possibleSchools();
|
||||||
if (count($possibilities) < 1) return view('schools.create');
|
if (count($possibilities) < 1) {
|
||||||
|
return view('schools.create');
|
||||||
|
}
|
||||||
|
|
||||||
return view('dashboard.select_school', ['possibilities' => $possibilities]);
|
return view('dashboard.select_school', ['possibilities' => $possibilities]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function my_invoice()
|
||||||
|
{
|
||||||
|
if (! Auth::user()->school_id) {
|
||||||
|
return redirect()->route('dashboard')->with('error', 'You do not have a school to get an invoice for');
|
||||||
|
}
|
||||||
|
$invoiceData = $this->invoiceService->allData(Auth::user()->school_id);
|
||||||
|
$school = Auth::user()->school;
|
||||||
|
return view('dashboard.invoice', compact('school', 'invoiceData'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Services\AuditionService;
|
use App\Services\AuditionService;
|
||||||
|
use App\Services\Invoice\InvoiceDataService;
|
||||||
use App\Services\TabulationService;
|
use App\Services\TabulationService;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Session;
|
use Illuminate\Support\Facades\Session;
|
||||||
|
|
@ -11,16 +12,22 @@ class TestController extends Controller
|
||||||
{
|
{
|
||||||
protected $scoringGuideCacheService;
|
protected $scoringGuideCacheService;
|
||||||
protected $tabulationService;
|
protected $tabulationService;
|
||||||
|
protected $invoiceService;
|
||||||
|
|
||||||
public function __construct(AuditionService $scoringGuideCacheService, TabulationService $tabulationService)
|
public function __construct(
|
||||||
{
|
AuditionService $scoringGuideCacheService,
|
||||||
|
TabulationService $tabulationService,
|
||||||
|
InvoiceDataService $invoiceService
|
||||||
|
) {
|
||||||
$this->scoringGuideCacheService = $scoringGuideCacheService;
|
$this->scoringGuideCacheService = $scoringGuideCacheService;
|
||||||
$this->tabulationService = $tabulationService;
|
$this->tabulationService = $tabulationService;
|
||||||
|
$this->invoiceService = $invoiceService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function flashTest(Request $request)
|
public function flashTest(Request $request)
|
||||||
{
|
{
|
||||||
$auditions = $this->tabulationService->getAuditionsWithStatus();
|
$lines = $this->invoiceService->getLines(12);
|
||||||
return view('test', compact('auditions'));
|
$totalFees = $this->invoiceService->getGrandTotal(12);
|
||||||
|
return view('test', compact('lines','totalFees'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,12 @@ class School extends Model
|
||||||
{
|
{
|
||||||
return $this->hasMany(User::class);
|
return $this->hasMany(User::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function users(): HasMany
|
public function users(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(User::class);
|
return $this->hasMany(User::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function emailDomains(): HasMany
|
public function emailDomains(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(SchoolEmailDomain::class);
|
return $this->hasMany(SchoolEmailDomain::class);
|
||||||
|
|
@ -30,12 +32,13 @@ class School extends Model
|
||||||
{
|
{
|
||||||
$img = "https://ui-avatars.com/api/?background=$bg_color&color=$text_color&name=";
|
$img = "https://ui-avatars.com/api/?background=$bg_color&color=$text_color&name=";
|
||||||
$img .= substr($this->name, 0, 1);
|
$img .= substr($this->name, 0, 1);
|
||||||
|
|
||||||
return $img;
|
return $img;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function students(): HasMany
|
public function students(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(Student::class);
|
return $this->hasMany(Student::class)->orderBy('last_name')->orderBy('first_name');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function entries(): HasManyThrough
|
public function entries(): HasManyThrough
|
||||||
|
|
@ -48,5 +51,4 @@ class School extends Model
|
||||||
'id',
|
'id',
|
||||||
'id');
|
'id');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Services\EntryService;
|
||||||
|
use App\Services\Invoice\InvoiceDataService;
|
||||||
|
use App\Services\Invoice\InvoiceOneFeePerEntry;
|
||||||
|
use App\Services\Invoice\InvoiceOneFeePerStudent;
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use function auditionSetting;
|
||||||
|
|
||||||
|
class InvoiceDataServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Register services.
|
||||||
|
*/
|
||||||
|
public function register(): void
|
||||||
|
{
|
||||||
|
$this->app->singleton(InvoiceDataService::class, function ($app) {
|
||||||
|
// Default binding, can be overridden in booth method
|
||||||
|
return new InvoiceOneFeePerEntry($app->make(EntryService::class));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bootstrap services.
|
||||||
|
*/
|
||||||
|
public function boot(): void
|
||||||
|
{
|
||||||
|
$this->app->singleton(InvoiceDataService::class, function ($app) {
|
||||||
|
return match (auditionSetting('fee_structure')) {
|
||||||
|
'oneFeePerEntry' => new InvoiceOneFeePerEntry($app->make(EntryService::class)),
|
||||||
|
'oneFeePerStudent' => new InvoiceOneFeePerStudent($app->make(EntryService::class)),
|
||||||
|
default => throw new \Exception('Unknown Invoice Method'),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Services\Invoice;
|
|
||||||
|
|
||||||
use App\Models\School;
|
|
||||||
|
|
||||||
use function auditionSetting;
|
|
||||||
|
|
||||||
class InvoiceAllStudentsPay implements InvoiceDataService
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Create a new class instance.
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLines(School $school)
|
|
||||||
{
|
|
||||||
// TODO: Implement getLines() method.
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLinesTotal(School $school)
|
|
||||||
{
|
|
||||||
// TODO: Implement getLinesTotal() method.
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLateFeesTotal(School $school)
|
|
||||||
{
|
|
||||||
// TODO: Implement getLateFeesTotal() method.
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSchoolFeeTotal(School $school)
|
|
||||||
{
|
|
||||||
if (! auditionSetting('school_fee')) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return auditionSetting('school_fee');
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getGrandTotal(School $school)
|
|
||||||
{
|
|
||||||
// TODO: Implement getGrandTotal() method.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,17 +2,17 @@
|
||||||
|
|
||||||
namespace App\Services\Invoice;
|
namespace App\Services\Invoice;
|
||||||
|
|
||||||
use App\Models\School;
|
|
||||||
|
|
||||||
interface InvoiceDataService
|
interface InvoiceDataService
|
||||||
{
|
{
|
||||||
public function getLines(School $school);
|
public function allData($schoolId);
|
||||||
|
|
||||||
public function getLinesTotal(School $school);
|
public function getLines($schoolId);
|
||||||
|
|
||||||
public function getLateFeesTotal(School $school);
|
public function getLinesTotal($schoolId);
|
||||||
|
|
||||||
public function getSchoolFeeTotal(School $school);
|
public function getLateFeesTotal($schoolId);
|
||||||
|
|
||||||
public function getGrandTotal(School $school);
|
public function getSchoolFeeTotal($schoolId);
|
||||||
|
|
||||||
|
public function getGrandTotal($schoolId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\Invoice;
|
||||||
|
|
||||||
|
use App\Models\School;
|
||||||
|
use App\Services\EntryService;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
|
||||||
|
use function auditionSetting;
|
||||||
|
|
||||||
|
class InvoiceOneFeePerEntry implements InvoiceDataService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a new class instance.
|
||||||
|
*/
|
||||||
|
protected $entryService;
|
||||||
|
|
||||||
|
public function __construct(EntryService $entryService)
|
||||||
|
{
|
||||||
|
$this->entryService = $entryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function allData($schoolId)
|
||||||
|
{
|
||||||
|
static $schoolInvoiceData = [];
|
||||||
|
|
||||||
|
if (Arr::has($schoolInvoiceData, $schoolId)) {
|
||||||
|
return $schoolInvoiceData[$schoolId];
|
||||||
|
}
|
||||||
|
$school = School::findOrFail($schoolId);
|
||||||
|
|
||||||
|
$invoiceData['lines'] = [];
|
||||||
|
$invoiceData['linesTotal'] = 0;
|
||||||
|
$invoiceData['lateFeesTotal'] = 0;
|
||||||
|
/** @noinspection PhpArrayIndexImmediatelyRewrittenInspection */
|
||||||
|
$invoiceData['grandTotal'] = 0;
|
||||||
|
|
||||||
|
$entries = $school->entries()->with('audition')->orderBy('created_at', 'desc')->get()->groupBy('student_id');
|
||||||
|
foreach ($school->students as $student) {
|
||||||
|
foreach ($entries[$student->id] as $entry) {
|
||||||
|
$entryFee = $entry->audition->entry_fee / 100;
|
||||||
|
$lateFee = $this->entryService->entryIsLate($entry) ? auditionSetting('late_fee') / 100 : 0;
|
||||||
|
|
||||||
|
$invoiceData['lines'][] = [
|
||||||
|
'student_name' => $student->full_name(true),
|
||||||
|
'audition' => $entry->audition->name,
|
||||||
|
'entry_timestamp' => $entry->created_at,
|
||||||
|
'entry_fee' => $entryFee,
|
||||||
|
'late_fee' => $lateFee,
|
||||||
|
];
|
||||||
|
$invoiceData['linesTotal'] += $entryFee;
|
||||||
|
$invoiceData['lateFeesTotal'] += $lateFee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// School Fee Total
|
||||||
|
if (! auditionSetting('school_fee')) {
|
||||||
|
$invoiceData['schoolFeeTotal'] = 0;
|
||||||
|
} else {
|
||||||
|
$invoiceData['schoolFeeTotal'] = auditionSetting('school_fee') / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoiceData['grandTotal'] = $invoiceData['linesTotal'] + $invoiceData['lateFeesTotal'] + $invoiceData['schoolFeeTotal'];
|
||||||
|
$schoolInvoiceData[$school->id] = $invoiceData;
|
||||||
|
|
||||||
|
return $invoiceData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLines($schoolId)
|
||||||
|
{
|
||||||
|
return $this->allData($schoolId)['lines'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLinesTotal($schoolId)
|
||||||
|
{
|
||||||
|
return $this->allData($schoolId)['linesTotal'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLateFeesTotal($schoolId)
|
||||||
|
{
|
||||||
|
return $this->allData($schoolId)['lateFeesTotal'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSchoolFeeTotal($schoolId)
|
||||||
|
{
|
||||||
|
return $this->allData($schoolId)['schoolFeeTotal'];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGrandTotal($schoolId)
|
||||||
|
{
|
||||||
|
return $this->allData($schoolId)['grandTotal'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\Invoice;
|
||||||
|
|
||||||
|
use App\Models\School;
|
||||||
|
use App\Services\EntryService;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
|
||||||
|
use function auditionSetting;
|
||||||
|
|
||||||
|
class InvoiceOneFeePerStudent implements InvoiceDataService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a new class instance.
|
||||||
|
*/
|
||||||
|
protected $entryService;
|
||||||
|
|
||||||
|
public function __construct(EntryService $entryService)
|
||||||
|
{
|
||||||
|
$this->entryService = $entryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function allData($schoolId)
|
||||||
|
{
|
||||||
|
static $schoolInvoiceData = [];
|
||||||
|
|
||||||
|
if (Arr::has($schoolInvoiceData, $schoolId)) {
|
||||||
|
return $schoolInvoiceData[$schoolId];
|
||||||
|
}
|
||||||
|
$school = School::findOrFail($schoolId);
|
||||||
|
|
||||||
|
$invoiceData['lines'] = [];
|
||||||
|
$invoiceData['linesTotal'] = 0;
|
||||||
|
$invoiceData['lateFeesTotal'] = 0;
|
||||||
|
/** @noinspection PhpArrayIndexImmediatelyRewrittenInspection */
|
||||||
|
$invoiceData['grandTotal'] = 0;
|
||||||
|
|
||||||
|
$entries = $school->entries()->with('audition')->orderBy('created_at', 'desc')->get()->groupBy('student_id');
|
||||||
|
foreach ($school->students as $student) {
|
||||||
|
$firstEntryForStudent = true;
|
||||||
|
foreach ($entries[$student->id] as $entry) {
|
||||||
|
if ($firstEntryForStudent) {
|
||||||
|
$entryFee = $entry->audition->entry_fee / 100;
|
||||||
|
$lateFee = $this->entryService->entryIsLate($entry) ? auditionSetting('late_fee') / 100 : 0;
|
||||||
|
} else {
|
||||||
|
$entryFee = 0;
|
||||||
|
$lateFee = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoiceData['lines'][] = [
|
||||||
|
'student_name' => $student->full_name(true),
|
||||||
|
'audition' => $entry->audition->name,
|
||||||
|
'entry_timestamp' => $entry->created_at,
|
||||||
|
'entry_fee' => $entryFee,
|
||||||
|
'late_fee' => $lateFee,
|
||||||
|
];
|
||||||
|
$invoiceData['linesTotal'] += $entryFee;
|
||||||
|
$invoiceData['lateFeesTotal'] += $lateFee;
|
||||||
|
$firstEntryForStudent = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// School Fee Total
|
||||||
|
if (! auditionSetting('school_fee')) {
|
||||||
|
$invoiceData['schoolFeeTotal'] = 0;
|
||||||
|
} else {
|
||||||
|
$invoiceData['schoolFeeTotal'] = auditionSetting('school_fee') / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
$invoiceData['grandTotal'] = $invoiceData['linesTotal'] + $invoiceData['lateFeesTotal'] + $invoiceData['schoolFeeTotal'];
|
||||||
|
$schoolInvoiceData[$school->id] = $invoiceData;
|
||||||
|
|
||||||
|
return $invoiceData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLines($schoolId)
|
||||||
|
{
|
||||||
|
return $this->allData($schoolId)['lines'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLinesTotal($schoolId)
|
||||||
|
{
|
||||||
|
return $this->allData($schoolId)['linesTotal'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLateFeesTotal($schoolId)
|
||||||
|
{
|
||||||
|
return $this->allData($schoolId)['lateFeesTotal'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSchoolFeeTotal($schoolId)
|
||||||
|
{
|
||||||
|
return $this->allData($schoolId)['schoolFeeTotal'];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGrandTotal($schoolId)
|
||||||
|
{
|
||||||
|
return $this->allData($schoolId)['grandTotal'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,4 +3,5 @@
|
||||||
return [
|
return [
|
||||||
App\Providers\AppServiceProvider::class,
|
App\Providers\AppServiceProvider::class,
|
||||||
App\Providers\FortifyServiceProvider::class,
|
App\Providers\FortifyServiceProvider::class,
|
||||||
|
App\Providers\InvoiceDataServiceProvider::class,
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
@props(['school', 'invoiceData'])
|
||||||
|
|
||||||
|
<x-layout.app>
|
||||||
|
<x-slot:page_title>Invoice - {{ $school->name }}</x-slot:page_title>
|
||||||
|
@php( dump($invoiceData ))
|
||||||
|
<x-table.table class="mt-6">
|
||||||
|
<x-slot:title>Invoice</x-slot:title>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<x-table.th>Student Name</x-table.th>
|
||||||
|
<x-table.th>Audition</x-table.th>
|
||||||
|
<x-table.th>Entry Timestamp</x-table.th>
|
||||||
|
<x-table.th>Entry Fee</x-table.th>
|
||||||
|
<x-table.th>Late Fee</x-table.th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<x-table.body>
|
||||||
|
@foreach($invoiceData['lines'] as $line)
|
||||||
|
<tr>
|
||||||
|
<x-table.td>{{ $line['student_name'] }}</x-table.td>
|
||||||
|
<x-table.td>{{ $line['audition'] }}</x-table.td>
|
||||||
|
<x-table.td>{{ $line['entry_timestamp']->setTimezone('America/Chicago')->format('m/d/Y g:i:s A') }}</x-table.td>
|
||||||
|
<x-table.td>${{ number_format($line['entry_fee'],2) }}</x-table.td>
|
||||||
|
<x-table.td>${{ number_format($line['late_fee'],2) }}</x-table.td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</x-table.body>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<x-table.th colspan="3" class="text-right">Totals</x-table.th>
|
||||||
|
<x-table.th>${{ number_format($invoiceData['linesTotal'],2) }}</x-table.th>
|
||||||
|
<x-table.th>${{ number_format($invoiceData['lateFeesTotal'],2) }}</x-table.th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<x-table.th colspan="4" class="text-right">School Fee</x-table.th>
|
||||||
|
<x-table.th >${{ number_format($invoiceData['schoolFeeTotal'],2) }}</x-table.th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<x-table.th colspan="4" class="text-right">Grand Total</x-table.th>
|
||||||
|
<x-table.th >${{ number_format($invoiceData['grandTotal'],2) }}</x-table.th>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</x-table.table>
|
||||||
|
</x-layout.app>
|
||||||
|
|
@ -16,9 +16,9 @@
|
||||||
<x-layout.app>
|
<x-layout.app>
|
||||||
<x-slot:page_title>Test Page</x-slot:page_title>
|
<x-slot:page_title>Test Page</x-slot:page_title>
|
||||||
@php
|
@php
|
||||||
$schools = School::all();
|
dump($totalFees);
|
||||||
|
dump($lines);
|
||||||
|
|
||||||
}
|
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
||||||
Route::get('/dashboard', [DashboardController::class, 'dashboard'])->name('dashboard');
|
Route::get('/dashboard', [DashboardController::class, 'dashboard'])->name('dashboard');
|
||||||
Route::get('/profile', [DashboardController::class, 'profile']);
|
Route::get('/profile', [DashboardController::class, 'profile']);
|
||||||
Route::get('/my_school', [DashboardController::class, 'my_school']);
|
Route::get('/my_school', [DashboardController::class, 'my_school']);
|
||||||
|
Route::get('/my_invoice', [DashboardController::class, 'my_invoice'])->name('my_invoice');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Entry Related Routes
|
// Entry Related Routes
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue