Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.testing
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
APP_NAME=Laravel
APP_ENV=local
APP_ENV=testing
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
Expand Down
2 changes: 1 addition & 1 deletion .php-cs-fixer.cache
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"php":"8.4.11","version":"3.85.1:v3.85.1#2fb6d7f6c3398dca5786a1635b27405d73a417ba","indent":" ","lineEnding":"\n","rules":{"binary_operator_spaces":{"default":"at_least_single_space"},"blank_line_after_opening_tag":true,"blank_line_between_import_groups":true,"blank_lines_before_namespace":true,"braces_position":{"allow_single_line_empty_anonymous_classes":true},"class_definition":{"inline_constructor_arguments":false,"space_before_parenthesis":true},"compact_nullable_type_declaration":true,"declare_equal_normalize":true,"lowercase_cast":true,"lowercase_static_reference":true,"new_with_parentheses":true,"no_blank_lines_after_class_opening":true,"no_extra_blank_lines":{"tokens":["use"]},"no_leading_import_slash":true,"no_whitespace_in_blank_line":true,"ordered_class_elements":{"order":["use_trait"]},"ordered_imports":{"imports_order":["class","function","const"],"sort_algorithm":"none"},"return_type_declaration":true,"short_scalar_cast":true,"single_import_per_statement":{"group_to_single_imports":false},"single_space_around_construct":{"constructs_followed_by_a_single_space":["abstract","as","case","catch","class","const_import","do","else","elseif","final","finally","for","foreach","function","function_import","if","insteadof","interface","namespace","new","private","protected","public","static","switch","trait","try","use","use_lambda","while"],"constructs_preceded_by_a_single_space":["as","else","elseif","use_lambda"]},"single_trait_insert_per_statement":true,"ternary_operator_spaces":true,"unary_operator_spaces":{"only_dec_inc":true},"visibility_required":true,"blank_line_after_namespace":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"method_argument_space":{"attribute_placement":"ignore","on_multiline":"ensure_fully_multiline"},"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_line_after_imports":true,"spaces_inside_parentheses":true,"statement_indentation":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"encoding":true,"full_opening_tag":true},"hashes":{"app\/Providers\/AppServiceProvider.php":"50869d5235b70741292b4181483fb3a1","app\/Providers\/TelescopeServiceProvider.php":"50d77d91eb762925829c525b616b8ede","app\/Providers\/AuthServiceProvider.php":"9ed5c3030497fc6c2a47f8e8826be16d","app\/Providers\/RouteServiceProvider.php":"2c8cf6e7e10996320f03213cf6fd80c9","app\/Providers\/HorizonServiceProvider.php":"3e77ce1476fe086c39ab902a16466867","app\/Providers\/EventServiceProvider.php":"34134ae301e25e33b1c9ec617568517f","app\/Models\/Sale.php":"3185fb625054cb0307c381f2a95b6031","app\/Models\/Inventory.php":"bcf3b8fdff335bb1bea129368f16dd49","app\/Models\/Product.php":"c393b5ea82bf6a0f0a94222ad310c7fa","app\/Models\/Purchase.php":"0c8e2d61f21462761a4759d312f1fc7b","app\/Models\/User.php":"34e86f5ca68b584e124e81eb3d3f45e1","app\/Models\/Role.php":"26c273b5302f20e7ba86cb377d5ca30d","app\/Models\/Permission.php":"ec9f1430ebf6d98abb1e496e6909e9f7","app\/Saloon\/Connectors\/TextbeltConnector.php":"bee6b70c66a9efc22add60d9fe33d88d","app\/Saloon\/Middlewares\/SaloonLogger.php":"105c98edd63c4b3d8319efd1a0ffd598","app\/Saloon\/Requests\/VerifyTextbeltOTP.php":"6ab3989a6d5267bf63a1618a8ed1a6f6","app\/Saloon\/Requests\/GenerateTextbeltOTP.php":"bc22c4cafdc3bf9687470863645bfe00","app\/Policies\/InventoryPolicy.php":"85fc6635cb57c108d4b0484fb08b0b9a","app\/Policies\/PurchasePolicy.php":"550ab44c86fa6257bcb5f61e1ef19a02","app\/Policies\/ProductPolicy.php":"0384857d1d1ddf1670fd59f13ac08e97","app\/Policies\/UserPolicy.php":"73d992a08e36de2193c252f6f85851a6","app\/Policies\/SalePolicy.php":"6e573fe5e8875e729f648cbf9ece3b34","app\/Exports\/InventoryExport.php":"702cfefafec0fa02f6904cbc03b4ce95","app\/Http\/Middleware\/ApiLocalization.php":"7df372cb93193297702f9d03c13ace76","app\/Http\/Controllers\/UserController.php":"a710cd139d253bb7ecc39416351a85b2","app\/Http\/Controllers\/PurchaseController.php":"5bf4177505312ad861d9322c20235e92","app\/Http\/Controllers\/AuthController.php":"ddfb72a54d6d1ec0b9dc7d5d96539378","app\/Http\/Controllers\/SaleController.php":"bf091ecb4c4dd6445db5cec7672e9d97","app\/Http\/Controllers\/InventoryController.php":"0a1c7d667146b857d85cbbd7b216065c","app\/Http\/Controllers\/ProductController.php":"a1b4ec750a74a6fba4a8c24027f57735","app\/Http\/Kernel.php":"e62999818bb65d413780164884c90960","app\/Actions\/ExportInventory.php":"a0650617c8921d03eb6e5adc506689ac","app\/Events\/ProductsSold.php":"bc0c0bc7ca203bbf7612f4cb913efb01","app\/Events\/UserCreated.php":"9c854425a69334cddb46c752065d8988","app\/Events\/ProductsPurchased.php":"89ccd011c461d49b9fad2a45c5f096ed","app\/Listeners\/SendUserVerificationNotifications.php":"52aefd22fd2907dba1c0cd1b62103b10","app\/Listeners\/UpdateProduct.php":"d6ef0bc9493dd90076eaa2f5ce9f9556","app\/Listeners\/CreateProduct.php":"edb7a12d9cad824b0c190c7861a85dd6","app\/Listeners\/UpdateInventory.php":"147758a50f0c6c71f6e37fb4bb5d78b3","app\/Listeners\/CreateInventory.php":"abd01b446f5f60da5407f3d40aeb9802","app\/Notifications\/SendPhoneVerificationNotification.php":"61d4cb57170fd42a8dc83e7bbaaba612","app\/Notifications\/Contracts\/TextbeltMessage.php":"eae9bb4b7182aab740cbea159c516888","app\/Notifications\/Channels\/TextbeltChannel.php":"c47379b8dd0b252de39b7992da7d3c01","app\/Events\/ProductCreated.php":"1fa7d37bdfd1c57cce06b4746d1979fc","app\/Listeners\/UpdateProductImageUrl.php":"506670cd825c3dde6c2c9c3e806877b4","app\/Http\/Resources\/RoleResource.php":"74c49f71f6b8d35dc512f885e11aca2a","app\/Http\/Resources\/UserResource.php":"deeec5be8483364fec89064984769f22"}}
{"php":"8.4.11","version":"3.85.1:v3.85.1#2fb6d7f6c3398dca5786a1635b27405d73a417ba","indent":" ","lineEnding":"\n","rules":{"binary_operator_spaces":{"default":"at_least_single_space"},"blank_line_after_opening_tag":true,"blank_line_between_import_groups":true,"blank_lines_before_namespace":true,"braces_position":{"allow_single_line_empty_anonymous_classes":true},"class_definition":{"inline_constructor_arguments":false,"space_before_parenthesis":true},"compact_nullable_type_declaration":true,"declare_equal_normalize":true,"lowercase_cast":true,"lowercase_static_reference":true,"new_with_parentheses":true,"no_blank_lines_after_class_opening":true,"no_extra_blank_lines":{"tokens":["use"]},"no_leading_import_slash":true,"no_whitespace_in_blank_line":true,"ordered_class_elements":{"order":["use_trait"]},"ordered_imports":{"imports_order":["class","function","const"],"sort_algorithm":"none"},"return_type_declaration":true,"short_scalar_cast":true,"single_import_per_statement":{"group_to_single_imports":false},"single_space_around_construct":{"constructs_followed_by_a_single_space":["abstract","as","case","catch","class","const_import","do","else","elseif","final","finally","for","foreach","function","function_import","if","insteadof","interface","namespace","new","private","protected","public","static","switch","trait","try","use","use_lambda","while"],"constructs_preceded_by_a_single_space":["as","else","elseif","use_lambda"]},"single_trait_insert_per_statement":true,"ternary_operator_spaces":true,"unary_operator_spaces":{"only_dec_inc":true},"visibility_required":true,"blank_line_after_namespace":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"function_declaration":true,"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"method_argument_space":{"attribute_placement":"ignore","on_multiline":"ensure_fully_multiline"},"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_line_after_imports":true,"spaces_inside_parentheses":true,"statement_indentation":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"encoding":true,"full_opening_tag":true},"hashes":{"app\/Providers\/AppServiceProvider.php":"50869d5235b70741292b4181483fb3a1","app\/Providers\/TelescopeServiceProvider.php":"50d77d91eb762925829c525b616b8ede","app\/Providers\/AuthServiceProvider.php":"9ed5c3030497fc6c2a47f8e8826be16d","app\/Providers\/RouteServiceProvider.php":"2c8cf6e7e10996320f03213cf6fd80c9","app\/Providers\/HorizonServiceProvider.php":"3e77ce1476fe086c39ab902a16466867","app\/Providers\/EventServiceProvider.php":"34134ae301e25e33b1c9ec617568517f","app\/Models\/Sale.php":"75153feaf2619fcccee4bf8873afa0ee","app\/Models\/Inventory.php":"bcf3b8fdff335bb1bea129368f16dd49","app\/Models\/Product.php":"c393b5ea82bf6a0f0a94222ad310c7fa","app\/Models\/Purchase.php":"0c8e2d61f21462761a4759d312f1fc7b","app\/Models\/User.php":"34e86f5ca68b584e124e81eb3d3f45e1","app\/Models\/Role.php":"26c273b5302f20e7ba86cb377d5ca30d","app\/Models\/Permission.php":"ec9f1430ebf6d98abb1e496e6909e9f7","app\/Saloon\/Connectors\/TextbeltConnector.php":"bee6b70c66a9efc22add60d9fe33d88d","app\/Saloon\/Middlewares\/SaloonLogger.php":"105c98edd63c4b3d8319efd1a0ffd598","app\/Saloon\/Requests\/VerifyTextbeltOTP.php":"6ab3989a6d5267bf63a1618a8ed1a6f6","app\/Saloon\/Requests\/GenerateTextbeltOTP.php":"bc22c4cafdc3bf9687470863645bfe00","app\/Policies\/InventoryPolicy.php":"85fc6635cb57c108d4b0484fb08b0b9a","app\/Policies\/PurchasePolicy.php":"550ab44c86fa6257bcb5f61e1ef19a02","app\/Policies\/ProductPolicy.php":"0384857d1d1ddf1670fd59f13ac08e97","app\/Policies\/UserPolicy.php":"73d992a08e36de2193c252f6f85851a6","app\/Policies\/SalePolicy.php":"6e573fe5e8875e729f648cbf9ece3b34","app\/Exports\/InventoryExport.php":"702cfefafec0fa02f6904cbc03b4ce95","app\/Http\/Middleware\/ApiLocalization.php":"7df372cb93193297702f9d03c13ace76","app\/Http\/Controllers\/UserController.php":"c5cd48c1c358b7161388a14ef700f982","app\/Http\/Controllers\/PurchaseController.php":"53050317a02f1ddf8acdfa52eef513ec","app\/Http\/Controllers\/AuthController.php":"ddfb72a54d6d1ec0b9dc7d5d96539378","app\/Http\/Controllers\/SaleController.php":"65a04c708fddb5296158b4639489ace5","app\/Http\/Controllers\/InventoryController.php":"7195e3051f73c6b1276dcafc4f3b4371","app\/Http\/Controllers\/ProductController.php":"382d2747b334c3c110c1da38b276a5a7","app\/Http\/Kernel.php":"e62999818bb65d413780164884c90960","app\/Actions\/ExportInventory.php":"a0650617c8921d03eb6e5adc506689ac","app\/Events\/ProductsSold.php":"bc0c0bc7ca203bbf7612f4cb913efb01","app\/Events\/UserCreated.php":"9c854425a69334cddb46c752065d8988","app\/Events\/ProductsPurchased.php":"89ccd011c461d49b9fad2a45c5f096ed","app\/Listeners\/SendUserVerificationNotifications.php":"52aefd22fd2907dba1c0cd1b62103b10","app\/Listeners\/UpdateProduct.php":"d6ef0bc9493dd90076eaa2f5ce9f9556","app\/Listeners\/CreateProduct.php":"edb7a12d9cad824b0c190c7861a85dd6","app\/Listeners\/UpdateInventory.php":"147758a50f0c6c71f6e37fb4bb5d78b3","app\/Listeners\/CreateInventory.php":"f3a32bfc3eaae14c499feea0b82b7794","app\/Notifications\/SendPhoneVerificationNotification.php":"61d4cb57170fd42a8dc83e7bbaaba612","app\/Notifications\/Contracts\/TextbeltMessage.php":"eae9bb4b7182aab740cbea159c516888","app\/Notifications\/Channels\/TextbeltChannel.php":"c47379b8dd0b252de39b7992da7d3c01","app\/Events\/ProductCreated.php":"1fa7d37bdfd1c57cce06b4746d1979fc","app\/Listeners\/UpdateProductImageUrl.php":"506670cd825c3dde6c2c9c3e806877b4","app\/Http\/Resources\/RoleResource.php":"74c49f71f6b8d35dc512f885e11aca2a","app\/Http\/Resources\/UserResource.php":"672ed11dc3cd71b66d6a0048592e9887","app\/Http\/Resources\/ProductResource.php":"79a4339c22f1335a49dad3a6dc67d2a0","app\/Http\/Resources\/PurchaseResource.php":"bd23e432f5f41a4f8d56d0dd052edf05","app\/Http\/Resources\/SaleResource.php":"80c09fc6b4754301b970743d9e9775ba","app\/Http\/Resources\/InventoryResource.php":"2aa5931065e8a5a1f877752d330be7b4","app\/Actions\/UploadImage.php":"280dcfe3c370a9f5e237d1b57e41a331"}}
25 changes: 25 additions & 0 deletions app/Actions/UploadImage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace App\Actions;

use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\JsonResponse;

class UploadImage
{
public function __invoke(Request $request): JsonResponse
{
$request->validate([
'image' => 'required|image|max:5120', // max 5MB
]);

$file = $request->file('image');
$filename = 'temp/' . Str::random(40) . '.' . $file->getClientOriginalExtension();
Storage::disk('s3')->putFileAs('temp', $file, basename($filename), 'public');
$url = Storage::disk('s3')->url($filename);

return response()->json(['url' => $url]);
}
}
5 changes: 4 additions & 1 deletion app/Http/Controllers/InventoryController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
namespace App\Http\Controllers;

use App\Models\Inventory;
use App\Policies\InventoryPolicy;
use Orion\Http\Controllers\Controller;
use App\Http\Resources\InventoryResource;

class InventoryController extends Controller
{
protected $model = Inventory::class;
protected $policy = \App\Policies\InventoryPolicy::class;
protected $policy = InventoryPolicy::class;
protected $resource = InventoryResource::class;

public function includes(): array
{
Expand Down
27 changes: 24 additions & 3 deletions app/Http/Controllers/ProductController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@

namespace App\Http\Controllers;

use App\Events\ProductCreated;
use App\Models\Product;
use App\Events\ProductCreated;
use App\Policies\ProductPolicy;
use Orion\Http\Requests\Request;
use Orion\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Http\Resources\ProductResource;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

class ProductController extends Controller
{
protected $model = Product::class;
protected $policy = \App\Policies\ProductPolicy::class;
protected $policy = ProductPolicy::class;
protected $resource = ProductResource::class;

public function includes(): array
{
Expand All @@ -32,8 +37,24 @@ public function searchableBy(): array
return ['id', 'name', 'description', 'color', 'image_url', 'price'];
}

protected function buildIndexFetchQuery(Request $request, array $requestedRelations): Builder
{
$query = parent::buildIndexFetchQuery($request, $requestedRelations);
return $query->withTrashed();
}

protected function afterStore(Request $request, $model)
{
ProductCreated::dispatch($model);
}

protected function afterDestroy(Request $request, $entity)
{
$entity->inventory()->delete();
}

protected function afterRestore(Request $request, Model $entity)
{
$entity->inventory()->restore();
}
}
2 changes: 2 additions & 0 deletions app/Http/Controllers/PurchaseController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Http\Controllers;

use App\Events\ProductsPurchased;
use App\Http\Resources\PurchaseResource;
use App\Models\Purchase;
use Illuminate\Http\Request;
use App\Policies\PurchasePolicy;
Expand All @@ -14,6 +15,7 @@ class PurchaseController extends Controller
{
protected $model = Purchase::class;
protected $policy = PurchasePolicy::class;
protected $resource = PurchaseResource::class;

public function includes(): array
{
Expand Down
11 changes: 7 additions & 4 deletions app/Http/Controllers/SaleController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,21 @@

namespace App\Http\Controllers;

use App\Events\ProductsSold;
use App\Models\Sale;
use App\Models\Product;
use Illuminate\Database\Eloquent\Model;
use App\Events\ProductsSold;
use App\Policies\SalePolicy;
use Orion\Http\Requests\Request;
use App\Http\Resources\SaleResource;
use Illuminate\Support\Facades\Auth;
use Orion\Http\Controllers\Controller;
use Orion\Http\Requests\Request;
use Illuminate\Database\Eloquent\Model;

class SaleController extends Controller
{
protected $model = Sale::class;
protected $policy = \App\Policies\SalePolicy::class;
protected $policy = SalePolicy::class;
protected $resource = SaleResource::class;

public function includes(): array
{
Expand Down
7 changes: 5 additions & 2 deletions app/Http/Controllers/UserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
namespace App\Http\Controllers;

use App\Models\User;
use Orion\Http\Controllers\Controller;
use App\Policies\UserPolicy;
use Illuminate\Http\Request;
use App\Http\Resources\UserResource;
use Orion\Http\Controllers\Controller;

class UserController extends Controller
{
protected $model = User::class;
protected $policy = \App\Policies\UserPolicy::class;
protected $policy = UserPolicy::class;
protected $resource = UserResource::class;

public function includes(): array
{
Expand Down
29 changes: 29 additions & 0 deletions app/Http/Resources/InventoryResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class InventoryResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->product?->name ?: "",
'color' => $this->product?->color ?: "",
'image_url' => $this->product?->image_url ?: "",
'price' => $this->product?->price ?: "",
'quantity' => $this->quantity,
'last_updated' => $this->last_stocked_at,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
30 changes: 30 additions & 0 deletions app/Http/Resources/ProductResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class ProductResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'description' => $this->description,
'color' => $this->color,
'image_url' => $this->image_url,
'price' => $this->price,
'meta' => $this->meta,
'status' => $this->deleted_at ? 'archived' : 'active',
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
35 changes: 35 additions & 0 deletions app/Http/Resources/PurchaseResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class PurchaseResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'product_id' => $this->product_id,
'user_id' => $this->user_id,
'supplier' => $this->supplier,
'manufacturer' => $this->manufacturer,
'cost_per_unit' => $this->cost_per_unit,
'amount' => $this->amount,
'product' => [
'id' => $this->product_id,
'name' => $this->product?->name,
],
'quantity' => $this->quantity,
'meta' => $this->meta,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
19 changes: 19 additions & 0 deletions app/Http/Resources/SaleResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class SaleResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return parent::toArray($request);
}
}
Loading