diff --git a/app/Http/Controllers/Customer/Auth/AuthenticatedSessionController.php b/app/Http/Controllers/Customer/Auth/AuthenticatedSessionController.php new file mode 100644 index 00000000..f72a485d --- /dev/null +++ b/app/Http/Controllers/Customer/Auth/AuthenticatedSessionController.php @@ -0,0 +1,65 @@ +validate([ + 'email' => ['required', 'email'], + 'password' => ['required', 'string'], + 'remember' => ['nullable', 'boolean'], + ]); + + $authenticated = Auth::guard('customer')->attempt([ + 'mail' => $credentials['email'], + 'password' => $credentials['password'], + ], $request->boolean('remember')); + + if (! $authenticated) { + throw ValidationException::withMessages([ + 'email' => trans('auth.failed'), + ]); + } + + $request->session()->regenerate(); + + $customer = Auth::guard('customer')->user(); + if ($customer) { + $customer->forceFill(['last_login_at' => now()])->save(); + } + + return redirect()->intended(RouteServiceProvider::CUSTOMER_HOME); + } + + /** + * Log the customer out of the application. + */ + public function destroy(Request $request) + { + Auth::guard('customer')->logout(); + + $request->session()->invalidate(); + $request->session()->regenerateToken(); + + return redirect()->route('customer.login'); + } +} diff --git a/app/Http/Controllers/Customer/PortalController.php b/app/Http/Controllers/Customer/PortalController.php new file mode 100644 index 00000000..d7020a3f --- /dev/null +++ b/app/Http/Controllers/Customer/PortalController.php @@ -0,0 +1,297 @@ + 'general_content.open_trans_key', + 2 => 'general_content.in_progress_trans_key', + 3 => 'general_content.delivered_trans_key', + 4 => 'general_content.partly_delivered_trans_key', + ]; + + private const ORDER_STATUS_BADGES = [ + 1 => 'info', + 2 => 'warning', + 3 => 'success', + 4 => 'danger', + ]; + + private const INVOICE_STATUS_LABELS = [ + 1 => 'general_content.in_progress_trans_key', + 2 => 'general_content.send_trans_key', + 3 => 'general_content.pending_trans_key', + 4 => 'general_content.unpaid_trans_key', + 5 => 'general_content.paid_trans_key', + ]; + + private const INVOICE_STATUS_BADGES = [ + 1 => 'info', + 2 => 'primary', + 3 => 'warning', + 4 => 'danger', + 5 => 'success', + ]; + + private const DELIVERY_STATUS_LABELS = [ + 1 => 'general_content.in_progress_trans_key', + 2 => 'general_content.send_trans_key', + ]; + + private const DELIVERY_STATUS_BADGES = [ + 1 => 'info', + 2 => 'warning', + ]; + + /** + * Display the customer dashboard. + */ + public function index(Request $request) + { + $customer = Auth::guard('customer')->user(); + + $ordersBaseQuery = Orders::query() + ->where(function ($query) use ($customer) { + $query->where('companies_id', $customer->companies_id) + ->orWhere('companies_contacts_id', $customer->getKey()); + }); + + $ordersQuery = (clone $ordersBaseQuery)->with('companie'); + if ($status = $request->integer('order_status')) { + $ordersQuery->where('statu', $status); + } + if ($search = $request->input('order_search')) { + $ordersQuery->where(function ($query) use ($search) { + $query->where('code', 'like', "%{$search}%") + ->orWhere('label', 'like', "%{$search}%") + ->orWhere('customer_reference', 'like', "%{$search}%"); + }); + } + + $orders = $ordersQuery + ->orderByDesc('created_at') + ->paginate(10, ['*'], 'orders_page') + ->withQueryString(); + + $openOrdersCount = (clone $ordersBaseQuery)->whereIn('statu', [1, 2, 4])->count(); + + $deliveriesBaseQuery = Deliverys::query() + ->where(function ($query) use ($customer) { + $query->where('companies_id', $customer->companies_id) + ->orWhere('companies_contacts_id', $customer->getKey()); + }); + + $deliveries = (clone $deliveriesBaseQuery) + ->with('Orders') + ->orderByDesc('created_at') + ->paginate(5, ['*'], 'deliveries_page') + ->withQueryString(); + + $pendingDeliveriesCount = (clone $deliveriesBaseQuery)->where('statu', 1)->count(); + + $invoicesBaseQuery = Invoices::query() + ->where(function ($query) use ($customer) { + $query->where('companies_id', $customer->companies_id) + ->orWhere('companies_contacts_id', $customer->getKey()); + }); + + $invoicesQuery = (clone $invoicesBaseQuery)->with('companie'); + if ($status = $request->integer('invoice_status')) { + $invoicesQuery->where('statu', $status); + } + if ($search = $request->input('invoice_search')) { + $invoicesQuery->where(function ($query) use ($search) { + $query->where('code', 'like', "%{$search}%") + ->orWhere('label', 'like', "%{$search}%"); + }); + } + + $invoices = $invoicesQuery + ->orderByDesc('created_at') + ->paginate(10, ['*'], 'invoices_page') + ->withQueryString(); + + $unpaidInvoicesCount = (clone $invoicesBaseQuery)->whereIn('statu', [3, 4])->count(); + + $notifications = [ + [ + 'title' => __('general_content.orders_trans_key'), + 'subtitle' => __('general_content.in_progress_trans_key'), + 'value' => $openOrdersCount, + 'variant' => 'info', + ], + [ + 'title' => __('general_content.delivery_notes_trans_key'), + 'subtitle' => __('general_content.in_progress_trans_key'), + 'value' => $pendingDeliveriesCount, + 'variant' => 'warning', + ], + [ + 'title' => __('general_content.invoices_trans_key'), + 'subtitle' => __('general_content.unpaid_trans_key'), + 'value' => $unpaidInvoicesCount, + 'variant' => 'danger', + ], + ]; + + return view('customer.dashboard', [ + 'customer' => $customer, + 'orders' => $orders, + 'invoices' => $invoices, + 'deliveries' => $deliveries, + 'notifications' => $notifications, + 'orderStatusOptions' => $this->getOrderStatusLabels(), + 'invoiceStatusOptions' => $this->getInvoiceStatusLabels(), + 'orderStatusBadges' => self::ORDER_STATUS_BADGES, + 'invoiceStatusBadges' => self::INVOICE_STATUS_BADGES, + 'deliveryStatusBadges' => self::DELIVERY_STATUS_BADGES, + 'deliveryStatusLabels' => $this->getDeliveryStatusLabels(), + ]); + } + + /** + * Display an order. + */ + public function showOrder(string $uuid) + { + $customer = Auth::guard('customer')->user(); + + $order = Orders::where('uuid', $uuid) + ->where(function ($query) use ($customer) { + $query->where('companies_id', $customer->companies_id) + ->orWhere('companies_contacts_id', $customer->getKey()); + }) + ->with([ + 'OrderLines.Unit', + 'OrderLines.VAT', + 'OrderLines.OrderLineDetails', + 'OrderLines.DeliveryLines.delivery', + 'payment_method', + 'payment_condition', + 'delevery_method', + 'companie', + 'contact', + 'adresse', + 'Rating', + ]) + ->firstOrFail(); + + $calculator = new OrderCalculatorService($order); + + return view('customer.orders.show', [ + 'order' => $order, + 'totalPrices' => $calculator->getTotalPrice(), + 'subPrice' => $calculator->getSubTotal(), + 'vatPrice' => $calculator->getVatTotal(), + 'orderStatusBadges' => self::ORDER_STATUS_BADGES, + 'orderStatusLabels' => $this->getOrderStatusLabels(), + ]); + } + + /** + * Display a delivery note. + */ + public function showDelivery(string $uuid) + { + $customer = Auth::guard('customer')->user(); + + $delivery = Deliverys::where('uuid', $uuid) + ->where(function ($query) use ($customer) { + $query->where('companies_id', $customer->companies_id) + ->orWhere('companies_contacts_id', $customer->getKey()); + }) + ->with([ + 'DeliveryLines.OrderLine.Unit', + 'DeliveryLines.OrderLine.order', + 'DeliveryLines.QualityNonConformity', + ]) + ->firstOrFail(); + + return view('customer.deliveries.show', [ + 'delivery' => $delivery, + 'deliveryStatusBadges' => self::DELIVERY_STATUS_BADGES, + 'deliveryStatusLabels' => $this->getDeliveryStatusLabels(), + ]); + } + + /** + * Display an invoice. + */ + public function showInvoice(string $uuid) + { + $customer = Auth::guard('customer')->user(); + + $invoice = Invoices::where('uuid', $uuid) + ->where(function ($query) use ($customer) { + $query->where('companies_id', $customer->companies_id) + ->orWhere('companies_contacts_id', $customer->getKey()); + }) + ->with([ + 'invoiceLines.orderLine.Unit', + 'invoiceLines.orderLine.VAT', + 'invoiceLines.deliveryLine.delivery', + 'companie', + 'contact', + 'adresse', + ]) + ->firstOrFail(); + + $calculator = new InvoiceCalculatorService($invoice); + + return view('customer.invoices.show', [ + 'invoice' => $invoice, + 'totalPrices' => $calculator->getTotalPrice(), + 'subPrice' => $calculator->getSubTotal(), + 'vatPrice' => $calculator->getVatTotal(), + 'invoiceStatusBadges' => self::INVOICE_STATUS_BADGES, + 'invoiceStatusLabels' => $this->getInvoiceStatusLabels(), + ]); + } + + /** + * Translate order status labels. + */ + private function getOrderStatusLabels(): array + { + return $this->translateLabels(self::ORDER_STATUS_LABELS); + } + + /** + * Translate invoice status labels. + */ + private function getInvoiceStatusLabels(): array + { + return $this->translateLabels(self::INVOICE_STATUS_LABELS); + } + + /** + * Translate delivery status labels. + */ + private function getDeliveryStatusLabels(): array + { + return $this->translateLabels(self::DELIVERY_STATUS_LABELS); + } + + /** + * Translate status labels with localization support. + */ + private function translateLabels(array $labels): array + { + $translated = []; + foreach ($labels as $status => $translationKey) { + $translated[$status] = __($translationKey); + } + + return $translated; + } +} diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 737c5097..5eb8edfe 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -70,5 +70,6 @@ class Kernel extends HttpKernel 'localeViewPath' => \Mcamara\LaravelLocalization\Middleware\LaravelLocalizationViewPath::class, 'check.factory' => \App\Http\Middleware\CheckFactory::class, 'check.task.status' => \App\Http\Middleware\CheckTaskStatus::class, + 'customer' => \App\Http\Middleware\EnsureCustomerIsAuthenticated::class, ]; } diff --git a/app/Http/Middleware/EnsureCustomerIsAuthenticated.php b/app/Http/Middleware/EnsureCustomerIsAuthenticated.php new file mode 100644 index 00000000..53d50e2f --- /dev/null +++ b/app/Http/Middleware/EnsureCustomerIsAuthenticated.php @@ -0,0 +1,26 @@ +check()) { + return $next($request); + } + + if ($request->expectsJson()) { + abort(401, 'Unauthenticated.'); + } + + return redirect()->guest(route('customer.login')); + } +} diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index 537c3b00..933361e5 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -15,7 +15,7 @@ class RedirectIfAuthenticated * @param \Illuminate\Http\Request $request * @param \Closure $next * @param string|null ...$guards - * @return \Illuminate\Contracts\View\View + * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse */ public function handle(Request $request, Closure $next, ...$guards) { @@ -23,6 +23,10 @@ public function handle(Request $request, Closure $next, ...$guards) foreach ($guards as $guard) { if (Auth::guard($guard)->check()) { + if ($guard === 'customer') { + return redirect(RouteServiceProvider::CUSTOMER_HOME); + } + return redirect(RouteServiceProvider::HOME); } } diff --git a/app/Models/Customer/Customer.php b/app/Models/Customer/Customer.php new file mode 100644 index 00000000..46bef7fd --- /dev/null +++ b/app/Models/Customer/Customer.php @@ -0,0 +1,101 @@ + 'datetime', + ]; + + /** + * Automatically hash passwords. + */ + public function setPasswordAttribute(?string $value): void + { + if (! empty($value)) { + $this->attributes['password'] = bcrypt($value); + } + } + + /** + * Customer company relation. + */ + public function companie() + { + return $this->belongsTo(Companies::class, 'companies_id'); + } + + /** + * Orders associated with the customer. + */ + public function orders() + { + return $this->hasMany(Orders::class, 'companies_contacts_id'); + } + + /** + * Deliveries associated with the customer. + */ + public function deliveries() + { + return $this->hasMany(Deliverys::class, 'companies_contacts_id'); + } + + /** + * Invoices associated with the customer. + */ + public function invoices() + { + return $this->hasMany(Invoices::class, 'companies_contacts_id'); + } +} diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 2a4cc034..b147a1ce 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -18,9 +18,11 @@ class RouteServiceProvider extends ServiceProvider * @var string */ public const HOME = '/dashboard'; - + public const WORKSHOP = '/workshop'; + public const CUSTOMER_HOME = '/customer'; + /** * The controller namespace for the application. * diff --git a/config/auth.php b/config/auth.php index 36e33fab..27459113 100644 --- a/config/auth.php +++ b/config/auth.php @@ -44,6 +44,10 @@ 'driver' => 'session', 'provider' => 'ldap', ], + 'customer' => [ + 'driver' => 'session', + 'provider' => 'customers', + ], 'api' => [ 'driver' => 'token', 'provider' => 'users', @@ -77,6 +81,10 @@ 'driver' => 'ldap', 'model' => LdapRecord\Models\ActiveDirectory\User::class, ], + 'customers' => [ + 'driver' => 'eloquent', + 'model' => App\Models\Customer\Customer::class, + ], // 'users' => [ // 'driver' => 'database', // 'table' => 'users', diff --git a/database/migrations/2024_09_10_000000_add_auth_fields_to_companies_contacts_table.php b/database/migrations/2024_09_10_000000_add_auth_fields_to_companies_contacts_table.php new file mode 100644 index 00000000..4af9e5f7 --- /dev/null +++ b/database/migrations/2024_09_10_000000_add_auth_fields_to_companies_contacts_table.php @@ -0,0 +1,30 @@ +string('password')->nullable()->after('default'); + $table->rememberToken()->nullable()->after('password'); + $table->timestamp('last_login_at')->nullable()->after('remember_token'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('companies_contacts', function (Blueprint $table) { + $table->dropColumn(['password', 'remember_token', 'last_login_at']); + }); + } +}; diff --git a/resources/views/customer/auth/login.blade.php b/resources/views/customer/auth/login.blade.php new file mode 100644 index 00000000..30a983d6 --- /dev/null +++ b/resources/views/customer/auth/login.blade.php @@ -0,0 +1,48 @@ + + + + + @if($Factory->picture) + {{ $Factory->name }} + @else + {{ $Factory->name ?? config('app.name', 'WebErpMesv2') }} + @endif + + + + + +
+ @csrf + +
+ + + @error('email') +

{{ $message }}

+ @enderror +
+ +
+ + + @error('password') +

{{ $message }}

+ @enderror +
+ +
+ +
+ +
+ + {{ __('adminlte::adminlte.sign_in') }} + +
+
+
+
diff --git a/resources/views/customer/dashboard.blade.php b/resources/views/customer/dashboard.blade.php new file mode 100644 index 00000000..def266d6 --- /dev/null +++ b/resources/views/customer/dashboard.blade.php @@ -0,0 +1,227 @@ +@extends('customer.layouts.app') + +@section('title', __('general_content.dashboard_trans_key')) + +@section('content') +
+ @foreach($notifications as $notification) +
+
+
+
+
+

{{ $notification['title'] }}

+

{{ $notification['value'] }}

+
+ {{ $notification['subtitle'] }} +
+
+
+
+ @endforeach +
+ +
+
+
+
{{ __('general_content.orders_trans_key') }}
+ {{ __('general_content.orders_list_trans_key') }} +
+
+ + +
+ +
+
+ +
+
+ +
+
+
+
+
+ + + + + + + + + + + + + @forelse($orders as $order) + + + + + + + + + @empty + + + + @endforelse + +
{{ __('general_content.code_trans_key') }}{{ __('general_content.label_trans_key') }}{{ __('general_content.status_trans_key') }}{{ __('general_content.created_at_trans_key') }}{{ __('general_content.total_trans_key') }}{{ __('general_content.action_trans_key') }}
{{ $order->code }}{{ $order->label }} + @php($status = $order->statu) + + {{ $orderStatusOptions[$status] ?? __('general_content.status_trans_key') }} + + {{ $order->GetshortCreatedAttribute() }}{{ number_format($order->total_price, 2, '.', ' ') }} {{ $Factory->curency }} + + {{ __('general_content.view_trans_key') ?? __('general_content.show_trans_key') }} + +
{{ __('general_content.no_data_trans_key') }}
+
+
+ +
+ +
+
+
+
{{ __('general_content.invoices_trans_key') }}
+ {{ __('general_content.invoices_list_trans_key') }} +
+
+ + +
+ +
+
+ +
+
+ +
+
+
+
+
+ + + + + + + + + + + + + @forelse($invoices as $invoice) + + + + + + + + + @empty + + + + @endforelse + +
{{ __('general_content.code_trans_key') }}{{ __('general_content.label_trans_key') }}{{ __('general_content.status_trans_key') }}{{ __('general_content.due_date_trans_key') }}{{ __('general_content.total_trans_key') }}{{ __('general_content.action_trans_key') }}
{{ $invoice->code }}{{ $invoice->label }} + @php($status = $invoice->statu) + + {{ $invoiceStatusOptions[$status] ?? __('general_content.status_trans_key') }} + + + @if($invoice->due_date) + {{ \Illuminate\Support\Carbon::parse($invoice->due_date)->format('d/m/Y') }} + @else + {{ __('general_content.undefined_trans_key') }} + @endif + {{ number_format($invoice->total_price, 2, '.', ' ') }} {{ $Factory->curency }} + + {{ __('general_content.view_trans_key') ?? __('general_content.show_trans_key') }} + +
{{ __('general_content.no_data_trans_key') }}
+
+
+ +
+ +
+
+
{{ __('general_content.delivery_notes_trans_key') }}
+
+
+
+ + + + + + + + + + + + @forelse($deliveries as $delivery) + + + + + + + + @empty + + + + @endforelse + +
{{ __('general_content.code_trans_key') }}{{ __('general_content.status_trans_key') }}{{ __('general_content.created_at_trans_key') }}{{ __('general_content.order_trans_key') }}{{ __('general_content.action_trans_key') }}
{{ $delivery->code }} + @php($status = $delivery->statu) + + {{ $deliveryStatusLabels[$status] ?? __('general_content.status_trans_key') }} + + {{ $delivery->GetshortCreatedAttribute() }} + @if($delivery->Orders) + #{{ $delivery->Orders->code }} + @endif + + + {{ __('general_content.view_trans_key') ?? __('general_content.show_trans_key') }} + +
{{ __('general_content.no_data_trans_key') }}
+
+
+ +
+@endsection diff --git a/resources/views/customer/deliveries/show.blade.php b/resources/views/customer/deliveries/show.blade.php new file mode 100644 index 00000000..eda7d64e --- /dev/null +++ b/resources/views/customer/deliveries/show.blade.php @@ -0,0 +1,137 @@ +@extends('customer.layouts.app') + +@section('title', __('general_content.delivery_notes_trans_key') . ' #' . $delivery->code) + +@section('content') +
+
+
+

{{ __('general_content.delivery_notes_trans_key') }} #{{ $delivery->code }}

+ {{ $delivery->GetshortCreatedAttribute() }} +
+ + @include('include.alert-result') + +
+
+
+
+ {{ $delivery->GetshortCreatedAttribute() }} + #{{ $delivery->code }} + @php($status = $delivery->statu) + @if(isset($deliveryStatusBadges[$status])) + {{ __($deliveryStatusLabels[$status]) }} + @endif +
+
+ + + + + + + + + + + + + + + + + @forelse($delivery->DeliveryLines as $DocumentLine) + + + + + + + + + + + + @empty + + @endforelse + +
{{ __('general_content.order_trans_key') }}{{ __('general_content.external_id_trans_key') }}{{ __('general_content.description_trans_key') }}{{ __('general_content.qty_trans_key') }}{{ __('general_content.unit_trans_key') }}{{ __('general_content.delivered_qty_trans_key') }}{{ __('general_content.remaining_qty_trans_key') }}{{ __('general_content.invoice_status_trans_key') }}
+ @if($DocumentLine->OrderLine->order->uuid) + + @endif + {{ $DocumentLine->OrderLine->order['code'] }} + {{ $DocumentLine->OrderLine['code'] }}{{ $DocumentLine->OrderLine['label'] }}{{ $DocumentLine->OrderLine['qty'] }}{{ $DocumentLine->OrderLine->Unit['label'] }}{{ $DocumentLine->qty }}{{ $DocumentLine->OrderLine['delivered_remaining_qty'] }} + @if(1 == $DocumentLine->invoice_status) + {{ __('general_content.chargeable_trans_key') }} + @endif + @if(2 == $DocumentLine->invoice_status) + {{ __('general_content.not_chargeable_trans_key') }} + @endif + @if(3 == $DocumentLine->invoice_status) + {{ __('general_content.partly_invoiced_trans_key') }} + @endif + @if(4 == $DocumentLine->invoice_status) + {{ __('general_content.invoiced_trans_key') }} + @endif + + @if($DocumentLine->QualityNonConformity) + + + {{ $DocumentLine->QualityNonConformity->label }} + + @if($DocumentLine->QualityNonConformity->statu == 1) + {{ __('general_content.in_progress_trans_key') }} + @endif + @if($DocumentLine->QualityNonConformity->statu == 2) + {{ __('general_content.waiting_customer_data_trans_key') }} + @endif + @if($DocumentLine->QualityNonConformity->statu == 3) + {{ __('general_content.validate_trans_key') }} + @endif + @if($DocumentLine->QualityNonConformity->statu == 4) + {{ __('general_content.canceled_trans_key') }} + @endif + @else + + + {{ __('general_content.new_non_conformitie_trans_key') }} + + @endif +
+
+
+ +
+
+
+
+

{{ $Factory->name }}

+ @if($Factory->picture) + + @endif +
+
+

{{ __('general_content.adress_trans_key') }}

+
+ {{ $Factory->address }}
+ {{ $Factory->zipcode }} {{ $Factory->city }}
+ {{ __('general_content.phone_trans_key') }} : {{ $Factory->phone_number }}
+ {{ __('general_content.email_trans_key') }} : {{ $Factory->mail }}
+
+
+
+
+
+ + @if ($delivery->comment) +
+
+

{{ __('general_content.comment_trans_key') }}

+

{{ $delivery->comment }}

+
+
+ @endif +
+
+@endsection diff --git a/resources/views/customer/invoices/show.blade.php b/resources/views/customer/invoices/show.blade.php new file mode 100644 index 00000000..8ab07dec --- /dev/null +++ b/resources/views/customer/invoices/show.blade.php @@ -0,0 +1,142 @@ +@extends('customer.layouts.app') + +@section('title', __('general_content.invoice_trans_key') . ' #' . $invoice->code) + +@section('content') +
+
+
+

{{ __('general_content.invoice_trans_key') }} #{{ $invoice->code }}

+ {{ $invoice->GetshortCreatedAttribute() }} +
+ +
+
+
+
+
+
+ {{ $invoice->GetshortCreatedAttribute() }} + #{{ $invoice->code }} + @php($status = $invoice->statu) + @if(isset($invoiceStatusBadges[$status])) + {{ __($invoiceStatusLabels[$status]) }} + @endif +
+
+ + + + + + + + + + + + + + @forelse($invoice->invoiceLines as $DocumentLine) + + + + + + + + + @empty + + @endforelse + + + + + + + + + + + @forelse($vatPrice as $vatRate) + + + + + @empty + + + + + @endforelse + + + + + +
{{ __('general_content.description_trans_key') }}{{ __('general_content.qty_trans_key') }}{{ __('general_content.price_trans_key') }}{{ __('general_content.discount_trans_key') }}{{ __('general_content.vat_trans_key') }}{{ __('general_content.delivery_notes_trans_key') }}
+
+
+
{{ $DocumentLine->orderLine?->label }}
+ {{ $DocumentLine->orderLine?->code }} +
+
+
{{ $DocumentLine->qty }} {{ $DocumentLine->orderLine?->Unit['label'] }}{{ $DocumentLine->selling_price }} {{ $Factory->curency }}{{ $DocumentLine->discount }} %{{ $DocumentLine->orderLine?->VAT['rate'] }} % + @if($DocumentLine->deliveryLine?->delivery) + + {{ $DocumentLine->deliveryLine->delivery->code }} + @endif +

{{ __('general_content.sub_total_trans_key') }}{{ $subPrice }} {{ $Factory->curency }}
{{ __('general_content.tax_trans_key') }} {{ $vatRate[0] }}%{{ number_format($vatRate[1], 2, '.', ' ') }} {{ $Factory->curency }}
{{ __('general_content.no_tax_trans_key') }}
{{ __('general_content.total_trans_key') }}{{ number_format($totalPrices, 2, '.', ' ') }} {{ $Factory->curency }}
+
+
+ + @if($invoice->comment) +
+
+

{{ __('general_content.comment_trans_key') }}

+

{{ $invoice->comment }}

+
+
+ @endif +
+ +
+
+
+

{{ __('general_content.customer_trans_key') }}

+

+ {{ $invoice->companie?->label }}
+ {{ $invoice->contact?->full_name }}
+ {{ $invoice->adresse?->adress }}
+ {{ $invoice->adresse?->zipcode }} {{ $invoice->adresse?->city }} +

+
+
+ +
+
+

{{ __('general_content.payment_method_trans_key') }}

+

{{ $invoice->payment_method?->label }}

+

{{ __('general_content.delivery_notes_trans_key') }}

+

{{ $invoice->deliverys_notes }}

+
+
+ +
+
+

{{ __('general_content.factory_trans_key') }}

+

+ {{ $Factory->name }}
+ {{ $Factory->address }}
+ {{ $Factory->zipcode }} {{ $Factory->city }}
+ {{ __('general_content.phone_trans_key') }} : {{ $Factory->phone_number }}
+ {{ __('general_content.email_trans_key') }} : {{ $Factory->mail }} +

+
+
+
+
+
+
+@endsection diff --git a/resources/views/customer/layouts/app.blade.php b/resources/views/customer/layouts/app.blade.php new file mode 100644 index 00000000..204fa148 --- /dev/null +++ b/resources/views/customer/layouts/app.blade.php @@ -0,0 +1,79 @@ + + + + {{-- Base Meta Tags --}} + + + + + + {{-- Title --}} + + @hasSection('title') + @yield('title') - + @endif + {{ $Factory->name ?? config('app.name', 'WebErpMesv2') }} + + + {{-- Base Stylesheets --}} + @if(!config('adminlte.enabled_laravel_mix')) + + + + + @if(config('adminlte.google_fonts.allowed', true)) + + @endif + @else + + @endif + + + + @stack('styles') + + + @php($customer = auth('customer')->user()) + + +
+
+ @yield('content') +
+
+ + + + + @stack('scripts') + + diff --git a/resources/views/customer/orders/show.blade.php b/resources/views/customer/orders/show.blade.php new file mode 100644 index 00000000..9e23447c --- /dev/null +++ b/resources/views/customer/orders/show.blade.php @@ -0,0 +1,263 @@ +@extends('customer.layouts.app') + +@section('title', __('general_content.order_trans_key') . ' #' . $order->code) + +@section('content') +
+
+
+

{{ __('general_content.order_trans_key') }} #{{ $order->code }}

+ {{ $order->GetshortCreatedAttribute() }} +
+ +
+
+
+
+
+
+ {{ $order->GetshortCreatedAttribute() }} + #{{ $order->code }} + @php($status = $order->statu) + @if(isset($orderStatusBadges[$status])) + {{ __($orderStatusLabels[$status]) }} + @endif +
+
+ + + + + + + + + + + + + + + @forelse($order->OrderLines as $DocumentLine) + + + + + + + + + + @empty + + @endforelse + + + + + + + + + + + @forelse($vatPrice as $vatRate) + + + + + @empty + + + + + @endforelse + + + + + +
{{ __('general_content.description_trans_key') }}{{ __('general_content.qty_trans_key') }}{{ __('general_content.price_trans_key') }}{{ __('general_content.discount_trans_key') }}{{ __('general_content.vat_trans_key') }}{{ __('general_content.delivery_status_trans_key') }}{{ __('general_content.invoice_status_trans_key') }}
+
+
+
{{ $DocumentLine->label }}
+ {{ $DocumentLine->code }} + @php + $guestDetail = $DocumentLine->OrderLineDetails ?? null; + $guestCustomRequirements = $guestDetail ? collect($guestDetail->custom_requirements ?? [])->filter(function ($requirement) { + return !empty($requirement['label'] ?? null) || !empty($requirement['value'] ?? null); + }) : collect(); + @endphp + @if($guestCustomRequirements->isNotEmpty()) +
    + @foreach($guestCustomRequirements as $requirement) +
  • {{ $requirement['label'] ?? __('Requirement') }}: {{ $requirement['value'] ?? '' }}
  • + @endforeach +
+ @endif +
+
+
{{ $DocumentLine->qty }} {{ $DocumentLine->Unit['label'] }}{{ $DocumentLine->selling_price }} {{ $Factory->curency }}{{ $DocumentLine->discount }} %{{ $DocumentLine->VAT['rate'] }} % + @if(1 == $DocumentLine->delivery_status) + {{ __('general_content.not_delivered_trans_key') }} + @endif + @if(2 == $DocumentLine->delivery_status) + + {{ __('general_content.partly_delivered_trans_key') }} ({{ $DocumentLine->delivered_qty }}) + + @endif + @if(3 == $DocumentLine->delivery_status) + + {{ __('general_content.delivered_trans_key') }} ({{ $DocumentLine->delivered_qty }}) + + @endif + @if(4 == $DocumentLine->delivery_status) + {{ __('general_content.delivered_without_dn_trans_key') }} ({{ $DocumentLine->delivered_qty }}) + @endif + + +
    + @foreach($DocumentLine->DeliveryLines as $deliveryLine) +
  • +
    {{ __('general_content.delivery_notes_trans_key') }}: {{ $deliveryLine->delivery->code }}
    +
    {{ __('general_content.qty_trans_key') }}: {{ $deliveryLine->qty }}
    +
    {{ __('general_content.created_at_trans_key') }}: {{ $deliveryLine->GetPrettyCreatedAttribute() }}
    + +
  • + @endforeach +
+
+
+ @if(1 == $DocumentLine->invoice_status) + {{ __('general_content.not_invoiced_trans_key') }} + @endif + @if(2 == $DocumentLine->invoice_status) + {{ __('general_content.partly_invoiced_trans_key') }} + @endif + @if(3 == $DocumentLine->invoice_status) + {{ __('general_content.invoiced_trans_key') }} + @endif +

{{ __('general_content.sub_total_trans_key') }}{{ $subPrice }} {{ $Factory->curency }}
{{ __('general_content.tax_trans_key') }} {{ $vatRate[0] }}%{{ number_format($vatRate[1], 2, '.', ' ') }} {{ $Factory->curency }}
{{ __('general_content.no_tax_trans_key') }}
{{ __('general_content.total_trans_key') }}{{ number_format($totalPrices, 2, '.', ' ') }} {{ $Factory->curency }}
+
+
+ +
+
+
+
+

{{ __('general_content.payment_methods_trans_key') }}

+

{{ $order->payment_method['label'] ?? '-' }}

+
+
+

{{ __('general_content.payment_conditions_trans_key') }}

+

{{ $order->payment_condition['label'] ?? '-' }}

+
+
+
+
+ +
+
+
+
+

{{ $Factory->name }}

+ @if($Factory->picture) + + @endif +
+
+

{{ __('general_content.adress_trans_key') }}

+
+ {{ $Factory->address }}
+ {{ $Factory->zipcode }} {{ $Factory->city }}
+ {{ __('general_content.phone_trans_key') }} : {{ $Factory->phone_number }}
+ {{ __('general_content.email_trans_key') }} : {{ $Factory->mail }}
+
+
+
+
+
+
+ +
+ @if ($order->comment) +
+
+

{{ __('general_content.comment_trans_key') }}

+

{{ $order->comment }}

+
+
+ @endif + + @if ($order->customer_reference) +
+
+

{{ __('general_content.identifier_trans_key') }}

+

{{ $order->customer_reference }}

+
+
+ @endif + +
+
+

{{ __('general_content.delevery_method_trans_key') }}

+ {{ $order->delevery_method['label'] ?? '-' }} +
+

{{ __('general_content.adress_trans_key') }}

+
+ {{ $order->companie['label'] ?? '-' }}
+ {{ $order->contact['civility'] ?? '' }} {{ $order->contact['first_name'] ?? '' }} {{ $order->contact['name'] ?? '' }}
+ {{ $order->adresse['adress'] ?? '' }}
+ {{ $order->adresse['zipcode'] ?? '' }} {{ $order->adresse['city'] ?? '' }}
+ {{ $order->adresse['country'] ?? '' }} +
+
+
+ +
+ @if($order->Rating->isEmpty()) +
+ @csrf +
+ + +
+ +
+
+ +
+ +
+
+
+ +
+ +
+
+ @else + @php($Rating = $order->Rating->first()) +
+ +
+ @for ($i = 1; $i <= 5; $i++) + @if ($i <= ($Rating->rating ?? 0)) + + @else + + @endif + @endfor +
+
+ @endif +
+
+
+
+
+@endsection diff --git a/routes/web.php b/routes/web.php index 2358d5dc..fe0b2d16 100644 --- a/routes/web.php +++ b/routes/web.php @@ -28,6 +28,22 @@ //Rating Route::post('/order/ratings', 'App\Http\Controllers\Workflow\OrdersRatingController@store')->name('order.ratings.store'); + Route::prefix('customer')->name('customer.')->group(function () { + Route::middleware('guest:customer')->group(function () { + Route::get('login', 'App\Http\Controllers\Customer\Auth\AuthenticatedSessionController@create')->name('login'); + Route::post('login', 'App\Http\Controllers\Customer\Auth\AuthenticatedSessionController@store')->name('login.store'); + }); + + Route::middleware('customer')->group(function () { + Route::post('logout', 'App\Http\Controllers\Customer\Auth\AuthenticatedSessionController@destroy')->name('logout'); + Route::get('/', 'App\Http\Controllers\Customer\PortalController@index')->name('dashboard'); + Route::get('/orders/{order}', 'App\Http\Controllers\Customer\PortalController@showOrder')->name('orders.show'); + Route::get('/deliveries/{delivery}', 'App\Http\Controllers\Customer\PortalController@showDelivery')->name('deliveries.show'); + Route::get('/invoices/{invoice}', 'App\Http\Controllers\Customer\PortalController@showInvoice')->name('invoices.show'); + }); + }); + + Route::get('/dashboard', 'App\Http\Controllers\HomeController@index')->middleware(['auth', 'check.factory'])->name('dashboard'); Route::group(['prefix' => 'workshop', 'middleware' => ['auth', 'check.factory']], function () {