diff --git a/app/DataMapper/CompanySettings.php b/app/DataMapper/CompanySettings.php index 241751974daf..758c494e15c8 100644 --- a/app/DataMapper/CompanySettings.php +++ b/app/DataMapper/CompanySettings.php @@ -291,7 +291,10 @@ class CompanySettings extends BaseSettings public $email_from_name = ''; public $auto_archive_invoice_cancelled = false; + public $vendor_portal_enable_uploads=false; + public static $casts = [ + 'vendor_portal_enable_uploads' => 'bool', 'besr_id' => 'string', 'qr_iban' => 'string', 'email_subject_purchase_order' => 'string', diff --git a/app/Http/Controllers/PurchaseOrderController.php b/app/Http/Controllers/PurchaseOrderController.php index 77027d0789db..e7ec463ab6c2 100644 --- a/app/Http/Controllers/PurchaseOrderController.php +++ b/app/Http/Controllers/PurchaseOrderController.php @@ -23,21 +23,25 @@ use App\Http\Requests\PurchaseOrder\EditPurchaseOrderRequest; use App\Http\Requests\PurchaseOrder\ShowPurchaseOrderRequest; use App\Http\Requests\PurchaseOrder\StorePurchaseOrderRequest; use App\Http\Requests\PurchaseOrder\UpdatePurchaseOrderRequest; +use App\Http\Requests\PurchaseOrder\UploadPurchaseOrderRequest; use App\Jobs\Invoice\ZipInvoices; use App\Jobs\PurchaseOrder\PurchaseOrderEmail; use App\Jobs\PurchaseOrder\ZipPurchaseOrders; +use App\Models\Account; use App\Models\Client; use App\Models\PurchaseOrder; use App\Repositories\PurchaseOrderRepository; use App\Transformers\PurchaseOrderTransformer; use App\Utils\Ninja; use App\Utils\Traits\MakesHash; +use App\Utils\Traits\SavesDocuments; use Illuminate\Http\Response; use Illuminate\Support\Facades\Storage; class PurchaseOrderController extends BaseController { use MakesHash; + use SavesDocuments; protected $entity_type = PurchaseOrder::class; protected $entity_transformer = PurchaseOrderTransformer::class; @@ -655,4 +659,69 @@ class PurchaseOrderController extends BaseController break; } } + + /** + * Update the specified resource in storage. + * + * @param UploadPurchaseOrderRequest $request + * @param PurchaseOrder $purchase_order + * @return Response + * + * + * + * @OA\Put( + * path="/api/v1/purchase_orders/{id}/upload", + * operationId="uploadPurchaseOrder", + * tags={"purchase_orders"}, + * summary="Uploads a document to a purchase_orders", + * description="Handles the uploading of a document to a purchase_order", + * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), + * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Parameter( + * name="id", + * in="path", + * description="The Purchase Order Hashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns the Purchase Order object", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * @OA\JsonContent(ref="#/components/schemas/Vendor"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + * + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + */ + public function upload(UploadPurchaseOrderRequest $request, PurchaseOrder $purchase_order) + { + + if(!$this->checkFeature(Account::FEATURE_DOCUMENTS)) + return $this->featureFailure(); + + if ($request->has('documents')) + $this->saveDocuments($request->file('documents'), $purchase_order); + + return $this->itemResponse($purchase_order->fresh()); + + } + } diff --git a/app/Http/Controllers/VendorPortal/UploadController.php b/app/Http/Controllers/VendorPortal/UploadController.php new file mode 100644 index 000000000000..23f11e4827a2 --- /dev/null +++ b/app/Http/Controllers/VendorPortal/UploadController.php @@ -0,0 +1,41 @@ +saveDocuments($request->getFile(), $purchase_order, true); + + return response([], 200); + } +} diff --git a/app/Http/Requests/ClientPortal/Uploads/StoreUploadRequest.php b/app/Http/Requests/ClientPortal/Uploads/StoreUploadRequest.php index a106df59e9ab..27cce5800c2e 100644 --- a/app/Http/Requests/ClientPortal/Uploads/StoreUploadRequest.php +++ b/app/Http/Requests/ClientPortal/Uploads/StoreUploadRequest.php @@ -1,4 +1,14 @@ user()->can('edit', $this->purchase_order); + } + + public function rules() + { + + $rules = []; + + if($this->input('documents')) + $rules['documents'] = 'file|mimes:csv,png,ai,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx|max:2000000'; + + return $rules; + + } +} diff --git a/app/Http/Requests/VendorPortal/Uploads/StoreUploadRequest.php b/app/Http/Requests/VendorPortal/Uploads/StoreUploadRequest.php new file mode 100644 index 000000000000..686e8dab6d09 --- /dev/null +++ b/app/Http/Requests/VendorPortal/Uploads/StoreUploadRequest.php @@ -0,0 +1,55 @@ +guard('vendor')->user()->vendor->company->getSetting('vendor_portal_enable_uploads'); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'file' => ['file', 'mimes:png,ai,jpeg,tiff,pdf,gif,psd,txt,doc,xls,ppt,xlsx,docx,pptx|max:20000'], + ]; + } + + /** + * Since saveDocuments() expects an array of uploaded files, + * we need to convert it to an array before uploading. + * + * @return mixed + */ + public function getFile() + { + if (gettype($this->file) !== 'array') { + return [$this->file]; + } + + return $this->file; + } +} diff --git a/app/Transformers/PurchaseOrderTransformer.php b/app/Transformers/PurchaseOrderTransformer.php index 0163714e6009..5364a534c24e 100644 --- a/app/Transformers/PurchaseOrderTransformer.php +++ b/app/Transformers/PurchaseOrderTransformer.php @@ -14,6 +14,7 @@ namespace App\Transformers; use App\Models\PurchaseOrder; use App\Models\PurchaseOrderInvitation; +use App\Transformers\DocumentTransformer; use App\Utils\Traits\MakesHash; class PurchaseOrderTransformer extends EntityTransformer @@ -22,6 +23,7 @@ class PurchaseOrderTransformer extends EntityTransformer protected $defaultIncludes = [ 'invitations', + 'documents' ]; public function includeInvitations(PurchaseOrder $purchase_order) @@ -31,6 +33,14 @@ class PurchaseOrderTransformer extends EntityTransformer return $this->includeCollection($purchase_order->invitations, $transformer, PurchaseOrderInvitation::class); } + + public function includeDocuments(PurchaseOrder $purchase_order) + { + $transformer = new DocumentTransformer($this->serializer); + + return $this->includeCollection($purchase_order->documents, $transformer, Document::class); + } + public function transform(PurchaseOrder $purchase_order) { return [ diff --git a/resources/views/portal/ninja2020/purchase_orders/includes/upload.blade.php b/resources/views/portal/ninja2020/purchase_orders/includes/upload.blade.php new file mode 100644 index 000000000000..3828defc83a7 --- /dev/null +++ b/resources/views/portal/ninja2020/purchase_orders/includes/upload.blade.php @@ -0,0 +1,20 @@ + + + +{{-- TODO: HOSTED --}} +