You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

504 lines
20 KiB

<?php
namespace App\Controllers;
use App\Models\Attributes;
use App\Models\Brands;
use App\Models\Category;
use App\Models\FourchettePrix;
use App\Models\Notification;
use App\Models\Products;
use App\Models\Stores;
use Config\Services;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
class ProductCOntroller extends AdminController
{
public function __construct()
{
parent::__construct();
// Assuming permission is being set from a session
helper(['form', 'url']);
}
private $pageTitle = 'Produits';
public function index()
{
$Stores = new Stores();
$this->verifyRole('viewProduct');
$data['page_title'] = $this->pageTitle;
$Product = new Products();
$data['motos'] = $Product->getActiveProductData();
$data['stores'] = $Stores->getActiveStore();
return $this->render_template('products/index', $data);
}
public function assign_store()
{
// Vérifie que la requête est bien une requête AJAX
if (!$this->request->isAJAX()) {
$response = Services::response();
$response->setStatusCode(404, 'Page Not Found')->send();
exit;
}
// Récupère les données POST sous format JSON
$data = $this->request->getJSON(true); // Décodage en tableau associatif
if (!isset($data['product_id']) || !isset($data['store_id'])) {
return $this->response->setJSON([
'success' => false,
'message' => 'Paramètres manquants.'
])->setStatusCode(400);
}
$product_id = $data['product_id'];
$store_id = $data['store_id'];
$productsModel = new Products();
// Appeler la méthode assignToStore pour mettre à jour la base de données
$result = $productsModel->assignToStore($product_id, $store_id);
// Répondre en JSON avec le résultat
if ($result) {
return $this->response->setJSON(['success' => true]);
} else {
return $this->response->setJSON(['success' => false, 'message' => 'Échec de la mise à jour.']);
}
}
public function fetchProductData()
{
$result = ['data' => []];
$Products = new Products();
$Stores = new Stores();
function convertString($name)
{
return "$name";
}
$data = $Products->getProductData();
foreach ($data as $key => $value) {
// Gestion du nom du magasin
if ($value['store_id'] == 0) {
$store_name = "TOUS";
} else {
$store_info = $Stores->getStoresData($value['store_id']);
$store_name = $store_info && isset($store_info['name']) ? $store_info['name'] : "Inconnu";
}
// Disponibilité
$availability = ($value['qty'] > 0) ? '<span class="label label-success">En stock</span>' : '<span class="label label-danger">Rupture</span>';
// Construction des boutons
$buttons = '';
if (in_array('updateProduct', $this->permission ?? [])) {
$buttons .= '<a href="' . base_url('products/update/' . $value['id']) . '" class="btn btn-default"><i class="fa fa-pencil"></i></a>';
}
if (in_array('deleteProduct', $this->permission ?? [])) {
$buttons .= ' <button type="button" class="btn btn-danger" onclick="removeFunc(' . $value['id'] . ')" data-toggle="modal" data-target="#removeModal"><i class="fa fa-trash"></i></button>';
}
if (in_array('updateProduct', $this->permission ?? [])) {
$buttons .= ' <a href="ventes/' . $value['id'] . '" class="btn btn-default"><i class="fa fa-image"></i></a>';
}
if (in_array('updateProduct', $this->permission ?? [])) {
$buttons .= ' <button class="btn btn-default" onclick="generateQrPdf(' . $value["id"] . ')"><i class="fa fa-qrcode"></i></button>';
}
if (in_array('viewProduct', $this->permission ?? [])) {
$buttons .= " <a href='/ventes/show/" . $value['id'] . "' class='btn btn-default'><i class='fa fa-eye'></i></a>";
}
if (in_array('assignStore', $this->permission ?? [])) {
$buttons .=
'<button type="button" class="btn btn-info assignbtn" title="Assigner sur un magasin" data-magasin="' . $store_name . '" data-products-id="' . $value["id"] . '" data-toggle="modal" data-target="#assignStoreModal">
<i class="fa fa-forward"></i>
</button>';
}
$imagePath = 'assets/images/product_image/' . $value['image'];
$imageHtml = $value['image'] ?
'<img src="' . base_url($imagePath) . '" width="50" height="50" class="img-thumbnail">' :
'<div class="no-image">Aucune image</div>';
// Préparer les données pour DataTables (7 colonnes)
$result['data'][$key] = [
$value['image'],
convertString($value['sku']),
$value['name'],
$value['prix_vente'],
$store_name,
$availability, // <-- ici la disponibilité ajoutée
$buttons
];
}
return $this->response->setJSON($result);
}
public function create()
{
$Products = new Products();
$Brands = new Brands();
$Category = new Category();
$Stores = new Stores();
$Notification = new NotificationController();
$this->verifyRole('createProduct');
$data['page_title'] = $this->pageTitle;
// die(var_dump(json_encode($this->request->getPost('categorie[]'))));
// Validate form inputs
$validation = \Config\Services::validation();
$validation->setRules([
'nom_de_produit' => 'required',
'marque' => 'required',
'type' => 'required',
'numero_de_moteur' => 'required',
'prix' => 'required|numeric',
'price_vente' => 'required|numeric',
'puissance' => 'required',
'store' => 'required',
'availability' => 'required',
'price_min' => 'required|numeric',
]);
if ($this->request->getMethod() === 'post' && $validation->withRequest($this->request)->run()) {
// die(var_dump($this->request->getPost()));
// Handle image upload
$upload_image = $this->uploadImage();
// Prepare data for insertion
$product_sold = false;
$data = [
'name' => $this->request->getPost('nom_de_produit'),
'sku' => $this->request->getPost('numero_de_serie'),
'price' => $this->request->getPost('prix'),
'qty' => 1,
'image' => $upload_image,
'description' => $this->request->getPost('description'),
'numero_de_moteur' => $this->request->getPost('numero_de_moteur'),
'marque' => $this->request->getPost('marque'),
'chasis' => $this->request->getPost('chasis'),
'store_id' => $this->request->getPost('store'),
'availability' => $this->request->getPost('availability'),
'prix_vente' => $this->request->getPost('price_vente'),
'date_arivage' => $this->request->getPost('datea'),
'puissance' => $this->request->getPost('puissance'),
'cler' => $this->request->getPost('cler'),
'categorie_id' => json_encode($this->request->getPost('categorie[]')),
'etats' => $this->request->getPost('etats'),
'infoManquekit' => $this->request->getPost('infoManquekit'),
'info' => $this->request->getPost('info'),
'infoManque' => $this->request->getPost('infoManque'),
'product_sold' => $product_sold,
'type'=> $this->request->getPost('type')
];
$store_id1 = (int)$this->request->getPost('store');
// Insert data into the database
if ($Products->create($data)) {
$data = [
'product_id' => $Products->insertID(),
'prix_minimal' => $this->request->getPost('price_min'),
];
$Fourchette = new FourchettePrix();
$Fourchette->createFourchettePrix($data);
session()->setFlashdata('success', 'Créé avec succès');
$Notification->createNotification("Un nouveau Produit a été crée", "COMMERCIALE",$store_id1,'product/');
return redirect()->to('/products');
} else {
session()->setFlashdata('errors', 'Error occurred while creating the product');
return redirect()->to('products/create');
}
} else {
$data = [
'stores' => $Stores->getActiveStore(),
'validation' => $validation, // Pass validation errors to the view
'page_title' => $this->pageTitle,
'marque' => $Brands->getActiveBrands(),
'categorie' => $Category->getActiveCategory(),
];
// Render the form view
return $this->render_template('products/create', $data);
}
}
private function uploadImage()
{
// Define the upload directory
$uploadPath = 'assets/images/product_image';
// Ensure the directory exists
if (!is_dir($uploadPath)) {
mkdir($uploadPath, 0777, true);
}
// Check if the file is uploaded via the form
$file = $this->request->getFile('product_image');
if ($file && $file->isValid() && !$file->hasMoved()) {
// Generate a unique file name
$newName = uniqid() . '.' . $file->getExtension();
// Move the file to the target directory
$file->move($uploadPath, $newName);
// Return the actual file name
return $newName;
}
// If an error occurs, return the error message
return $file ? $file->getErrorString() : 'No file was uploaded.';
}
public function update(int $id)
{
$Products = new Products();
$Stores = new Stores();
$Category = new Category();
$this->verifyRole('updateProduct');
$data['page_title'] = $this->pageTitle;
$Brands = new Brands();
// Validate form inputs
$validation = \Config\Services::validation();
$validation->setRules([
'nom_de_produit' => 'required',
'marque' => 'required',
]);
if ($this->request->getMethod() === 'post' && $validation->withRequest($this->request)->run()) {
$data = [
'name' => $this->request->getPost('nom_de_produit'),
'sku' => $this->request->getPost('numero_de_serie'),
'price' => $this->request->getPost('price'),
'qty' => 1,
'description' => $this->request->getPost('description'),
'numero_de_moteur' => $this->request->getPost('numero_de_moteur'),
'marque' => $this->request->getPost('marque'),
'chasis' => $this->request->getPost('chasis'),
'store_id' => $this->request->getPost('store'),
'availability' => $this->request->getPost('availability'),
'prix_vente' => $this->request->getPost('price_vente'),
'date_arivage' => $this->request->getPost('datea'),
'puissance' => $this->request->getPost('puissance'),
'cler' => $this->request->getPost('cler'),
'categorie_id' => json_encode($this->request->getPost('categorie[]')),
'etats' => $this->request->getPost('etats'),
'infoManquekit' => $this->request->getPost('infoManquekit'),
'info' => $this->request->getPost('info'),
'infoManque' => $this->request->getPost('infoManque'),
'type'=> $this->request->getPost('type'),
];
// Check if a product image is uploaded
if ($this->request->getFile('product_image')->isValid()) {
$uploadImage = $this->uploadImage(); // Use the previously provided upload function
$uploadData = ['image' => $uploadImage];
// Update the product with the uploaded image
$Products->update($id, $uploadData);
}
if ($Products->updateProduct($data, $id)) {
// die(var_dump('tonga eto'));
session()->setFlashdata('success', 'Successfully updated');
return redirect()->to('/products');
} else {
session()->setFlashdata('errors', 'Error occurred!!');
return redirect()->to('/produtcs/update/' . $id);
}
} else {
$data = [
'stores' => $Stores->getActiveStore(),
'validation' => $validation, // Pass validation errors to the view
'page_title' => $this->pageTitle,
'product_data' => $Products->getProductData($id),
'categorie' => $Category->getActiveCategory(),
'marque' => $Brands->getActiveBrands()
];
return $this->render_template('products/editbackup', $data);
}
}
public function remove()
{
$this->verifyRole('deleteProduct');
$product_id = $this->request->getPost('product_id');
$response = [];
$Products = new Products();
if ($product_id) {
if ($Products->remove($product_id)) {
$response['success'] = true;
$response['messages'] = "Successfully removed";
} else {
$response['success'] = false;
$response['messages'] = "Error in the database while removing the product information";
}
} else {
$response['success'] = false;
$response['messages'] = "Refersh the page again!!";
}
// Return JSON response
return $this->response->setJSON($response);
}
public function createByExcel()
{
$this->verifyRole("createProduct");
try {
$file = $this->request->getFile('excel_product');
if (!$file || !$file->isValid()) {
return $this->response->setJSON([
'success' => false,
'messages' => "Fichier invalide ou non reçu"
]);
}
$ext = strtolower($file->getClientExtension());
if (!in_array($ext, ['xls', 'xlsx'])) {
return $this->response->setJSON([
'success' => false,
'messages' => "Seuls les fichiers Excel (.xls, .xlsx) sont acceptés"
]);
}
$spreadsheet = IOFactory::load($file->getTempName());
$sheet = $spreadsheet->getActiveSheet();
$rows = $sheet->toArray();
if (count($rows) <= 1) {
return $this->response->setJSON([
'success' => false,
'messages' => "Le fichier ne contient pas de données"
]);
}
// Récupérer les en-têtes
$headers = array_shift($rows);
$headers = array_map('strtolower', $headers);
// Mapping des colonnes Excel vers les champs de la base
$columnMapping = [
'n° série' => 'sku',
'marque' => 'marque',
'désignation' => 'name',
'fournisseur' => 'info', // À adapter selon votre besoin
'date d\'arrivage' => 'date_arivage',
'n° moteur' => 'numero_de_moteur',
'châssis' => 'chasis',
'puissance' => 'puissance',
'clé' => 'cler',
'prix d\'achat' => 'price',
'prix ar' => 'prix_vente',
'catégories' => 'categorie_id',
'magasin' => 'store_id',
'disponibilité' => 'availability',
'état' => 'etats',
'pièce manquant' => 'infoManque',
'type' => 'type',
];
$ProductsModel = new Products();
$BrandsModel = new Brands();
$StoresModel = new Stores();
$CategoryModel = new Category();
$countInserted = 0;
foreach ($rows as $row) {
if (empty(array_filter($row))) continue; // Ignore les lignes vides
$data = [
'is_piece' => 0,
'product_sold' => 0,
'qty' => 1
];
// Mapper chaque colonne
foreach ($headers as $index => $header) {
$header = trim($header);
if (isset($columnMapping[$header]) && isset($row[$index])) {
$field = $columnMapping[$header];
$value = trim($row[$index]);
// Traitements spécifiques pour certains champs
switch ($field) {
case 'marque':
// Chercher ou créer la marque
$brand = $BrandsModel->where('name', $value)->first();
if (!$brand) {
$brandId = $BrandsModel->insert(['name' => $value, 'active' => 1]);
} else {
$brandId = $brand['id'];
}
$data[$field] = $brandId;
break;
case 'store_id':
// Gestion du magasin
if ($value == 'TOUS') {
$data[$field] = 0;
} else {
$store = $StoresModel->where('name', $value)->first();
$data[$field] = $store ? $store['id'] : 0;
}
break;
case 'date_arivage':
// Convertir la date Excel en format MySQL
if (is_numeric($value)) {
$data[$field] = date('Y-m-d', \PhpOffice\PhpSpreadsheet\Shared\Date::excelToTimestamp($value));
} else {
$data[$field] = date('Y-m-d', strtotime($value));
}
break;
case 'price':
// Nettoyer "1 900 000 Ar" → 1900000.00
$cleanedValue = str_replace(['Ar', ' ', ','], '', $value);
$data[$field] = (float)$cleanedValue;
break;
default:
$data[$field] = $value;
}
}
}
// Insertion
if (!empty($data['name'])) {
if ($ProductsModel->insert($data)) {
$countInserted++;
}
}
}
return $this->response->setJSON([
'success' => true,
'messages' => "$countInserted produits importés avec succès"
]);
} catch (\Exception $e) {
return $this->response->setJSON([
'success' => false,
'messages' => "Erreur lors de l'import: " . $e->getMessage()
]);
}
}
}