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.
 
 
 
 
 
 

874 lines
30 KiB

<?php
namespace App\Models;
use CodeIgniter\Model;
use App\Models\Products;
use App\Models\OrderItems;
use App\Models\FourchettePrix;
class Orders extends Model
{
/**
* table name
* @var string
*/
protected $table = 'orders';
protected $allowedFields = [
'bill_no',
'customer_name',
'customer_address',
'customer_phone',
'customer_cin',
'customer_type',
'source',
'date_time',
'gross_amount',
'service_charge_rate',
'vat_charge_rate',
'vat_charge',
'net_amount',
'discount',
'paid_status',
'user_id',
'validated_by',
'validated_at',
'store_id',
'tranche_1',
'tranche_2',
'order_payment_mode',
'order_payment_mode_1',
'delivered_at',
'delivered_by'
];
/**
* get the order data
* @param int $id
* @return array|object|null
*/
// public function getOrdersData(int $id = null)
// {
// $session = session();
// $users = $session->get('user');
// // teste
// $this->select('orders.bill_no, orders.customer_name, orders.customer_phone, orders.date_time,
// orders.gross_amount, orders.net_amount, orders.paid_status, products.name as product_name')
// ->join('orders_item', 'orders.id = orders_item.order_id', 'left')
// ->join('product', 'orders_item.product_id = product.id', 'left');
// if ($id) {
// return $this->find($id); // Fetch a single order
// }
// return $this->where("store_id", $users['store_id'])->orderBy('id', 'DESC')->findAll(); // Fetch all orders, ordered by ID
// }
public function getUserGroupNameByUserId($userId)
{
return $this->db->table('users')
->select('groups.group_name as group_name')
->join('user_group', 'user_group.user_id = users.id', 'left')
->join('groups', 'groups.id = user_group.group_id', 'left')
->where('users.id', $userId)
->get()
->getRowArray(); // Retourne un tableau associatif
}
public function getOrdersData(int $id = null)
{
$session = session();
$user = $session->get('user');
// ✅ CORRECTION : Si on demande UNE commande spécifique
if ($id !== null) {
return $this->db->table('orders')
->select([
'orders.*', // ✅ Ceci inclut déjà customer_type et source
"CONCAT(users.firstname, ' ', users.lastname) AS user_name"
])
->join('users', 'orders.user_id = users.id', 'left')
->where('orders.id', $id)
->get()
->getRowArray(); // ✅ Retourne bien un tableau associatif
}
// Pour la LISTE des commandes (avec GROUP_CONCAT)
$builder = $this->db->table('orders')
->select([
'orders.id',
'orders.bill_no',
'orders.store_id',
'orders.customer_name',
'orders.customer_phone',
'orders.customer_cin',
'orders.customer_address',
'orders.customer_type', // ✅ DÉJÀ PRÉSENT
'orders.source', // ✅ DÉJÀ PRÉSENT
'orders.discount',
'orders.date_time',
'orders.gross_amount',
'orders.net_amount',
'orders.paid_status',
'orders.user_id',
"CONCAT(users.firstname, ' ', users.lastname) AS user_name"
])
->join('users', 'orders.user_id = users.id', 'left')
->join('orders_item', 'orders_item.order_id = orders.id', 'left')
->join('products', 'products.id = orders_item.product_id', 'left')
->select("IFNULL(GROUP_CONCAT(DISTINCT products.name SEPARATOR '\\n'), '') AS product_names", false)
->groupBy('orders.id');
// Récupération du groupe de l'utilisateur
$group = $this->getUserGroupNameByUserId($user['id']);
$groupName = $group['group_name'] ?? '';
// Selon le rôle
if (in_array($groupName, ['Direction', 'Conseil'], true)) {
return $builder
->orderBy('orders.id', 'DESC')
->get()
->getResultArray();
}
return $builder
->where('orders.store_id', $user['store_id'])
->orderBy('orders.id', 'DESC')
->get()
->getResultArray();
}
public function getOrdersDataByBillNo(string $id = null)
{
$session = session();
$users = $session->get('user');
$builder = $this->db->table('orders')
->select('orders.id, orders.bill_no, orders.customer_name, orders.customer_phone, orders.customer_cin, orders.customer_address, orders.discount, orders.date_time,
orders.gross_amount, orders.net_amount, orders.paid_status');
// ->join('orders_item', 'orders.id = orders_item.order_id', 'left')
// ->join('products', 'orders_item.product_id = products.id', 'left');
if ($id) {
return $builder->where('orders.bill_no', $id)->get()->getRowArray(); // Retourne une seule commande
}
// Récupération du nom de groupe
$group = $this->getUserGroupNameByUserId($users['id']);
$groupName = $group['group_name'] ?? ''; // Évite une erreur si 'group_name' est null
if ($groupName === "Direction" || $groupName === "Conseil") {
return $builder->orderBy('orders.id', 'DESC')->get()->getResultArray();
} else {
return $builder->where('orders.store_id', $users['store_id'])
->orderBy('orders.id', 'DESC')
->get()
->getResultArray(); // Retourne toutes les commandes du magasin
}
}
/**
* get the orders item data
* @param mixed $order_id
* @return array|bool
*/
public function getOrdersItemData($order_id = null)
{
if (!$order_id) {
return false;
}
return $this->where('order_id', $order_id)->findAll(); // Get items of a specific order
}
/**
* create order
*/
public function create(array $data, $post)
{
try {
// Insert the order data
$this->insert($data);
$order_id = $this->insertID();
// Initialize models
$orderItemModel = new OrderItems();
$productModel = new Products();
// ✅ RÉCUPÉRER LE TABLEAU DES PUISSANCES
$puissances = $data['puissance'] ?? [];
// Loop through products and insert order items
$count_product = count($post);
for ($x = 0; $x < $count_product; $x++) {
// ✅ AJOUT DE LA PUISSANCE
$items = [
'order_id' => $order_id,
'product_id' => $post[$x],
'rate' => $data['rate_value'][$x],
'qty' => 1,
'amount' => $data['amount_value'][$x],
'puissance' => $puissances[$x] ?? 1, // ✅ CORRECTION ICI
];
$orderItemModel->insert($items);
// Decrease stock for the product
$product_data = $productModel->find($post[$x]);
if((int)$data['paid_status'] == 1){
if ($product_data) {
$product_sold = true;
$productModel->update($post[$x], ['product_sold' => $product_sold]);
} else {
$product_sold = false;
$productModel->update($post[$x], ['product_sold' => $product_sold]);
}
}
}
return $order_id;
} catch (\Exception $e) {
log_message('error', 'Error creating order: ' . $e->getMessage());
return false;
}
}
/**
* count order item
* @param int $order_id
* @return int|string
*/
public function countOrderItem(int $order_id)
{
if ($order_id) {
$orderItemModel = new OrderItems();
return $orderItemModel->where('order_id', $order_id)->countAllResults();
}
return 0;
}
/**
* update order
* @param int $id
* @return bool
*/
public function updates(int $id, $data)
{
if ($id) {
$this->update($id, $data);
// Update order items
$orderItemModel = new OrderItems();
$productModel = new Products();
// First revert the product quantity to its original value
$get_order_item = $orderItemModel->getOrdersItemData($id);
foreach ($get_order_item as $item) {
$product_data = $productModel->find($item['product_id']);
}
// Delete existing items
$orderItemModel->where('order_id', $id)->delete();
// Insert new items
$count_product = count($data['product']);
for ($x = 0; $x < $count_product; $x++) {
$items = [
'order_id' => $id,
'product_id' => $data['product'][$x],
'rate' => $data['rate_value'][$x],
'puissance' => $data['puissance'][$x],
'amount' => $data['amount_value'][$x],
];
$orderItemModel->insert($items);
// Update stock quantity
// $product_data = $productModel->find($data['product'][$x]);
// $qty = (int) $product_data['qty'] - (int) $data['qty'][$x];
if((int)$data['paid_status'] == 1){
$product_sold = true;
// Update product stock
$productModel->update($data['product'][$x], ['product_sold' => $product_sold]);
}
else{
$product_sold = false;
$productModel->update($data['product'][$x], ['product_sold' => $product_sold]);
}
}
return true;
}
return false;
}
/**
* delete order
* @param int $id
* @return bool
*/
public function remove(int $id)
{
if ($id) {
$orderItemModel = new OrderItems();
$Product = new Products();
// Delete order and items
$this->delete($id);
// Get the selected order item
$selectorderItem = $orderItemModel->where('order_id', $id)->first();
$securite = new Securite();
if ($selectorderItem) {
$product_id = $selectorderItem['product_id'];
$securite->removeSecurite($product_id);
// $qty = $selectorderItem['qty'];
// Fetch the current product details
$product = $Product->find($product_id);
if ($product) {
// Add the new qty to the existing qty
$product_sold = false;
// Update the product quantity
$data = ['product_sold' => $product_sold];
$Product->update($product_id, $data);
}
}
// die(var_dump($selectorderItem['product_id']));
$orderItemModel->where('order_id', $id)->delete();
return true;
}
return false;
}
/**
* count of order already paid
* @return int|string
*/
public function countTotalPaidOrders()
{
return $this->whereIn('paid_status', [1, 3])->countAllResults();
}
public function getPaidOrderData()
{
$session = session();
$users = $session->get('user');
$isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']);
if($isAdmin) {
return $this->whereIn('paid_status', [1, 3]) // ← Ajoutez 3 ici
->orderBy('id', 'DESC')
->findAll();
}
else {
return $this->whereIn('paid_status', [1, 3]) // ← Ajoutez 3 ici
->where('store_id', $users['store_id'])
->orderBy('id', 'DESC')
->findAll();
}
}
public function getSingleStat(int $id)
{
return $this->select('orders.*, orders_item.*')
->join('orders_item', 'orders_item.order_id = orders.id')
->where('orders.user_id', $id)
->findAll();
}
public function getPaymentModes()
{
$session = session();
$users = $session->get('user');
$isAdmin = in_array($users['group_name'], ['Conseil', 'Direction']);
$baseQuery = $this->db->table('orders')
->select('
SUM(CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN orders.discount
ELSE orders.net_amount
END) AS total,
SUM(CASE
WHEN orders.order_payment_mode = "MVOLA" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN (orders.tranche_1 * orders.discount / orders.net_amount)
ELSE orders.tranche_1
END
ELSE 0
END) AS total_mvola1,
SUM(CASE
WHEN orders.order_payment_mode_1 = "MVOLA" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN (orders.tranche_2 * orders.discount / orders.net_amount)
ELSE orders.tranche_2
END
ELSE 0
END) AS total_mvola2,
SUM(CASE
WHEN orders.order_payment_mode = "En espèce" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN (orders.tranche_1 * orders.discount / orders.net_amount)
ELSE orders.tranche_1
END
ELSE 0
END) AS total_espece1,
SUM(CASE
WHEN orders.order_payment_mode_1 = "En espèce" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN (orders.tranche_2 * orders.discount / orders.net_amount)
ELSE orders.tranche_2
END
ELSE 0
END) AS total_espece2,
SUM(CASE
WHEN orders.order_payment_mode = "Virement bancaire" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN (orders.tranche_1 * orders.discount / orders.net_amount)
ELSE orders.tranche_1
END
ELSE 0
END) AS total_virement_bancaire1,
SUM(CASE
WHEN orders.order_payment_mode_1 = "Virement bancaire" THEN
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN (orders.tranche_2 * orders.discount / orders.net_amount)
ELSE orders.tranche_2
END
ELSE 0
END) AS total_virement_bancaire2
')
->whereIn('orders.paid_status', [1, 3]); // ← CHANGEZ CETTE LIGNE
if (!$isAdmin) {
$baseQuery->where('orders.store_id', $users['store_id']);
}
return $baseQuery->get()->getRowObject();
}
public function getTotalOrders()
{
return $this->db->table('orders')
->select(' COUNT(*) as total_orders')
->get()
->getRow();
}
public function getTotalOrderPerStore()
{
return $this->db->table('orders')
->select('store_id, COUNT(*) as total')
->groupBy('store_id')
->get()
->getResult();
}
public function getPaymentModesPercentage()
{
$totalOrders = $this->db->table('orders')
->where('paid_status', '1')
->countAllResults();
if ($totalOrders == 0) {
return [];
}
$paymentModesCount = $this->db->table('orders')
->select('order_payment_mode, order_payment_mode_1')
->where('paid_status', '1')
->get()
->getResultArray();
$uniquePaymentModes = [];
foreach ($paymentModesCount as $order) {
if (!empty($order['order_payment_mode']) && !isset($uniquePaymentModes[$order['order_payment_mode']])) {
$uniquePaymentModes[$order['order_payment_mode']] = 0;
}
if (!empty($order['order_payment_mode_1']) && !isset($uniquePaymentModes[$order['order_payment_mode_1']])) {
$uniquePaymentModes[$order['order_payment_mode_1']] = 0;
}
}
foreach ($paymentModesCount as $order) {
if (!empty($order['order_payment_mode'])) {
$uniquePaymentModes[$order['order_payment_mode']]++;
}
if (!empty($order['order_payment_mode_1'])) {
$uniquePaymentModes[$order['order_payment_mode_1']]++;
}
}
$paymentModesPercentage = [];
foreach ($uniquePaymentModes as $mode => $count) {
$modePercentage = ($count / $totalOrders) * 100;
$paymentModesPercentage[$mode] = $modePercentage;
}
return $paymentModesPercentage;
}
public function getTotalProductvente()
{
$order = $this->db->table('orders')
->select('orders.id, orders.paid_status, orders.store_id, orders.date_time, brands.name, products.name as Pname')
->join('orders_item', 'orders.id = orders_item.order_id')
->join('products', 'orders_item.product_id = products.id')
->join('brands', 'brands.id = products.marque')
->whereIn('orders.paid_status', [1, 3]) // ← CHANGÉ ICI
->get()
->getResult();
return $order;
}
public function getTotalProductvente2(?int $id)
{
if ($id != 0) {
$order = $this->db->table('orders')
->select('orders.id, orders.paid_status, orders.store_id, orders.date_time, brands.name, products.name as Pname, products.sku')
->join('orders_item', 'orders.id = orders_item.order_id')
->join('products', 'orders_item.product_id = products.id')
->join('brands', 'brands.id = products.marque')
->whereIn('orders.paid_status', [1, 3]) // ← CHANGÉ ICI
->where('orders.store_id', $id)
->get()
->getResult();
} else {
$order = $this->db->table('orders')
->select('orders.id, orders.paid_status, orders.store_id, orders.date_time, brands.name, products.name as Pname, products.sku')
->join('orders_item', 'orders.id = orders_item.order_id')
->join('products', 'orders_item.product_id = products.id')
->join('brands', 'brands.id = products.marque')
->whereIn('orders.paid_status', [1, 3]) // ← CHANGÉ ICI
->get()
->getResult();
}
return $order;
}
public function getOrderVendue()
{
$order = $this->db->table('products')
->select('
products.*,
products.name as Pname,
products.sku,
CASE
WHEN orders.discount > 0 AND orders.discount IS NOT NULL
THEN orders.discount
ELSE orders.gross_amount
END as totalNet,
orders.date_time as DateTime
', false) // ← MODIFIÉ ICI
->join('orders_item', 'products.id = orders_item.product_id')
->join('orders', 'orders_item.order_id = orders.id')
->whereIn('orders.paid_status', [1, 3]) // ← ET ICI
->get()
->getResultArray();
return $order;
}
public function getPerformanceByOrders()
{
$Performance = $this->db->table('orders')
->select('orders.id as orderid, orders.net_amount, orders.date_time as datevente, orders.discount, products.price, products.sku, products.prix_vente, products.name as motoname, stores.id as store_id, users.firstname, users.lastname, users.email')
->join('stores', 'orders.store_id = stores.id')
->join('orders_item', 'orders.id = orders_item.order_id')
->join('products', 'products.id = orders_item.product_id')
->join('users', 'users.id = orders.user_id')
->whereIn('orders.paid_status', [1, 3])
->get()
->getResultArray();
return $Performance;
}
// for Adminan cheffe d'agence
public function getPerformanceByOrders1()
{
$session = session();
$users = $session->get('user');
$Performance = $this->db
->table('orders')
->select('orders.id as orderid, orders.net_amount, orders.date_time as datevente, orders.discount, products.price, products.sku, products.prix_vente, products.name as motoname, stores.id as store_id, users.firstname, users.lastname, users.email')
->join('stores', 'orders.store_id = stores.id')
->join('orders_item', 'orders.id = orders_item.order_id')
->join('products', 'products.id = orders_item.product_id')
->join('users', 'users.id = orders.user_id')
->whereIn('orders.paid_status', [1, 3])
->where('orders.store_id', $users["store_id"])
->get()
->getResultArray();
return $Performance;
}
// for commerciale
public function getPerformanceByOrders2()
{
$session = session();
$users = $session->get('user');
$Performance = $this->db
->table('orders')
->select('orders.id as orderid, orders.net_amount, orders.date_time as datevente, orders.discount, products.price, products.sku, products.prix_vente, products.name as motoname, stores.id as store_id, users.firstname, users.lastname, users.email')
->join('stores', 'orders.store_id = stores.id')
->join('orders_item', 'orders.id = orders_item.order_id')
->join('products', 'products.id = orders_item.product_id')
->join('users', 'users.id = orders.user_id')
->whereIn('orders.paid_status', [1, 3])
->where('orders.user_id', $users["id"])
->get()
->getResultArray();
return $Performance;
}
public function update1(int $id, $data1,$data2)
{
if ($id) {
$this->update($id, $data1);
// Update order items
$orderItemModel = new OrderItems();
$orderItemModel->updateOrderItem($id,$data2);
}
}
public function getUserList()
{
$session = session();
$users = $session->get('user');
try {
return $this->db->table('users')
->select("users.id AS user_id, CONCAT(firstname, ' ', lastname) AS full_name")
->join('user_group', 'user_group.user_id = users.id')
->join('groups', 'groups.id = user_group.group_id')
->where('groups.id',4)
// ->where('users.store_id',$users['store_id'])
->get()
->getResult();
} catch (\Throwable $th) {
return [];
}
}
public function getUserPerformanceToday(string $date)
{
$users = $this->getUserList();
$results = [];
foreach ($users as $user) {
$summary = $this->db->table('orders')
->select('COUNT(id) AS total_user_order, SUM(net_amount) AS total_prix_vente')
->where('user_id', $user->user_id)
->where('DATE(date_time)', $date)
->whereIn('paid_status', [1, 3])
->get()
->getRow();
$ids = $this->db->table('orders')
->select('id')
->where('user_id', $user->user_id)
->where('DATE(date_time)', $date)
->whereIn('paid_status', [1, 3])
->get()
->getResult();
$orderIds = array_map(fn($o) => $o->id, $ids);
$results[] = [
'user_id' => $user->user_id,
'full_name' => $user->full_name,
'total_user_order' => $summary->total_user_order,
'total_prix_vente' => $summary->total_prix_vente,
'order_ids' => $orderIds,
];
}
return $results;
}
public function getUserPerformanceByWeek(string $date = null)
{
$users = $this->getUserList();
$results = [];
if ($date === null) {
$date = date('Y-m-d');
}
$timestamp = strtotime($date);
$startOfWeek = date('Y-m-d', strtotime('monday this week', $timestamp));
$endOfWeek = date('Y-m-d', strtotime('sunday this week', $timestamp));
foreach ($users as $user) {
$summary = $this->db->table('orders')
->select('COUNT(id) AS total_user_order, SUM(net_amount) AS total_prix_vente')
->where('user_id', $user->user_id)
->where('DATE(date_time) >=', $startOfWeek)
->where('DATE(date_time) <=', $endOfWeek)
->whereIn('paid_status', [1, 3])
->get()
->getRow();
$ids = $this->db->table('orders')
->select('id')
->where('user_id', $user->user_id)
->where('DATE(date_time) >=', $startOfWeek)
->where('DATE(date_time) <=', $endOfWeek)
->whereIn('paid_status', [1, 3])
->get()
->getResult();
$orderIds = array_map(fn($o) => $o->id, $ids);
$results[] = [
'user_id' => $user->user_id,
'full_name' => $user->full_name,
'total_user_order' => $summary->total_user_order ?? 0,
'total_prix_vente' => $summary->total_prix_vente ?? 0,
'order_ids' => $orderIds,
];
}
return $results;
}
public function checkMinimalPrice($product_id, $discount)
{
$fourchetteModel = new FourchettePrix(); // plus court car on a "use"
$row = $fourchetteModel->where('product_id', $product_id)->first();
if ($row) {
return ($discount >= $row['prix_minimal']);
}
return true;
}
public function getUserPerformanceByMonth(string $month)
{
$startOfMonth = date('Y-m-01', strtotime($month . '-01'));
$endOfMonth = date('Y-m-t', strtotime($month . '-01'));
$users = $this->getUserList();
$results = [];
foreach ($users as $user) {
$orderData = $this->db->table('orders')
->select('COUNT(id) as total_user_order, SUM(net_amount) as total_prix_vente')
->where('user_id', $user->user_id)
->where('DATE(date_time) >=', $startOfMonth)
->where('DATE(date_time) <=', $endOfMonth)
->whereIn('paid_status', [1, 3])
->get()
->getRow();
$ids = $this->db->table('orders')
->select('id')
->where('user_id', $user->user_id)
->where('DATE(date_time) >=', $startOfMonth)
->where('DATE(date_time) <=', $endOfMonth)
->whereIn('paid_status', [1, 3])
->get()
->getResult();
$orderIds = array_map(fn($o) => $o->id, $ids);
$results[] = [
'user_id' => $user->user_id,
'full_name' => $user->full_name,
'total_user_order' => $orderData->total_user_order ?? 0,
'total_prix_vente' => $orderData->total_prix_vente ?? 0,
'order_ids' => $orderIds,
];
}
return $results;
}
public function getPerformanceByCaissier(int $caissierId, $startDate = null, $endDate = null)
{
$builder = $this->db->table('orders')
->select('
orders.id as orderid,
orders.net_amount,
orders.date_time as datevente,
orders.discount,
orders.validated_at,
products.price,
products.sku,
products.prix_vente,
products.name as motoname,
stores.id as store_id,
stores.name as store_name,
CONCAT(validator.firstname, " ", validator.lastname) as caissier_name
')
->join('stores', 'orders.store_id = stores.id', 'left')
->join('orders_item', 'orders.id = orders_item.order_id', 'left')
->join('products', 'products.id = orders_item.product_id', 'left')
->join('users as validator', 'validator.id = orders.validated_by', 'left')
->whereIn('orders.paid_status', [1, 3])
->where('orders.validated_by', $caissierId)
->where('orders.validated_by IS NOT NULL', null, false);
// ✅ AJOUT : Filtrage par dates
if ($startDate && $endDate) {
$builder->where('DATE(orders.validated_at) >=', $startDate)
->where('DATE(orders.validated_at) <=', $endDate);
} elseif ($startDate) {
$builder->where('DATE(orders.validated_at) >=', $startDate);
} elseif ($endDate) {
$builder->where('DATE(orders.validated_at) <=', $endDate);
}
return $builder->orderBy('orders.validated_at', 'DESC')
->get()
->getResultArray();
}
}