feat(price request): membuat enum status
- membuat datatables - membuat logika untuk handle approve dan reject - casting dan scope model - membuat badge di sidebar untuk counting data yang belum disetujui - menyesuaikan logika untuk mengajukan harga beli dengan skema table yang baru - menyesuaikan skema table yang baru - menyesuaikan parameter yang dikriim untuk pengajuan - menyesuaikan logika table - membuat permission
This commit is contained in:
parent
c984206d94
commit
396440eda7
33
app/Enums/PriceRequestStatus.php
Normal file
33
app/Enums/PriceRequestStatus.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Enums;
|
||||||
|
|
||||||
|
use App\Traits\WithCommentEnum;
|
||||||
|
use App\Traits\WithValueEnum;
|
||||||
|
|
||||||
|
enum PriceRequestStatus: int
|
||||||
|
{
|
||||||
|
use WithCommentEnum, WithValueEnum;
|
||||||
|
|
||||||
|
case PENDING = 1;
|
||||||
|
case APPROVED = 2;
|
||||||
|
case REJECTED = 3;
|
||||||
|
|
||||||
|
public function label(): string
|
||||||
|
{
|
||||||
|
return match ($this) {
|
||||||
|
self::PENDING => 'Menunggu',
|
||||||
|
self::APPROVED => 'Disetujui',
|
||||||
|
self::REJECTED => 'Ditolak',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function color()
|
||||||
|
{
|
||||||
|
return match ($this) {
|
||||||
|
self::PENDING => 'gray',
|
||||||
|
self::APPROVED => 'emerald',
|
||||||
|
self::REJECTED => 'red',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -21,10 +21,16 @@ class BottlesTable extends DataTableComponent
|
|||||||
|
|
||||||
protected $model = Bottle::class;
|
protected $model = Bottle::class;
|
||||||
|
|
||||||
protected ?int $refreshTime = 3000;
|
protected int $refreshTime = 3000;
|
||||||
|
|
||||||
public function columns(): array
|
public function columns(): array
|
||||||
{
|
{
|
||||||
|
$canSeePrice = PriceRequest::where('user_id', auth()->id())
|
||||||
|
->where('module', 'botol')
|
||||||
|
->approved()
|
||||||
|
->where('finalized_at', '>', now()->subMinute(10))
|
||||||
|
->exists();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
Column::make('Nama')
|
Column::make('Nama')
|
||||||
->label(function ($row) {
|
->label(function ($row) {
|
||||||
@ -42,13 +48,7 @@ public function columns(): array
|
|||||||
->html(),
|
->html(),
|
||||||
|
|
||||||
Column::make('Harga Beli', 'cost_price')
|
Column::make('Harga Beli', 'cost_price')
|
||||||
->label(function ($row) {
|
->label(function ($row) use ($canSeePrice) {
|
||||||
$canSeePrice = PriceRequest::where('user_id', auth()->id())
|
|
||||||
->where('model', Bottle::class)
|
|
||||||
->whereNotNull('approved_at')
|
|
||||||
->where('expires_at', '>', now())
|
|
||||||
->exists();
|
|
||||||
|
|
||||||
if ($canSeePrice) {
|
if ($canSeePrice) {
|
||||||
return currency($row->cost_price, 'Rp');
|
return currency($row->cost_price, 'Rp');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,10 +20,16 @@ class PerfumesTable extends DataTableComponent
|
|||||||
|
|
||||||
protected $model = Perfume::class;
|
protected $model = Perfume::class;
|
||||||
|
|
||||||
protected ?int $refreshTime = 3000;
|
protected $refreshTime = 3000;
|
||||||
|
|
||||||
public function columns(): array
|
public function columns(): array
|
||||||
{
|
{
|
||||||
|
$canSeePrice = PriceRequest::where('user_id', auth()->id())
|
||||||
|
->where('module', 'parfum')
|
||||||
|
->approved()
|
||||||
|
->where('finalized_at', '>', now()->subMinute(10))
|
||||||
|
->exists();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
Column::make('Nama')
|
Column::make('Nama')
|
||||||
->label(function ($row) {
|
->label(function ($row) {
|
||||||
@ -52,13 +58,7 @@ public function columns(): array
|
|||||||
->html(),
|
->html(),
|
||||||
|
|
||||||
Column::make('Harga Beli', 'cost_price')
|
Column::make('Harga Beli', 'cost_price')
|
||||||
->label(function ($row) {
|
->label(function ($row) use ($canSeePrice) {
|
||||||
$canSeePrice = PriceRequest::where('user_id', auth()->id())
|
|
||||||
->where('model', Perfume::class)
|
|
||||||
->whereNotNull('approved_at')
|
|
||||||
->where('expires_at', '>', now())
|
|
||||||
->exists();
|
|
||||||
|
|
||||||
if ($canSeePrice) {
|
if ($canSeePrice) {
|
||||||
return currency($row->cost_price, 'Rp');
|
return currency($row->cost_price, 'Rp');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,10 +20,16 @@ class ProductsTable extends DataTableComponent
|
|||||||
|
|
||||||
protected $model = Product::class;
|
protected $model = Product::class;
|
||||||
|
|
||||||
protected ?int $refreshTime = 3000;
|
protected int $refreshTime = 3000;
|
||||||
|
|
||||||
public function columns(): array
|
public function columns(): array
|
||||||
{
|
{
|
||||||
|
$canSeePrice = PriceRequest::where('user_id', auth()->id())
|
||||||
|
->where('module', 'produk')
|
||||||
|
->approved()
|
||||||
|
->where('finalized_at', '>', now()->subMinute(10))
|
||||||
|
->exists();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
Column::make('Nama')
|
Column::make('Nama')
|
||||||
->label(function ($row) {
|
->label(function ($row) {
|
||||||
@ -41,13 +47,7 @@ public function columns(): array
|
|||||||
->html(),
|
->html(),
|
||||||
|
|
||||||
Column::make('Harga Beli', 'cost_price')
|
Column::make('Harga Beli', 'cost_price')
|
||||||
->label(function ($row) {
|
->label(function ($row) use ($canSeePrice) {
|
||||||
$canSeePrice = PriceRequest::where('user_id', auth()->id())
|
|
||||||
->where('model', Product::class)
|
|
||||||
->whereNotNull('approved_at')
|
|
||||||
->where('expires_at', '>', now())
|
|
||||||
->exists();
|
|
||||||
|
|
||||||
if ($canSeePrice) {
|
if ($canSeePrice) {
|
||||||
return currency($row->cost_price, 'Rp');
|
return currency($row->cost_price, 'Rp');
|
||||||
}
|
}
|
||||||
|
|||||||
106
app/Livewire/Datatable/Studio/Manage/PriceRequestsTable.php
Normal file
106
app/Livewire/Datatable/Studio/Manage/PriceRequestsTable.php
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Livewire\Datatable\Studio\Manage;
|
||||||
|
|
||||||
|
use App\Enums\PriceRequestStatus;
|
||||||
|
use App\Models\PriceRequest;
|
||||||
|
use App\Traits\Datatable\WithAppendColumn;
|
||||||
|
use App\Traits\Datatable\WithConfiguration;
|
||||||
|
use App\Traits\Datatable\WithPrependColumn;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Support\Facades\Blade;
|
||||||
|
use Rappasoft\LaravelLivewireTables\DataTableComponent;
|
||||||
|
use Rappasoft\LaravelLivewireTables\Views\Column;
|
||||||
|
|
||||||
|
class PriceRequestsTable extends DataTableComponent
|
||||||
|
{
|
||||||
|
use WithConfiguration, WithPrependColumn, WithAppendColumn;
|
||||||
|
|
||||||
|
protected $model = PriceRequest::class;
|
||||||
|
|
||||||
|
public function columns(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Column::make('Pemohon', 'user.employee.full_name')->searchable(),
|
||||||
|
|
||||||
|
Column::make('module', 'module')
|
||||||
|
->format(fn($row) => ucfirst($row))
|
||||||
|
->searchable(),
|
||||||
|
|
||||||
|
Column::make('Status', 'status')
|
||||||
|
->label(fn($row, $column) => Blade::render('<flux:badge color="' . $row->status->color() . '">' . $row->status->label() . '</flux:badge>'))
|
||||||
|
->html(),
|
||||||
|
|
||||||
|
Column::make('Tanggal')
|
||||||
|
->label(function ($row) {
|
||||||
|
$startDate = formatDate($row->created_at);
|
||||||
|
$startAgo = timeAgo($row->created_at);
|
||||||
|
|
||||||
|
$endDate = formatDate($row->finalized_at);
|
||||||
|
$endAgo = timeAgo($row->finalized_at);
|
||||||
|
|
||||||
|
return <<<HTML
|
||||||
|
<div class="flex flex-col text-xs text-gray-700 dark:text-gray-300 gap-0.5">
|
||||||
|
<div>
|
||||||
|
<span class="font-medium text-gray-900 dark:text-white">Tgl Permohonan:</span>
|
||||||
|
<span>{$startDate}</span>
|
||||||
|
<span class="text-gray-500">({$startAgo})</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="font-medium text-gray-900 dark:text-white">Tgl Ditanggapi:</span>
|
||||||
|
<span>{$endDate}</span>
|
||||||
|
<span class="text-gray-500">({$endAgo})</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
HTML;
|
||||||
|
})
|
||||||
|
->html(),
|
||||||
|
|
||||||
|
Column::make('Aksi')
|
||||||
|
->label(function ($row) {
|
||||||
|
$actions = '';
|
||||||
|
|
||||||
|
if (auth()->user()->can('approve price request') && $row->status === PriceRequestStatus::PENDING) {
|
||||||
|
$actions .= view('components.datatables.confirm', [
|
||||||
|
'id' => $row->hash,
|
||||||
|
'message' => 'Pemohon yang diterima bisa melihat data harga beli.',
|
||||||
|
'confirmButtonText' => 'Ya, Terima',
|
||||||
|
'target' => 'approve',
|
||||||
|
'title' => 'Terima',
|
||||||
|
'confirmButtonColor' => 'primary',
|
||||||
|
'icon' => 'check-circle',
|
||||||
|
])->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auth()->user()->can('reject price request') && $row->status === PriceRequestStatus::PENDING) {
|
||||||
|
$actions .= view('components.datatables.confirm', [
|
||||||
|
'id' => $row->hash,
|
||||||
|
'message' => 'Jika ditolak, pomohon tidak dapat melihat data harga beli.',
|
||||||
|
'confirmButtonText' => 'Ya, Tolak',
|
||||||
|
'target' => 'reject',
|
||||||
|
'title' => 'Tolak',
|
||||||
|
'confirmButtonColor' => 'red',
|
||||||
|
'icon' => 'x-circle',
|
||||||
|
])->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $actions;
|
||||||
|
})
|
||||||
|
->html()
|
||||||
|
->hideIf(auth()->user()->cannot('approve price request') && auth()->user()->cannot('reject price request')),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function builder(): Builder
|
||||||
|
{
|
||||||
|
return PriceRequest::select(
|
||||||
|
'price_requests.id',
|
||||||
|
'price_requests.user_id',
|
||||||
|
'module',
|
||||||
|
'price_requests.status',
|
||||||
|
'price_requests.created_at',
|
||||||
|
'finalized_at'
|
||||||
|
)
|
||||||
|
->with(['user', 'user.employee']);
|
||||||
|
}
|
||||||
|
}
|
||||||
77
app/Livewire/Studio/Manage/PriceRequest.php
Normal file
77
app/Livewire/Studio/Manage/PriceRequest.php
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Livewire\Studio\Manage;
|
||||||
|
|
||||||
|
use App\Enums\PriceRequestStatus;
|
||||||
|
use App\Jobs\StorePushNotification;
|
||||||
|
use App\Livewire\Datatable\Studio\Catalog\PerfumesTable;
|
||||||
|
use App\Models\PriceRequest as PriceRequestModel;
|
||||||
|
use App\Models\PushNotification;
|
||||||
|
use App\Traits\Notification\WithSubscribeNotification;
|
||||||
|
use App\Traits\WithAuthorization;
|
||||||
|
use App\Traits\WithConfirmation;
|
||||||
|
use App\Traits\WithToast;
|
||||||
|
use Flux\Flux;
|
||||||
|
use Livewire\Attributes\Title;
|
||||||
|
use Livewire\Component;
|
||||||
|
|
||||||
|
#[Title('Permintaan Harga')]
|
||||||
|
class PriceRequest extends Component
|
||||||
|
{
|
||||||
|
use WithAuthorization, WithConfirmation, WithSubscribeNotification, WithToast;
|
||||||
|
|
||||||
|
public function approve(PriceRequestModel $priceRequest)
|
||||||
|
{
|
||||||
|
$this->canOrAbort('approve price request');
|
||||||
|
|
||||||
|
$priceRequest->update([
|
||||||
|
'status' => PriceRequestStatus::APPROVED->value,
|
||||||
|
'finalized_at' => now()
|
||||||
|
]);
|
||||||
|
|
||||||
|
StorePushNotification::dispatch(
|
||||||
|
PushNotification::where('user_id', $priceRequest->user_id)->get(),
|
||||||
|
[
|
||||||
|
'title' => 'Permintaan Harga Disetujui ✅',
|
||||||
|
'body' => "Selamat! Permintaan untuk melihat harga beli {$priceRequest->module} sudah disetujui 🎉",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->dispatch('refreshDatatable');
|
||||||
|
|
||||||
|
$this->toast('Permintaan harga berhasil disetujui.');
|
||||||
|
|
||||||
|
Flux::modals()->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reject(PriceRequestModel $priceRequest)
|
||||||
|
{
|
||||||
|
$this->canOrAbort('reject price request');
|
||||||
|
|
||||||
|
$priceRequest->update([
|
||||||
|
'status' => PriceRequestStatus::REJECTED->value,
|
||||||
|
'finalized_at' => now()
|
||||||
|
]);
|
||||||
|
|
||||||
|
StorePushNotification::dispatch(
|
||||||
|
PushNotification::where('user_id', $priceRequest->user_id)->get(),
|
||||||
|
[
|
||||||
|
'title' => 'Permintaan Harga Ditolak ❌',
|
||||||
|
'body' => "Maaf, permintaan untuk melihat harga beli {$priceRequest->module} tidak dapat dipenuhi 🙏",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->dispatch('refreshDatatable');
|
||||||
|
|
||||||
|
$this->toast('Permintaan harga berhasil ditolak.');
|
||||||
|
|
||||||
|
Flux::modals()->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return view('livewire.studio.manage.price-requests', [
|
||||||
|
'pageTitle' => 'Permintaan Harga',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Enums\PriceRequestStatus;
|
||||||
|
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
@ -13,6 +16,32 @@ class PriceRequest extends Model
|
|||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'status' => PriceRequestStatus::class,
|
||||||
|
'finalized_at' => 'datetime',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Scope]
|
||||||
|
protected function pending(Builder $query): void
|
||||||
|
{
|
||||||
|
$query->where('status', PriceRequestStatus::PENDING->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Scope]
|
||||||
|
protected function approved(Builder $query): void
|
||||||
|
{
|
||||||
|
$query->where('status', PriceRequestStatus::APPROVED->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Scope]
|
||||||
|
protected function rejected(Builder $query): void
|
||||||
|
{
|
||||||
|
$query->where('status', PriceRequestStatus::REJECTED->value);
|
||||||
|
}
|
||||||
|
|
||||||
public function user(): BelongsTo
|
public function user(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class);
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Enums\PriceRequestStatus;
|
||||||
|
use App\Models\PriceRequest;
|
||||||
use Illuminate\Support\Facades\View;
|
use Illuminate\Support\Facades\View;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
@ -9,7 +11,9 @@ class ViewServiceProvider extends ServiceProvider
|
|||||||
{
|
{
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
View::composer('*', function ($view) {
|
$priceRequestCount = PriceRequest::where('status', PriceRequestStatus::PENDING->value)->count();
|
||||||
|
|
||||||
|
View::composer('*', function ($view) use ($priceRequestCount) {
|
||||||
$sidebar = [
|
$sidebar = [
|
||||||
[
|
[
|
||||||
'heading' => 'Dasbor',
|
'heading' => 'Dasbor',
|
||||||
@ -165,6 +169,14 @@ public function boot(): void
|
|||||||
'match' => 'studio.manage.article.*',
|
'match' => 'studio.manage.article.*',
|
||||||
'can' => 'view article',
|
'can' => 'view article',
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'label' => 'Permintaan Harga',
|
||||||
|
'icon' => 'exclamation-triangle',
|
||||||
|
'route' => 'studio.manage.price_request.index',
|
||||||
|
'match' => 'studio.manage.price_request.*',
|
||||||
|
'can' => 'view price request',
|
||||||
|
'badge' => $priceRequestCount,
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'label' => 'FAQs',
|
'label' => 'FAQs',
|
||||||
'icon' => 'question-mark-circle',
|
'icon' => 'question-mark-circle',
|
||||||
|
|||||||
@ -2,102 +2,57 @@
|
|||||||
|
|
||||||
namespace App\Traits;
|
namespace App\Traits;
|
||||||
|
|
||||||
use App\Models\Bottle;
|
use App\Jobs\StorePushNotification;
|
||||||
use App\Models\Perfume;
|
|
||||||
use App\Models\PriceRequest;
|
use App\Models\PriceRequest;
|
||||||
use App\Models\Product;
|
use App\Models\PushNotification;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\Whatsapp;
|
|
||||||
use Flux\Flux;
|
use Flux\Flux;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Support\Facades\URL;
|
|
||||||
|
|
||||||
trait WithShowPrice
|
trait WithShowPrice
|
||||||
{
|
{
|
||||||
public function requestPrice(string $module)
|
public function requestPrice(string $module)
|
||||||
{
|
{
|
||||||
switch ($module) {
|
|
||||||
case 'perfume':
|
|
||||||
$label = 'parfum';
|
|
||||||
$model = Perfume::class;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'product':
|
|
||||||
$label = 'produk';
|
|
||||||
$model = Product::class;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
$label = 'botol';
|
|
||||||
$model = Bottle::class;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$recentRequest = PriceRequest::where('user_id', auth()->id())
|
$recentRequest = PriceRequest::where('user_id', auth()->id())
|
||||||
->where('model', $model)
|
->where('module', $module)
|
||||||
->where('created_at', '>', now()->subMinutes(30))
|
->pending()
|
||||||
->exists();
|
->exists();
|
||||||
|
|
||||||
if ($recentRequest) {
|
if ($recentRequest) {
|
||||||
$this->toast('Kamu baru saja mengajukan permintaan, tautan persetujuan masih berlaku selama 30 menit.', 'Peringatan', 'warning');
|
$this->toast('Permohonan kamu sedang di proses oleh owner, mohon tunggu dan kami akan memberi tahu Anda jika prosesnya sudah selesai.', 'Peringatan', 'warning');
|
||||||
Flux::modal('show-price')->close();
|
Flux::modal('show-price')->close();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$whatsapp = Whatsapp::first();
|
$owner = User::role(['owner', 'Developer'])->with('employee')->first();
|
||||||
$owner = User::role('owner')->with('employee')->first();
|
|
||||||
|
|
||||||
if (! $owner) {
|
if (! $owner) {
|
||||||
$this->toast('Owner belum terdaftar, silakan hubungi Admin', 'Gagal', 'danger');
|
$this->toast('Owner belum terdaftar, silakan hubungi Admin.', 'Gagal', 'danger');
|
||||||
Flux::modal('show-price')->close();
|
Flux::modal('show-price')->close();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$phoneNumber = formatPhoneNumber($owner->employee?->phone_number, '62');
|
|
||||||
|
|
||||||
try {
|
|
||||||
$priceRequest = PriceRequest::create([
|
|
||||||
'user_id' => auth()->id(),
|
|
||||||
'model' => $model,
|
|
||||||
'expires_at' => now()->addMinutes(30),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$signedUrl = URL::temporarySignedRoute(
|
|
||||||
'price-request.approve',
|
|
||||||
$priceRequest->expires_at,
|
|
||||||
['priceRequest' => $priceRequest->hash]
|
|
||||||
);
|
|
||||||
|
|
||||||
$priceRequest->update([
|
|
||||||
'signature' => hash('sha256', $signedUrl),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$causerName = auth()->user()->employee?->full_name;
|
$causerName = auth()->user()->employee?->full_name;
|
||||||
|
|
||||||
$response = Http::withHeaders([
|
DB::transaction(function () use ($module, $owner, $causerName) {
|
||||||
'id' => $whatsapp->zawa_id,
|
PriceRequest::create([
|
||||||
'session-id' => $whatsapp->session_id,
|
'user_id' => auth()->id(),
|
||||||
'Content-Type' => 'application/json',
|
'module' => $module,
|
||||||
])->post(config('services.zawa.url').'/message', [
|
|
||||||
'phone' => $phoneNumber,
|
|
||||||
'type' => 'text',
|
|
||||||
'text' => "Haloo {$owner->employee?->full_name}, saya {$causerName}, "
|
|
||||||
."saya ingin mengajukan permintaan persetujuan untuk mengakses data harga beli {$label}."
|
|
||||||
."\n\nSilakan klik tautan berikut untuk menyetujui:\n\n{$signedUrl}",
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($response->successful()) {
|
StorePushNotification::dispatch(
|
||||||
|
PushNotification::all(),
|
||||||
|
[
|
||||||
|
'title' => 'Permintaan Persetujuan Harga Beli',
|
||||||
|
'body' => "Haloo {$owner->employee?->full_name}, saya {$causerName}, saya ingin mengajukan permintaan persetujuan untuk mengakses data harga beli {$module}.",
|
||||||
|
'route' => route('studio.manage.price_request.index'),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
$this->toast('Permintaan persetujuan berhasil dikirim.');
|
$this->toast('Permintaan persetujuan berhasil dikirim.');
|
||||||
} else {
|
|
||||||
$this->toast('Permintaan persetujuan gagal dikirim, silakan coba lagi.', 'Gagal', 'danger');
|
|
||||||
}
|
|
||||||
} catch (\Throwable $th) {
|
|
||||||
Log::error($th->getMessage());
|
|
||||||
$this->toast('Opps, terjadi kesalahan. Silakan coba lagi dan jika masih terjadi, hubungi Administrator.', 'Gagal', 'danger');
|
|
||||||
}
|
|
||||||
|
|
||||||
Flux::modal('show-price')->close();
|
Flux::modal('show-price')->close();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\PriceRequestStatus;
|
||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
@ -14,11 +15,9 @@ public function up(): void
|
|||||||
Schema::create('price_requests', function (Blueprint $table) {
|
Schema::create('price_requests', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
|
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
|
||||||
$table->string('model', 20);
|
$table->string('module', 20);
|
||||||
$table->string('signature')->unique()->nullable();
|
$table->enum('status', [PriceRequestStatus::values()])->default(PriceRequestStatus::PENDING)->comment(PriceRequestStatus::comment());
|
||||||
$table->timestamp('last_requested_at')->nullable();
|
$table->timestamp('finalized_at')->nullable();
|
||||||
$table->timestamp('expires_at')->nullable();
|
|
||||||
$table->timestamp('approved_at')->nullable();
|
|
||||||
$table->timestamp('created_at')->useCurrent();
|
$table->timestamp('created_at')->useCurrent();
|
||||||
$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
|
$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
|
|||||||
@ -118,6 +118,10 @@ public function run(): void
|
|||||||
'update article',
|
'update article',
|
||||||
'delete article',
|
'delete article',
|
||||||
|
|
||||||
|
'view price request',
|
||||||
|
'approve price request',
|
||||||
|
'reject price request',
|
||||||
|
|
||||||
'view faq',
|
'view faq',
|
||||||
'create faq',
|
'create faq',
|
||||||
'update faq',
|
'update faq',
|
||||||
|
|||||||
@ -26,5 +26,5 @@ class="text-sm">
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@include('components.confirmation.delete')
|
@include('components.confirmation.delete')
|
||||||
@include('components.confirmation.show-price', ['module' => 'bottle'])
|
@include('components.confirmation.show-price', ['module' => 'botol'])
|
||||||
</flux:main>
|
</flux:main>
|
||||||
|
|||||||
@ -26,5 +26,5 @@ class="text-sm">
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@include('components.confirmation.delete')
|
@include('components.confirmation.delete')
|
||||||
@include('components.confirmation.show-price', ['module' => 'perfume'])
|
@include('components.confirmation.show-price', ['module' => 'parfum'])
|
||||||
</flux:main>
|
</flux:main>
|
||||||
|
|||||||
@ -26,5 +26,5 @@ class="text-sm">
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@include('components.confirmation.delete')
|
@include('components.confirmation.delete')
|
||||||
@include('components.confirmation.show-price', ['module' => 'product'])
|
@include('components.confirmation.show-price', ['module' => 'produk'])
|
||||||
</flux:main>
|
</flux:main>
|
||||||
|
|||||||
@ -0,0 +1,13 @@
|
|||||||
|
<flux:main>
|
||||||
|
<div class="flex justify-between items-center">
|
||||||
|
<div>
|
||||||
|
<flux:heading size="xl">{{ $pageTitle }}</flux:heading>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-6">
|
||||||
|
<livewire:datatable.studio.manage.price-requests-table />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@include('components.confirmation')
|
||||||
|
</flux:main>
|
||||||
@ -33,6 +33,7 @@
|
|||||||
use App\Livewire\Studio\Manage\Order\Create as OrderCreate;
|
use App\Livewire\Studio\Manage\Order\Create as OrderCreate;
|
||||||
use App\Livewire\Studio\Manage\Order\Index as OrderIndex;
|
use App\Livewire\Studio\Manage\Order\Index as OrderIndex;
|
||||||
use App\Livewire\Studio\Manage\Order\Show as OrderShow;
|
use App\Livewire\Studio\Manage\Order\Show as OrderShow;
|
||||||
|
use App\Livewire\Studio\Manage\PriceRequest as PriceRequestComponent;
|
||||||
use App\Livewire\Studio\Manage\Purchase\Create as PurchaseCreate;
|
use App\Livewire\Studio\Manage\Purchase\Create as PurchaseCreate;
|
||||||
use App\Livewire\Studio\Manage\Purchase\Index as PurchaseIndex;
|
use App\Livewire\Studio\Manage\Purchase\Index as PurchaseIndex;
|
||||||
use App\Livewire\Studio\Master\Formula as FormulaComponent;
|
use App\Livewire\Studio\Master\Formula as FormulaComponent;
|
||||||
@ -176,6 +177,12 @@
|
|||||||
Route::get('/', FaqComponent::class)->name('index')->middleware('can:view faq');
|
Route::get('/', FaqComponent::class)->name('index')->middleware('can:view faq');
|
||||||
Route::delete('/{faq}/delete', FaqComponent::class)->name('delete')->middleware('can:delete faq');
|
Route::delete('/{faq}/delete', FaqComponent::class)->name('delete')->middleware('can:delete faq');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::prefix('price-requests')->name('price_request.')->group(function () {
|
||||||
|
Route::get('/', PriceRequestComponent::class)->name('index')->middleware('can:view price request');
|
||||||
|
Route::patch('/{priceRequest}/approve', PriceRequestComponent::class)->name('approve')->middleware('can:approve price request');
|
||||||
|
Route::patch('/{priceRequest}/reject', PriceRequestComponent::class)->name('reject')->middleware('can:reject price request');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::prefix('feature')->name('studio.feature.')->group(function () {
|
Route::prefix('feature')->name('studio.feature.')->group(function () {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user