mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-24 02:14:21 -04:00
Vendor Portal - Purchase Orders
This commit is contained in:
parent
cbdf0a827c
commit
063d600bbd
54
app/Http/Controllers/Auth/VendorContactLoginController.php
Normal file
54
app/Http/Controllers/Auth/VendorContactLoginController.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Events\Contact\ContactLoggedIn;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\ViewComposers\PortalComposer;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Account;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Company;
|
||||
use App\Utils\Ninja;
|
||||
use Auth;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Route;
|
||||
|
||||
class VendorContactLoginController extends Controller
|
||||
{
|
||||
use AuthenticatesUsers;
|
||||
|
||||
protected $redirectTo = '/vendor/purchase_orders';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// $this->middleware('guest:vendor', ['except' => ['logout']]);
|
||||
}
|
||||
|
||||
public function catch()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function logout()
|
||||
{
|
||||
Auth::guard('vendor')->logout();
|
||||
request()->session()->invalidate();
|
||||
|
||||
return redirect('/vendor');
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -84,6 +84,7 @@ class BaseController extends Controller
|
||||
'company.products.documents',
|
||||
'company.payments.paymentables',
|
||||
'company.payments.documents',
|
||||
'company.purchase_orders.documents',
|
||||
'company.payment_terms.company',
|
||||
'company.projects.documents',
|
||||
'company.recurring_expenses',
|
||||
@ -296,6 +297,13 @@ class BaseController extends Controller
|
||||
if(!$user->hasPermission('view_project'))
|
||||
$query->where('projects.user_id', $user->id)->orWhere('projects.assigned_user_id', $user->id);
|
||||
|
||||
},
|
||||
'company.purchase_orders'=> function ($query) use ($updated_at, $user) {
|
||||
$query->where('updated_at', '>=', $updated_at)->with('documents');
|
||||
|
||||
if(!$user->hasPermission('view_purchase_order'))
|
||||
$query->where('purchase_orders.user_id', $user->id)->orWhere('purchase_orders.assigned_user_id', $user->id);
|
||||
|
||||
},
|
||||
'company.quotes'=> function ($query) use ($updated_at, $user) {
|
||||
$query->where('updated_at', '>=', $updated_at)->with('invitations', 'documents');
|
||||
@ -533,6 +541,13 @@ class BaseController extends Controller
|
||||
if(!$user->hasPermission('view_project'))
|
||||
$query->where('projects.user_id', $user->id)->orWhere('projects.assigned_user_id', $user->id);
|
||||
|
||||
},
|
||||
'company.purchase_orders'=> function ($query) use ($created_at, $user) {
|
||||
$query->where('created_at', '>=', $created_at)->with('documents');
|
||||
|
||||
if(!$user->hasPermission('view_purchase_order'))
|
||||
$query->where('purchase_orders.user_id', $user->id)->orWhere('purchase_orders.assigned_user_id', $user->id);
|
||||
|
||||
},
|
||||
'company.quotes'=> function ($query) use ($created_at, $user) {
|
||||
$query->where('created_at', '>=', $created_at)->with('invitations', 'documents');
|
||||
|
@ -35,6 +35,7 @@ class SubdomainController extends BaseController
|
||||
'html',
|
||||
'lb',
|
||||
'shopify',
|
||||
'beta',
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
|
@ -14,6 +14,7 @@ namespace App\Http\Controllers\VendorPortal;
|
||||
use App\Events\Misc\InvitationWasViewed;
|
||||
use App\Events\PurchaseOrder\PurchaseOrderWasViewed;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\VendorPortal\PurchaseOrders\ProcessPurchaseOrdersInBulkRequest;
|
||||
use App\Http\Requests\VendorPortal\PurchaseOrders\ShowPurchaseOrderRequest;
|
||||
use App\Http\Requests\VendorPortal\PurchaseOrders\ShowPurchaseOrdersRequest;
|
||||
use App\Models\PurchaseOrder;
|
||||
@ -115,4 +116,73 @@ class PurchaseOrderController extends Controller
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function bulk(ProcessPurchaseOrdersInBulkRequest $request)
|
||||
{
|
||||
$transformed_ids = $this->transformKeys($request->purchase_orders);
|
||||
|
||||
if ($request->input('action') == 'download') {
|
||||
return $this->downloadInvoices((array) $transformed_ids);
|
||||
}
|
||||
|
||||
return redirect()
|
||||
->back()
|
||||
->with('message', ctrans('texts.no_action_provided'));
|
||||
}
|
||||
|
||||
public function downloadInvoices($ids)
|
||||
{
|
||||
|
||||
$purchase_orders = PurchaseOrder::whereIn('id', $ids)
|
||||
->where('vendor_id', auth()->guard('vendor')->user()->vendor_id)
|
||||
->withTrashed()
|
||||
->get();
|
||||
|
||||
if(count($purchase_orders) == 0)
|
||||
return back()->with(['message' => ctrans('texts.no_items_selected')]);
|
||||
|
||||
|
||||
if(count($purchase_orders) == 1){
|
||||
|
||||
$purchase_order = $purchase_orders->first();
|
||||
|
||||
$file = $purchase_order->service()->getPurchaseOrderPdf(auth()->guard('vendor')->user());
|
||||
|
||||
return response()->streamDownload(function () use($file) {
|
||||
echo Storage::get($file);
|
||||
}, basename($file), ['Content-Type' => 'application/pdf']);
|
||||
}
|
||||
|
||||
return $this->buildZip($purchase_orders);
|
||||
}
|
||||
|
||||
|
||||
private function buildZip($purchase_orders)
|
||||
{
|
||||
// create new archive
|
||||
$zipFile = new \PhpZip\ZipFile();
|
||||
try{
|
||||
|
||||
foreach ($purchase_orders as $purchase_order) {
|
||||
|
||||
#add it to the zip
|
||||
$zipFile->addFromString(basename($purchase_order->pdf_file_path()), file_get_contents($purchase_order->pdf_file_path(null, 'url', true)));
|
||||
|
||||
}
|
||||
|
||||
$filename = date('Y-m-d').'_'.str_replace(' ', '_', trans('texts.purchase_orders')).'.zip';
|
||||
$filepath = sys_get_temp_dir() . '/' . $filename;
|
||||
|
||||
$zipFile->saveAsFile($filepath) // save the archive to a file
|
||||
->close(); // close archive
|
||||
|
||||
return response()->download($filepath, $filename)->deleteFileAfterSend(true);
|
||||
|
||||
}
|
||||
catch(\PhpZip\Exception\ZipException $e){
|
||||
// handle exception
|
||||
}
|
||||
finally{
|
||||
$zipFile->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\VendorPortal\PurchaseOrders;
|
||||
|
||||
use App\Http\ViewComposers\PortalComposer;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class ProcessPurchaseOrdersInBulkRequest extends FormRequest
|
||||
{
|
||||
public function authorize()
|
||||
{
|
||||
return auth()->guard('vendor')->user()->vendor->company->enabled_modules & PortalComposer::MODULE_PURCHASE_ORDERS;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'purchase_orders' => ['array'],
|
||||
];
|
||||
}
|
||||
}
|
4
app/Jobs/Vendor/CreatePurchaseOrderPdf.php
vendored
4
app/Jobs/Vendor/CreatePurchaseOrderPdf.php
vendored
@ -70,7 +70,7 @@ class CreatePurchaseOrderPdf implements ShouldQueue
|
||||
*
|
||||
* @param $invitation
|
||||
*/
|
||||
public function __construct($invitation, $disk = 'public')
|
||||
public function __construct($invitation, $disk = null)
|
||||
{
|
||||
$this->invitation = $invitation;
|
||||
$this->company = $invitation->company;
|
||||
@ -83,7 +83,7 @@ class CreatePurchaseOrderPdf implements ShouldQueue
|
||||
$this->vendor = $invitation->contact->vendor;
|
||||
$this->vendor->load('company');
|
||||
|
||||
$this->disk = Ninja::isHosted() ? config('filesystems.default') : $disk;
|
||||
$this->disk = $disk ?? config('filesystems.default');
|
||||
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ namespace App\Models;
|
||||
use App\DataMapper\CompanySettings;
|
||||
use App\Models\Language;
|
||||
use App\Models\Presenters\CompanyPresenter;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Models\User;
|
||||
use App\Services\Notification\NotificationService;
|
||||
use App\Utils\Ninja;
|
||||
@ -192,6 +193,11 @@ class Company extends BaseModel
|
||||
return $this->hasMany(Subscription::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function purchase_orders()
|
||||
{
|
||||
return $this->hasMany(PurchaseOrder::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function task_statuses()
|
||||
{
|
||||
return $this->hasMany(TaskStatus::class)->withTrashed();
|
||||
|
@ -101,7 +101,7 @@ class PurchaseOrder extends BaseModel
|
||||
|
||||
const STATUS_DRAFT = 1;
|
||||
const STATUS_SENT = 2;
|
||||
const STATUS_APPROVED = 3;
|
||||
const STATUS_ACCEPTED = 3;
|
||||
const STATUS_CANCELLED = 4;
|
||||
|
||||
public static function stringStatus(int $status)
|
||||
@ -113,8 +113,8 @@ class PurchaseOrder extends BaseModel
|
||||
case self::STATUS_SENT:
|
||||
return ctrans('texts.sent');
|
||||
break;
|
||||
case self::STATUS_APPROVED:
|
||||
return ctrans('texts.approved');
|
||||
case self::STATUS_ACCEPTED:
|
||||
return ctrans('texts.accepted');
|
||||
break;
|
||||
case self::STATUS_CANCELLED:
|
||||
return ctrans('texts.cancelled');
|
||||
@ -134,8 +134,8 @@ class PurchaseOrder extends BaseModel
|
||||
case self::STATUS_SENT:
|
||||
return '<h5><span class="badge badge-primary">'.ctrans('texts.sent').'</span></h5>';
|
||||
break;
|
||||
case self::STATUS_APPROVED:
|
||||
return '<h5><span class="badge badge-primary">'.ctrans('texts.approved').'</span></h5>';
|
||||
case self::STATUS_ACCEPTED:
|
||||
return '<h5><span class="badge badge-primary">'.ctrans('texts.accepted').'</span></h5>';
|
||||
break;
|
||||
case self::STATUS_CANCELLED:
|
||||
return '<h5><span class="badge badge-secondary">'.ctrans('texts.cancelled').'</span></h5>';
|
||||
|
@ -341,7 +341,7 @@ class InvoiceService
|
||||
if(Storage::disk(config('filesystems.default'))->exists($this->invoice->client->invoice_filepath($invitation) . $this->invoice->numberFormatter().'.pdf'))
|
||||
Storage::disk(config('filesystems.default'))->delete($this->invoice->client->invoice_filepath($invitation) . $this->invoice->numberFormatter().'.pdf');
|
||||
|
||||
if(Ninja::isHosted() && Storage::disk(config('filesystems.default'))->exists($this->invoice->client->invoice_filepath($invitation) . $this->invoice->numberFormatter().'.pdf')) {
|
||||
if(Ninja::isHosted() && Storage::disk('public')->exists($this->invoice->client->invoice_filepath($invitation) . $this->invoice->numberFormatter().'.pdf')) {
|
||||
Storage::disk('public')->delete($this->invoice->client->invoice_filepath($invitation) . $this->invoice->numberFormatter().'.pdf');
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ use App\Models\Payment;
|
||||
use App\Models\PaymentTerm;
|
||||
use App\Models\Product;
|
||||
use App\Models\Project;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Models\Quote;
|
||||
use App\Models\RecurringExpense;
|
||||
use App\Models\RecurringInvoice;
|
||||
@ -39,6 +40,7 @@ use App\Models\TaskStatus;
|
||||
use App\Models\TaxRate;
|
||||
use App\Models\User;
|
||||
use App\Models\Webhook;
|
||||
use App\Transformers\PurchaseOrderTransformer;
|
||||
use App\Transformers\RecurringExpenseTransformer;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use stdClass;
|
||||
@ -95,6 +97,7 @@ class CompanyTransformer extends EntityTransformer
|
||||
'task_statuses',
|
||||
'subscriptions',
|
||||
'recurring_expenses',
|
||||
'purchase_orders',
|
||||
];
|
||||
|
||||
/**
|
||||
@ -391,4 +394,11 @@ class CompanyTransformer extends EntityTransformer
|
||||
|
||||
return $this->includeCollection($company->subscriptions, $transformer, Subscription::class);
|
||||
}
|
||||
|
||||
public function includePurchaseOrders(Company $company)
|
||||
{
|
||||
$transformer = new PurchaseOrderTransformer($this->serializer);
|
||||
|
||||
return $this->includeCollection($company->purchase_orders, $transformer, PurchaseOrder::class);
|
||||
}
|
||||
}
|
||||
|
2
public/js/clients/purchase_orders/action-selectors.js
vendored
Normal file
2
public/js/clients/purchase_orders/action-selectors.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/*! For license information please see action-selectors.js.LICENSE.txt */
|
||||
(()=>{function e(e,n){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=function(e,n){if(!e)return;if("string"==typeof e)return t(e,n);var r=Object.prototype.toString.call(e).slice(8,-1);"Object"===r&&e.constructor&&(r=e.constructor.name);if("Map"===r||"Set"===r)return Array.from(e);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return t(e,n)}(e))||n&&e&&"number"==typeof e.length){r&&(e=r);var o=0,c=function(){};return{s:c,n:function(){return o>=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:c}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,l=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return a=e.done,e},e:function(e){l=!0,i=e},f:function(){try{a||null==r.return||r.return()}finally{if(l)throw i}}}}function t(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(new(function(){function t(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),this.parentElement=document.querySelector(".form-check-parent"),this.parentForm=document.getElementById("bulkActions")}var r,o,c;return r=t,o=[{key:"watchCheckboxes",value:function(e){var t=this;document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})),document.querySelectorAll(".form-check-child").forEach((function(n){e.checked?(n.checked=e.checked,t.processChildItem(n,document.getElementById("bulkActions"))):(n.checked=!1,document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})))}))}},{key:"processChildItem",value:function(t,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(r.hasOwnProperty("single")&&document.querySelectorAll(".child-hidden-input").forEach((function(e){return e.remove()})),!1!==t.checked){var o=document.createElement("INPUT");o.setAttribute("name","purchase_orders[]"),o.setAttribute("value",t.dataset.value),o.setAttribute("class","child-hidden-input"),o.hidden=!0,n.append(o)}else{var c,i=document.querySelectorAll("input.child-hidden-input"),a=e(i);try{for(a.s();!(c=a.n()).done;){var l=c.value;l.value==t.dataset.value&&l.remove()}}catch(e){a.e(e)}finally{a.f()}}}},{key:"handle",value:function(){var t=this;this.parentElement.addEventListener("click",(function(){t.watchCheckboxes(t.parentElement)}));var n,r=e(document.querySelectorAll(".form-check-child"));try{var o=function(){var e=n.value;e.addEventListener("click",(function(){t.processChildItem(e,t.parentForm)}))};for(r.s();!(n=r.n()).done;)o()}catch(e){r.e(e)}finally{r.f()}}}],o&&n(r.prototype,o),c&&n(r,c),Object.defineProperty(r,"prototype",{writable:!1}),t}())).handle()})();
|
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
@ -4,6 +4,7 @@
|
||||
"/js/clients/payments/authorize-credit-card-payment.js": "/js/clients/payments/authorize-credit-card-payment.js?id=803182f668c39d631ca5c55437876da4",
|
||||
"/js/clients/payments/stripe-ach.js": "/js/clients/payments/stripe-ach.js?id=7bed15f51bca764378d9a3aa605b8664",
|
||||
"/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=d4f86ddee4e8a1d6e9719010aa0fe62b",
|
||||
"/js/clients/purchase_orders/action-selectors.js": "/js/clients/purchase_orders/action-selectors.js?id=160b8161599fc2429b449b0970d3ba6c",
|
||||
"/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=b88ad7c8881cc87df07b129c5a7c76df",
|
||||
"/js/clients/payments/stripe-sofort.js": "/js/clients/payments/stripe-sofort.js?id=1c5493a4c53a5b862d07ee1818179ea9",
|
||||
"/js/clients/payments/stripe-alipay.js": "/js/clients/payments/stripe-alipay.js?id=0274ab4f8d2b411f2a2fe5142301e7af",
|
||||
|
79
resources/js/clients/purchase_orders/action-selectors.js
vendored
Normal file
79
resources/js/clients/purchase_orders/action-selectors.js
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
class ActionSelectors {
|
||||
constructor() {
|
||||
this.parentElement = document.querySelector('.form-check-parent');
|
||||
this.parentForm = document.getElementById('bulkActions');
|
||||
}
|
||||
|
||||
watchCheckboxes(parentElement) {
|
||||
document
|
||||
.querySelectorAll('.child-hidden-input')
|
||||
.forEach((element) => element.remove());
|
||||
|
||||
document.querySelectorAll('.form-check-child').forEach((child) => {
|
||||
if (parentElement.checked) {
|
||||
child.checked = parentElement.checked;
|
||||
this.processChildItem(
|
||||
child,
|
||||
document.getElementById('bulkActions')
|
||||
);
|
||||
} else {
|
||||
child.checked = false;
|
||||
document
|
||||
.querySelectorAll('.child-hidden-input')
|
||||
.forEach((element) => element.remove());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
processChildItem(element, parent, options = {}) {
|
||||
if (options.hasOwnProperty('single')) {
|
||||
document
|
||||
.querySelectorAll('.child-hidden-input')
|
||||
.forEach((element) => element.remove());
|
||||
}
|
||||
|
||||
if (element.checked === false) {
|
||||
let inputs = document.querySelectorAll('input.child-hidden-input');
|
||||
|
||||
for (let i of inputs) {
|
||||
if (i.value == element.dataset.value) i.remove();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let _temp = document.createElement('INPUT');
|
||||
|
||||
_temp.setAttribute('name', 'purchase_orders[]');
|
||||
_temp.setAttribute('value', element.dataset.value);
|
||||
_temp.setAttribute('class', 'child-hidden-input');
|
||||
_temp.hidden = true;
|
||||
|
||||
parent.append(_temp);
|
||||
}
|
||||
|
||||
handle() {
|
||||
this.parentElement.addEventListener('click', () => {
|
||||
this.watchCheckboxes(this.parentElement);
|
||||
});
|
||||
|
||||
for (let child of document.querySelectorAll('.form-check-child')) {
|
||||
child.addEventListener('click', () => {
|
||||
this.processChildItem(child, this.parentForm);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @handle **/
|
||||
new ActionSelectors().handle();
|
@ -4628,7 +4628,7 @@ $LANG = array(
|
||||
'purchase_order_date' => 'Purchase Order Date',
|
||||
'purchase_orders' => 'Purchase Orders',
|
||||
'purchase_order_number_placeholder' => 'Purchase Order # :purchase_order',
|
||||
|
||||
'accepted' => 'Accepted',
|
||||
);
|
||||
|
||||
return $LANG;
|
||||
|
@ -121,5 +121,5 @@
|
||||
</div>
|
||||
|
||||
@push('footer')
|
||||
<script src="{{ asset('js/clients/invoices/action-selectors.js') }}"></script>
|
||||
<script src="{{ asset('js/clients/purchase_orders/action-selectors.js') }}"></script>
|
||||
@endpush
|
||||
|
@ -0,0 +1,18 @@
|
||||
@extends('portal.ninja2020.layout.vendor_app')
|
||||
@section('meta_title', ctrans('texts.purchase_orders'))
|
||||
|
||||
@section('header')
|
||||
@if($errors->any())
|
||||
<div class="alert alert-failure mb-4">
|
||||
@foreach($errors->all() as $error)
|
||||
<p>{{ $error }}</p>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
@endsection
|
||||
|
||||
@section('body')
|
||||
<div class="flex items-center">
|
||||
<h1>Vendor Portal</h1>
|
||||
</div>
|
||||
@endsection
|
@ -9,10 +9,13 @@
|
||||
| is assigned the "api" middleware group. Enjoy building your API!
|
||||
|
|
||||
*/
|
||||
use App\Http\Controllers\Auth\VendorContactLoginController;
|
||||
use App\Http\Controllers\VendorPortal\InvitationController;
|
||||
use App\Http\Controllers\VendorPortal\PurchaseOrderController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::get('vendor', [VendorContactLoginController::class, 'catch'])->name('vendor.catchall')->middleware(['domain_db', 'contact_account','vendor_locale']); //catch all
|
||||
|
||||
Route::group(['middleware' => ['invite_db'], 'prefix' => 'vendor', 'as' => 'vendor.'], function () {
|
||||
/*Invitation catches*/
|
||||
Route::get('purchase_order/{invitation_key}', [InvitationController::class, 'purchaseOrder']);
|
||||
@ -30,5 +33,6 @@ Route::group(['middleware' => ['auth:vendor', 'vendor_locale', 'domain_db'], 'pr
|
||||
|
||||
Route::get('profile/{vendor_contact}/edit', [PurchaseOrderController::class, 'index'])->name('profile.edit');
|
||||
Route::post('invoices/payment', [PurchaseOrderController::class, 'bulk'])->name('purchase_orders.bulk');
|
||||
Route::get('logout', [VendorContactLoginController::class, 'logout'])->name('logout');
|
||||
|
||||
});
|
4
webpack.mix.js
vendored
4
webpack.mix.js
vendored
@ -18,6 +18,10 @@ mix.js("resources/js/app.js", "public/js")
|
||||
"resources/js/clients/invoices/action-selectors.js",
|
||||
"public/js/clients/invoices/action-selectors.js"
|
||||
)
|
||||
.js(
|
||||
"resources/js/clients/purchase_orders/action-selectors.js",
|
||||
"public/js/clients/purchase_orders/action-selectors.js"
|
||||
)
|
||||
.js(
|
||||
"resources/js/clients/invoices/payment.js",
|
||||
"public/js/clients/invoices/payment.js"
|
||||
|
Loading…
x
Reference in New Issue
Block a user