Feat: API sous-traitant
This commit is contained in:
parent
9a52bddd1a
commit
7506bdcf8b
@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\StoreSousTraitantRequest;
|
||||
use App\Http\Requests\UpdateSousTraitantRequest;
|
||||
use App\Http\Resources\SousTraitant\SousTraitantCollection;
|
||||
use App\Http\Resources\SousTraitant\SousTraitantResource;
|
||||
use App\Repositories\SousTraitantRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class SousTraitantController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly SousTraitantRepositoryInterface $sousTraitantRepository
|
||||
) {
|
||||
}
|
||||
|
||||
public function index(Request $request): SousTraitantCollection|JsonResponse
|
||||
{
|
||||
try {
|
||||
$perPage = $request->get('per_page', 15);
|
||||
$filters = [
|
||||
'search' => $request->get('search'),
|
||||
'statut' => $request->get('statut'),
|
||||
'sort_by' => $request->get('sort_by', 'created_at'),
|
||||
'sort_direction' => $request->get('sort_direction', 'desc'),
|
||||
];
|
||||
|
||||
$filters = array_filter($filters, function ($value) {
|
||||
return $value !== null && $value !== '';
|
||||
});
|
||||
|
||||
$sousTraitants = $this->sousTraitantRepository->paginate($perPage, $filters);
|
||||
|
||||
return new SousTraitantCollection($sousTraitants);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error fetching sous-traitants: ' . $e->getMessage(), [
|
||||
'exception' => $e,
|
||||
'trace' => $e->getTraceAsString(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Une erreur est survenue lors de la récupération des sous-traitants.',
|
||||
'error' => config('app.debug') ? $e->getMessage() : null,
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function store(StoreSousTraitantRequest $request): SousTraitantResource|JsonResponse
|
||||
{
|
||||
try {
|
||||
$sousTraitant = $this->sousTraitantRepository->create($request->validated());
|
||||
|
||||
return new SousTraitantResource($sousTraitant);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error creating sous-traitant: ' . $e->getMessage(), [
|
||||
'exception' => $e,
|
||||
'trace' => $e->getTraceAsString(),
|
||||
'data' => $request->validated(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Une erreur est survenue lors de la création du sous-traitant.',
|
||||
'error' => config('app.debug') ? $e->getMessage() : null,
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function show(string $id): SousTraitantResource|JsonResponse
|
||||
{
|
||||
try {
|
||||
$sousTraitant = $this->sousTraitantRepository->find($id);
|
||||
|
||||
if (!$sousTraitant) {
|
||||
return response()->json([
|
||||
'message' => 'Sous-traitant non trouvé.',
|
||||
], 404);
|
||||
}
|
||||
|
||||
return new SousTraitantResource($sousTraitant);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error fetching sous-traitant: ' . $e->getMessage(), [
|
||||
'exception' => $e,
|
||||
'trace' => $e->getTraceAsString(),
|
||||
'sous_traitant_id' => $id,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Une erreur est survenue lors de la récupération du sous-traitant.',
|
||||
'error' => config('app.debug') ? $e->getMessage() : null,
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function searchBy(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$name = $request->get('name', '');
|
||||
|
||||
if (empty($name)) {
|
||||
return response()->json([
|
||||
'message' => 'Le paramètre "name" est requis.',
|
||||
], 400);
|
||||
}
|
||||
|
||||
$sousTraitants = $this->sousTraitantRepository->searchByName($name);
|
||||
|
||||
return response()->json([
|
||||
'data' => $sousTraitants,
|
||||
'count' => $sousTraitants->count(),
|
||||
'message' => $sousTraitants->count() > 0
|
||||
? 'Sous-traitants trouvés avec succès.'
|
||||
: 'Aucun sous-traitant trouvé.',
|
||||
], 200);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error searching sous-traitants by name: ' . $e->getMessage(), [
|
||||
'exception' => $e,
|
||||
'trace' => $e->getTraceAsString(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Une erreur est survenue lors de la recherche des sous-traitants.',
|
||||
'error' => config('app.debug') ? $e->getMessage() : null,
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function update(UpdateSousTraitantRequest $request, string $id): SousTraitantResource|JsonResponse
|
||||
{
|
||||
try {
|
||||
$updated = $this->sousTraitantRepository->update($id, $request->validated());
|
||||
|
||||
if (!$updated) {
|
||||
return response()->json([
|
||||
'message' => 'Sous-traitant non trouvé ou échec de la mise à jour.',
|
||||
], 404);
|
||||
}
|
||||
|
||||
$sousTraitant = $this->sousTraitantRepository->find($id);
|
||||
|
||||
return new SousTraitantResource($sousTraitant);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error updating sous-traitant: ' . $e->getMessage(), [
|
||||
'exception' => $e,
|
||||
'trace' => $e->getTraceAsString(),
|
||||
'sous_traitant_id' => $id,
|
||||
'data' => $request->validated(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Une erreur est survenue lors de la mise à jour du sous-traitant.',
|
||||
'error' => config('app.debug') ? $e->getMessage() : null,
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy(string $id): JsonResponse
|
||||
{
|
||||
try {
|
||||
$deleted = $this->sousTraitantRepository->delete($id);
|
||||
|
||||
if (!$deleted) {
|
||||
return response()->json([
|
||||
'message' => 'Sous-traitant non trouvé ou échec de la suppression.',
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Sous-traitant supprimé avec succès.',
|
||||
], 200);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error deleting sous-traitant: ' . $e->getMessage(), [
|
||||
'exception' => $e,
|
||||
'trace' => $e->getTraceAsString(),
|
||||
'sous_traitant_id' => $id,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Une erreur est survenue lors de la suppression du sous-traitant.',
|
||||
'error' => config('app.debug') ? $e->getMessage() : null,
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class StoreSousTraitantRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'nom_entreprise' => 'required|string|max:255',
|
||||
'siret' => 'nullable|string|max:20',
|
||||
'forme_juridique' => 'nullable|string|max:100',
|
||||
'code_ape' => 'nullable|string|max:20',
|
||||
'adresse' => 'nullable|string',
|
||||
'contact_principal' => 'required|string|max:255',
|
||||
'telephone' => 'nullable|string|max:50',
|
||||
'email' => 'nullable|email|max:191',
|
||||
'site_web' => 'nullable|url|max:191',
|
||||
'numero_contrat' => 'nullable|string|max:100',
|
||||
'montant_contrat' => 'nullable|numeric|min:0',
|
||||
'date_debut_contrat' => 'nullable|date',
|
||||
'date_fin_contrat' => 'nullable|date|after_or_equal:date_debut_contrat',
|
||||
'type_prestation' => 'nullable|string|max:255',
|
||||
'conditions_paiement' => 'nullable|string',
|
||||
'statut' => ['nullable', Rule::in(['actif', 'inactif', 'en_evaluation'])],
|
||||
'note_qualite' => 'nullable|numeric|min:0|max:5',
|
||||
'certifications_labels' => 'nullable|array',
|
||||
'certifications_labels.*' => 'string|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'nom_entreprise.required' => 'Le nom de l\'entreprise est obligatoire.',
|
||||
'contact_principal.required' => 'Le contact principal est obligatoire.',
|
||||
'email.email' => 'L\'adresse email doit être valide.',
|
||||
'site_web.url' => 'Le site web doit être une URL valide.',
|
||||
'montant_contrat.numeric' => 'Le montant du contrat doit être numérique.',
|
||||
'montant_contrat.min' => 'Le montant du contrat doit être supérieur ou égal à 0.',
|
||||
'date_fin_contrat.after_or_equal' => 'La date de fin doit être postérieure ou égale à la date de début.',
|
||||
'statut.in' => 'Le statut sélectionné est invalide.',
|
||||
'note_qualite.numeric' => 'La note de qualité doit être numérique.',
|
||||
'note_qualite.min' => 'La note de qualité doit être au minimum de 0.',
|
||||
'note_qualite.max' => 'La note de qualité doit être au maximum de 5.',
|
||||
'certifications_labels.array' => 'Les certifications doivent être envoyées sous forme de liste.',
|
||||
'certifications_labels.*.string' => 'Chaque certification doit être une chaîne de caractères.',
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UpdateSousTraitantRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'nom_entreprise' => 'sometimes|required|string|max:255',
|
||||
'siret' => 'nullable|string|max:20',
|
||||
'forme_juridique' => 'nullable|string|max:100',
|
||||
'code_ape' => 'nullable|string|max:20',
|
||||
'adresse' => 'nullable|string',
|
||||
'contact_principal' => 'sometimes|required|string|max:255',
|
||||
'telephone' => 'nullable|string|max:50',
|
||||
'email' => 'nullable|email|max:191',
|
||||
'site_web' => 'nullable|url|max:191',
|
||||
'numero_contrat' => 'nullable|string|max:100',
|
||||
'montant_contrat' => 'nullable|numeric|min:0',
|
||||
'date_debut_contrat' => 'nullable|date',
|
||||
'date_fin_contrat' => 'nullable|date|after_or_equal:date_debut_contrat',
|
||||
'type_prestation' => 'nullable|string|max:255',
|
||||
'conditions_paiement' => 'nullable|string',
|
||||
'statut' => ['nullable', Rule::in(['actif', 'inactif', 'en_evaluation'])],
|
||||
'note_qualite' => 'nullable|numeric|min:0|max:5',
|
||||
'certifications_labels' => 'nullable|array',
|
||||
'certifications_labels.*' => 'string|max:255',
|
||||
];
|
||||
}
|
||||
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'nom_entreprise.required' => 'Le nom de l\'entreprise est obligatoire.',
|
||||
'contact_principal.required' => 'Le contact principal est obligatoire.',
|
||||
'email.email' => 'L\'adresse email doit être valide.',
|
||||
'site_web.url' => 'Le site web doit être une URL valide.',
|
||||
'montant_contrat.numeric' => 'Le montant du contrat doit être numérique.',
|
||||
'montant_contrat.min' => 'Le montant du contrat doit être supérieur ou égal à 0.',
|
||||
'date_fin_contrat.after_or_equal' => 'La date de fin doit être postérieure ou égale à la date de début.',
|
||||
'statut.in' => 'Le statut sélectionné est invalide.',
|
||||
'note_qualite.numeric' => 'La note de qualité doit être numérique.',
|
||||
'note_qualite.min' => 'La note de qualité doit être au minimum de 0.',
|
||||
'note_qualite.max' => 'La note de qualité doit être au maximum de 5.',
|
||||
'certifications_labels.array' => 'Les certifications doivent être envoyées sous forme de liste.',
|
||||
'certifications_labels.*.string' => 'Chaque certification doit être une chaîne de caractères.',
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources\SousTraitant;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
|
||||
class SousTraitantCollection extends ResourceCollection
|
||||
{
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'data' => $this->collection,
|
||||
'meta' => [
|
||||
'total' => $this->total(),
|
||||
'per_page' => $this->perPage(),
|
||||
'current_page' => $this->currentPage(),
|
||||
'last_page' => $this->lastPage(),
|
||||
'from' => $this->firstItem(),
|
||||
'to' => $this->lastItem(),
|
||||
'stats' => [
|
||||
'actif' => $this->collection->where('statut', 'actif')->count(),
|
||||
'inactif' => $this->collection->where('statut', 'inactif')->count(),
|
||||
'en_evaluation' => $this->collection->where('statut', 'en_evaluation')->count(),
|
||||
],
|
||||
],
|
||||
'links' => [
|
||||
'first' => $this->url(1),
|
||||
'last' => $this->url($this->lastPage()),
|
||||
'prev' => $this->previousPageUrl(),
|
||||
'next' => $this->nextPageUrl(),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function with(Request $request): array
|
||||
{
|
||||
return [
|
||||
'status' => 'success',
|
||||
'message' => 'Sous-traitants récupérés avec succès',
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources\SousTraitant;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class SousTraitantResource extends JsonResource
|
||||
{
|
||||
public function toArray(Request $request): array
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'nom_entreprise' => $this->nom_entreprise,
|
||||
'siret' => $this->siret,
|
||||
'forme_juridique' => $this->forme_juridique,
|
||||
'code_ape' => $this->code_ape,
|
||||
'adresse' => $this->adresse,
|
||||
'contact_principal' => $this->contact_principal,
|
||||
'telephone' => $this->telephone,
|
||||
'email' => $this->email,
|
||||
'site_web' => $this->site_web,
|
||||
'numero_contrat' => $this->numero_contrat,
|
||||
'montant_contrat' => $this->montant_contrat,
|
||||
'date_debut_contrat' => $this->date_debut_contrat?->format('Y-m-d'),
|
||||
'date_fin_contrat' => $this->date_fin_contrat?->format('Y-m-d'),
|
||||
'type_prestation' => $this->type_prestation,
|
||||
'conditions_paiement' => $this->conditions_paiement,
|
||||
'statut' => $this->statut,
|
||||
'note_qualite' => $this->note_qualite,
|
||||
'certifications_labels' => $this->certifications_labels ?? [],
|
||||
'created_at' => $this->created_at?->format('Y-m-d H:i:s'),
|
||||
'updated_at' => $this->updated_at?->format('Y-m-d H:i:s'),
|
||||
];
|
||||
}
|
||||
}
|
||||
42
thanasoft-back/app/Models/SousTraitant.php
Normal file
42
thanasoft-back/app/Models/SousTraitant.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class SousTraitant extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'sous_traitants';
|
||||
|
||||
protected $fillable = [
|
||||
'nom_entreprise',
|
||||
'siret',
|
||||
'forme_juridique',
|
||||
'code_ape',
|
||||
'adresse',
|
||||
'contact_principal',
|
||||
'telephone',
|
||||
'email',
|
||||
'site_web',
|
||||
'numero_contrat',
|
||||
'montant_contrat',
|
||||
'date_debut_contrat',
|
||||
'date_fin_contrat',
|
||||
'type_prestation',
|
||||
'conditions_paiement',
|
||||
'statut',
|
||||
'note_qualite',
|
||||
'certifications_labels',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'montant_contrat' => 'decimal:2',
|
||||
'date_debut_contrat' => 'date',
|
||||
'date_fin_contrat' => 'date',
|
||||
'note_qualite' => 'decimal:1',
|
||||
'certifications_labels' => 'array',
|
||||
];
|
||||
}
|
||||
@ -48,6 +48,10 @@ class AppServiceProvider extends ServiceProvider
|
||||
return new \App\Repositories\FournisseurRepository($app->make(\App\Models\Fournisseur::class));
|
||||
});
|
||||
|
||||
$this->app->bind(\App\Repositories\SousTraitantRepositoryInterface::class, function ($app) {
|
||||
return new \App\Repositories\SousTraitantRepository($app->make(\App\Models\SousTraitant::class));
|
||||
});
|
||||
|
||||
$this->app->bind(\App\Repositories\ProductRepositoryInterface::class, function ($app) {
|
||||
return new \App\Repositories\ProductRepository($app->make(\App\Models\Product::class));
|
||||
});
|
||||
|
||||
53
thanasoft-back/app/Repositories/SousTraitantRepository.php
Normal file
53
thanasoft-back/app/Repositories/SousTraitantRepository.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repositories;
|
||||
|
||||
use App\Models\SousTraitant;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
|
||||
class SousTraitantRepository extends BaseRepository implements SousTraitantRepositoryInterface
|
||||
{
|
||||
public function __construct(SousTraitant $model)
|
||||
{
|
||||
parent::__construct($model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get paginated sous-traitants.
|
||||
*/
|
||||
public function paginate(int $perPage = 15, array $filters = []): LengthAwarePaginator
|
||||
{
|
||||
$query = $this->model->newQuery();
|
||||
|
||||
if (!empty($filters['search'])) {
|
||||
$query->where(function ($q) use ($filters) {
|
||||
$q->where('nom_entreprise', 'like', '%' . $filters['search'] . '%')
|
||||
->orWhere('contact_principal', 'like', '%' . $filters['search'] . '%')
|
||||
->orWhere('email', 'like', '%' . $filters['search'] . '%')
|
||||
->orWhere('siret', 'like', '%' . $filters['search'] . '%')
|
||||
->orWhere('numero_contrat', 'like', '%' . $filters['search'] . '%')
|
||||
->orWhere('type_prestation', 'like', '%' . $filters['search'] . '%');
|
||||
});
|
||||
}
|
||||
|
||||
if (!empty($filters['statut'])) {
|
||||
$query->where('statut', $filters['statut']);
|
||||
}
|
||||
|
||||
$sortField = $filters['sort_by'] ?? 'created_at';
|
||||
$sortDirection = $filters['sort_direction'] ?? 'desc';
|
||||
$query->orderBy($sortField, $sortDirection);
|
||||
|
||||
return $query->paginate($perPage);
|
||||
}
|
||||
|
||||
public function searchByName(string $name)
|
||||
{
|
||||
return $this->model
|
||||
->newQuery()
|
||||
->where('nom_entreprise', 'like', '%' . $name . '%')
|
||||
->get();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repositories;
|
||||
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
|
||||
interface SousTraitantRepositoryInterface extends BaseRepositoryInterface
|
||||
{
|
||||
public function paginate(int $perPage = 15, array $filters = []): LengthAwarePaginator;
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('sous_traitants', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('nom_entreprise');
|
||||
$table->string('siret', 20)->nullable();
|
||||
$table->string('forme_juridique', 100)->nullable();
|
||||
$table->string('code_ape', 20)->nullable();
|
||||
$table->text('adresse')->nullable();
|
||||
$table->string('contact_principal');
|
||||
$table->string('telephone', 50)->nullable();
|
||||
$table->string('email', 191)->nullable();
|
||||
$table->string('site_web', 191)->nullable();
|
||||
$table->string('numero_contrat', 100)->nullable();
|
||||
$table->decimal('montant_contrat', 12, 2)->nullable();
|
||||
$table->date('date_debut_contrat')->nullable();
|
||||
$table->date('date_fin_contrat')->nullable();
|
||||
$table->string('type_prestation')->nullable();
|
||||
$table->text('conditions_paiement')->nullable();
|
||||
$table->enum('statut', ['actif', 'inactif', 'en_evaluation'])->default('actif');
|
||||
$table->decimal('note_qualite', 3, 1)->nullable();
|
||||
$table->json('certifications_labels')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('sous_traitants');
|
||||
}
|
||||
};
|
||||
@ -8,6 +8,7 @@ use App\Http\Controllers\Api\ClientLocationController;
|
||||
use App\Http\Controllers\Api\ContactController;
|
||||
use App\Http\Controllers\Api\ClientCategoryController;
|
||||
use App\Http\Controllers\Api\FournisseurController;
|
||||
use App\Http\Controllers\Api\SousTraitantController;
|
||||
use App\Http\Controllers\Api\ProductController;
|
||||
use App\Http\Controllers\Api\ProductCategoryController;
|
||||
use App\Http\Controllers\Api\EmployeeController;
|
||||
@ -131,6 +132,8 @@ Route::middleware('auth:sanctum')->group(function () {
|
||||
Route::apiResource('purchase-orders', PurchaseOrderController::class);
|
||||
Route::apiResource('fournisseurs', FournisseurController::class);
|
||||
Route::get('fournisseurs/{fournisseurId}/contacts', [ContactController::class, 'getContactsByFournisseur']);
|
||||
Route::get('/sous-traitants/searchBy', [SousTraitantController::class, 'searchBy']);
|
||||
Route::apiResource('sous-traitants', SousTraitantController::class);
|
||||
|
||||
// Product management
|
||||
Route::get('/products/searchBy', [ProductController::class, 'searchBy']);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user