Skip to content

Commit d465597

Browse files
committed
Refactor updateSeller method in CurrentSellerController to enhance seller and shop updates
This commit restructures the updateSeller method to improve data validation, file handling, and transaction management. It introduces clearer validation rules for seller and shop data, ensures proper handling of identity files, and updates the shop's profile and categories. The method now returns a more informative response upon successful updates, enhancing the overall functionality and user experience.
1 parent 237a7d5 commit d465597

File tree

3 files changed

+137
-113
lines changed

3 files changed

+137
-113
lines changed

app/Http/Controllers/Seller/CurrentSellerController.php

Lines changed: 119 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -25,125 +25,136 @@ public function currentSeller(){
2525
}
2626

2727
public function updateSeller(Request $request){
28-
$user=Auth::guard('api')->user();
29-
$seller = User::query()->with(['shops', 'shops.images', 'shops.categories'])->findOrFail($user->id);
30-
$shop = $seller->shops->first();
31-
32-
33-
$notEmpty = fn($v) => !is_null($v) && (!is_string($v) || trim($v) !== ''); // garde 0/'0'
34-
$onlyProvided = function(\Illuminate\Http\Request $r, array $keys) use ($notEmpty) {
35-
return array_filter($r->only($keys), $notEmpty);
36-
};
37-
38-
39-
28+
29+
// 1. Démarrer la transaction
30+
DB::beginTransaction();
4031

4132
try {
42-
// 1) Mise à jour vendeur
43-
$seller->fill([
44-
'firstName' => $request->input('firstName', $seller->firstName),
45-
'lastName' => $request->input('lastName', $seller->lastName),
46-
'email' => $request->input('email', $seller->email),
47-
'phone_number' => $request->input('phone_number', $seller->phone_number),
48-
'birthDate' => $request->input('birthDate', $seller->birthDate),
49-
'nationality' => $request->input('nationality', $seller->nationality),
50-
]);
51-
52-
DB::transaction(function() use ($request, $seller, $onlyProvided, $notEmpty) {
53-
// USER: update partiel sans null
54-
$userData = $onlyProvided($request, [
55-
'firstName','lastName','email','phone_number','birthDate','nationality','isWholesaler'
56-
]);
57-
if (!empty($userData)) {
58-
// caster isWholesaler si présent
59-
if (array_key_exists('isWholesaler', $userData)) {
60-
$userData['isWholesaler'] = (string)$userData['isWholesaler'];
61-
}
62-
$seller->update($userData);
63-
}
64-
65-
// FICHIERS USER
66-
if ($request->hasFile('identity_card_in_front')) {
67-
$seller->identity_card_in_front = $request->file('identity_card_in_front')->store('cni/front','public');
68-
}
69-
if ($request->hasFile('identity_card_in_back')) {
70-
$seller->identity_card_in_back = $request->file('identity_card_in_back')->store('cni/back','public');
71-
}
72-
if ($request->hasFile('identity_card_with_the_person')) {
73-
$seller->identity_card_with_the_person = $request->file('identity_card_with_the_person')->store('cni/person','public');
74-
}
75-
$seller->save();
76-
77-
// SHOP
78-
$shop = $seller->shop ?: new Shop(['user_id' => $seller->id]);
79-
80-
$shopData = $onlyProvided($request, [
81-
'shop_name','shop_description','product_type','town_id','quarter_id'
82-
]);
83-
84-
if (array_key_exists('product_type', $shopData)) {
85-
$shopData['product_type'] = (string)$shopData['product_type'];
86-
}
87-
88-
89-
if (!empty($shopData)) {
90-
$shop->fill($shopData); // fillable requis dans Shop
91-
}
92-
93-
// FICHIER SHOP PROFILE
94-
if ($request->hasFile('shop_profile')) {
95-
$shop->shop_profile = $request->file('shop_profile')->store('shop/profile','public');
96-
}
97-
98-
// Localisation par nom (optionnel, uniquement si fourni et non vide)
99-
if ($request->filled('town')) {
100-
$town = \App\Models\Town::where('town_name', $request->input('town'))->first();
101-
if ($town) $shop->town_id = $town->id;
33+
34+
$user =Auth::guard('api')->user();
35+
$shop = $user->shop;
36+
37+
// --- 2. Validation des Données ---
38+
$rules = [
39+
// Règles Vendeur (User)
40+
'firstName' => ['nullable', 'string', 'max:255'],
41+
'lastName' => ['nullable', 'string', 'max:255'],
42+
'email' => ['nullable', 'email', 'max:255', Rule::unique('users')->ignore($user->id)],
43+
'phone_number' => ['nullable', 'string', 'max:20'],
44+
'birthDate' => ['nullable', 'date'],
45+
'nationality' => ['nullable', 'string', 'max:100'],
46+
'isWholesaler' => ['nullable', 'in:0,1,2'],
47+
48+
// Règles Boutique (Shop)
49+
'shop_name' => ['nullable', 'string', 'max:255'],
50+
'shop_description' => ['nullable', 'string', 'max:1000'],
51+
'product_type' => ['nullable', 'in:0,1,2'],
52+
'shop_gender' => ['nullable', 'in:1,2'],
53+
'town' => ['nullable', 'string', 'max:100'],
54+
'quarter' => ['nullable', 'string', 'max:100'],
55+
// NOTE: Si le frontend envoie les IDs, utilisez 'town_id' et 'quarter_id'
56+
57+
// Règles Fichiers (si un nouveau fichier est envoyé)
58+
'identity_card_in_front' => ['nullable', 'file', 'mimes:jpeg,png,jpg', 'max:5120'],
59+
'identity_card_in_back' => ['nullable', 'file', 'mimes:jpeg,png,jpg', 'max:5120'],
60+
'identity_card_with_the_person' => ['nullable', 'file', 'mimes:jpeg,png,jpg', 'max:5120'],
61+
'shop_profile' => ['nullable', 'file', 'mimes:jpeg,png,jpg', 'max:5120'],
62+
'images' => ['nullable', 'array', 'max:10'], // Galerie
63+
'images.*' => ['file', 'mimes:jpeg,png,jpg', 'max:5120'],
64+
65+
// Catégories (IDs)
66+
'categories' => ['nullable', 'array'],
67+
'categories.*' => ['integer', 'exists:categories,id'],
68+
];
69+
70+
$data = $request->validate($rules);
71+
72+
// --- 3. Mise à jour du Vendeur (User) et des Fichiers d'Identité ---
73+
$userData = $request->only(['firstName', 'lastName', 'email', 'phone_number', 'birthDate', 'nationality']);
74+
if (isset($data['isWholesaler'])) {
75+
$userData['is_wholesaler'] = $data['isWholesaler'];
76+
}
77+
$user->update(array_filter($userData)); // array_filter retire les champs vides/nuls
78+
79+
// Traitement des fichiers CNI/Identité
80+
$identityFiles = [
81+
'identity_card_in_front' => 'identity_card_in_front',
82+
'identity_card_in_back' => 'identity_card_in_back',
83+
'identity_card_with_the_person' => 'identity_card_with_the_person',
84+
];
85+
foreach ($identityFiles as $requestKey => $modelAttribute) {
86+
if ($request->hasFile($requestKey)) {
87+
// **SUPPRESSION DE L'ANCIEN FICHIER**
88+
if ($user->$modelAttribute && Storage::disk('public')->exists($user->$modelAttribute)) {
89+
Storage::disk('public')->delete($user->$modelAttribute);
90+
}
91+
// Stocker le nouveau fichier
92+
$path = $request->file($requestKey)->store('seller/identity', 'public');
93+
$user->$modelAttribute = $path;
94+
$user->save();
10295
}
103-
if ($request->filled('quarter')) {
104-
$quarter = \App\Models\Quarter::where('quarter_name', $request->input('quarter'))->first();
105-
if ($quarter) $shop->quarter_id = $quarter->id;
96+
}
97+
98+
// --- 4. Mise à jour de la Boutique (Shop) et du Profil ---
99+
$shopData = $request->only(['shop_name', 'shop_description', 'town', 'quarter']);
100+
101+
if (isset($data['product_type'])) {
102+
$shopData['product_type'] = $data['product_type'];
103+
}
104+
if (isset($data['shop_gender'])) {
105+
$shopData['gender'] = $data['shop_gender'];
106+
}
107+
108+
$shop->update(array_filter($shopData));
109+
110+
// Traitement de la photo de profil de la boutique
111+
if ($request->hasFile('shop_profile')) {
112+
// **SUPPRESSION DE L'ANCIEN FICHIER**
113+
if ($shop->shop_profile && Storage::disk('public')->exists($shop->shop_profile)) {
114+
Storage::disk('public')->delete($shop->shop_profile);
106115
}
107-
116+
// Stocker la nouvelle photo de profil
117+
$shop->shop_profile = $request->file('shop_profile')->store('shop/profile', 'public');
108118
$shop->save();
109-
110-
// Catégories: sync seulement si fourni
111-
if ($request->has('categories') && is_array($request->input('categories'))) {
112-
$ids = collect($request->input('categories'))
113-
->map(fn($it) => is_array($it) ? ($it['id'] ?? $it['value'] ?? null) : $it)
114-
->filter()->unique()->values()->all();
115-
$shop->categories()->sync($ids);
116-
}
117-
118-
// Images: remplacer seulement si fichiers fournis
119-
if ($request->hasFile('images')) {
120-
$files = $request->file('images');
121-
if (is_array($files) && count($files) > 0) {
122-
$shop->images()->detach();
123-
$attach = [];
124-
foreach ($files as $f) {
125-
$img = new \App\Models\Image();
126-
$img->image_path = $f->store('shop/images','public');
127-
$img->save();
128-
$attach[] = $img->id;
129-
}
130-
if ($attach) $shop->images()->attach($attach);
131-
}
119+
}
120+
121+
// --- 5. Synchronisation des Catégories ---
122+
if (isset($data['categories'])) {
123+
// Utilisation de sync() pour s'assurer qu'il n'y ait que les nouvelles catégories
124+
$shop->categories()->sync($data['categories']);
125+
}
126+
127+
// --- 6. Traitement de la Galerie d'images ---
128+
// Le frontend doit gérer la suppression des anciennes images. Ici, on ajoute seulement les nouvelles.
129+
if ($request->hasFile('images')) {
130+
foreach ($request->file('images') as $file) {
131+
$imagePath = $file->store('shop/gallery', 'public');
132+
133+
// Créer un enregistrement dans la table de galerie
134+
$shop->images()->create([
135+
'image_path' => $imagePath // Assurez-vous que c'est le bon nom de colonne
136+
]);
132137
}
133-
});
138+
}
139+
140+
141+
// 7. Valider la transaction
142+
DB::commit();
143+
144+
// Recharger l'utilisateur avec la relation de boutique mise à jour pour la réponse
145+
$user->load('shop.categories', 'shop.images');
134146

135147
return response()->json([
136-
'success' => true,
137-
'message' => 'Shop updated successfully',
138-
], 200);
148+
'message' => 'Boutique et informations du vendeur mises à jour avec succès.',
149+
'seller_data' => $user->toArray(),
150+
]);
139151

140-
} catch (\Throwable $e) {
152+
} catch (\Exception $e) {
141153
DB::rollBack();
142-
Log::error('Shop update error', ['error' => $e->getMessage(), 'trace' => $e->getTraceAsString()]);
154+
Log::error("Erreur de mise à jour de boutique pour l'utilisateur {$user->id}: " . $e->getMessage());
155+
143156
return response()->json([
144-
'success' => false,
145-
'message' => 'Something went wrong',
146-
'errors' => $e->getMessage(),
157+
'message' => 'Une erreur interne est survenue lors de la mise à jour.'.$e->getMessage(),
147158
], 500);
148159
}
149160
}

app/Models/Shop.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,14 @@ class Shop extends Model
2424

2525
protected $fillable = [
2626
'shop_name',
27-
'shop_key',
2827
'shop_description',
29-
'user_id',
30-
'shop_type_id',
28+
'product_type',
29+
'shop_gender', // Assurez-vous que le nom du champ est bien 'gender' et non 'shop_gender' // Si vous stockez le nom du quartier
30+
'town_id', // Si vous utilisez les IDs
31+
'quarter_id', // Si vous utilisez les IDs
32+
'shop_profile', // Pour l'URL/chemin de l'image de profil
33+
'user_id', // Important si c'est défini lors de la création
34+
// Ajoutez ici toutes les colonnes qui pourraient être mises à jour
3135
];
3236

3337
protected $keyType = 'string';

app/Models/User.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ class User extends Authenticatable
2929
*/
3030
protected $fillable = [
3131
'userName',
32+
"firstName",
33+
"lastName",
34+
"birthDate",
35+
"nationality",
36+
"isWholesaler",
37+
"identity_card_in_front",
38+
'identity_card_in_back',
39+
"identity_card_with_the_person",
40+
3241
'role_id',
3342
'town_id',
3443
'phone_number',
@@ -67,8 +76,8 @@ public function findForPassport($username) {
6776
return $this->where('phone_number','=', $username)->first();
6877
}
6978

70-
public function shops():HasMany{
71-
return $this->hasMany(Shop::class);
79+
public function shop():HasOne{
80+
return $this->hasOne(Shop::class);
7281
}
7382

7483
public function vehicles():HasMany{

0 commit comments

Comments
 (0)