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.
778 lines
28 KiB
778 lines
28 KiB
<?php
|
|
namespace App\Models;
|
|
|
|
use CodeIgniter\Model;
|
|
|
|
class Avance extends Model {
|
|
protected $table = 'avances';
|
|
protected $primaryKey = 'avance_id';
|
|
|
|
protected $allowedFields = [
|
|
'avance_amount', 'avance_date','user_id',
|
|
'customer_name', 'customer_address', 'customer_phone', 'customer_cin',
|
|
'gross_amount','amount_due','product_id','is_order','active','store_id',
|
|
'type_avance','type_payment', 'deadline','commentaire','product_name'
|
|
];
|
|
|
|
public function createAvance(array $data) {
|
|
try {
|
|
if (empty($data['avance_date'])) {
|
|
$data['avance_date'] = date('Y-m-d');
|
|
}
|
|
|
|
if (!empty($data['type'])) {
|
|
if (strtolower($data['type']) === 'avance sur terre') {
|
|
$data['deadline'] = date('Y-m-d', strtotime($data['avance_date'] . ' +15 days'));
|
|
} elseif (strtolower($data['type']) === 'avance sur mer') {
|
|
$data['deadline'] = date('Y-m-d', strtotime($data['avance_date'] . ' +2 months'));
|
|
}
|
|
}
|
|
|
|
return $this->insert($data);
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur lors de l\'ajout de l\'avance : ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function updateAvance(int $id, array $data) {
|
|
if ($id <= 0) {
|
|
log_message('error', 'ID invalide pour la mise à jour du recouvrement : ' . $id);
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
if (!empty($data['type']) && !empty($data['avance_date'])) {
|
|
if (strtolower($data['type']) === 'avance sur terre') {
|
|
$data['deadline'] = date('Y-m-d', strtotime($data['avance_date'] . ' +15 days'));
|
|
} elseif (strtolower($data['type']) === 'avance sur mer') {
|
|
$data['deadline'] = date('Y-m-d', strtotime($data['avance_date'] . ' +2 months'));
|
|
}
|
|
}
|
|
|
|
// ✅ Mettre à jour l'avance
|
|
$updateResult = $this->update($id, $data);
|
|
|
|
if (!$updateResult) {
|
|
return false;
|
|
}
|
|
|
|
// ✅ AJOUT CRITIQUE : Vérifier automatiquement si conversion nécessaire
|
|
$this->autoCheckAndConvert($id);
|
|
|
|
return true;
|
|
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur lors de la mise à jour de l\'avance : ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private function autoCheckAndConvert(int $avance_id)
|
|
{
|
|
try {
|
|
// Recharger l'avance fraîchement mise à jour
|
|
$avance = $this->find($avance_id);
|
|
|
|
if (!$avance) {
|
|
log_message('warning', "⚠️ Avance {$avance_id} introuvable pour vérification auto");
|
|
return false;
|
|
}
|
|
|
|
// ✅ Conditions de conversion automatique
|
|
$shouldConvert = (
|
|
$avance['type_avance'] === 'terre' && // C'est une avance sur terre
|
|
(float)$avance['amount_due'] <= 0.01 && // Montant dû = 0 (avec tolérance)
|
|
$avance['is_order'] == 0 && // Pas encore convertie
|
|
$avance['active'] == 1 // Encore active
|
|
);
|
|
|
|
if ($shouldConvert) {
|
|
log_message('info', "🔄 [AUTO-CHECK] Avance {$avance_id} complète détectée ! Conversion automatique...");
|
|
|
|
// ✅ Appeler la conversion
|
|
$order_id = $this->convertToOrder($avance_id);
|
|
|
|
if ($order_id) {
|
|
log_message('info', "✅ [AUTO-CHECK] Conversion réussie → Commande {$order_id}");
|
|
return $order_id;
|
|
} else {
|
|
log_message('error', "❌ [AUTO-CHECK] Échec conversion avance {$avance_id}");
|
|
return false;
|
|
}
|
|
} else {
|
|
// Log pour débogage
|
|
$reason = '';
|
|
if ($avance['type_avance'] !== 'terre') $reason .= 'type=' . $avance['type_avance'] . ' ';
|
|
if ((float)$avance['amount_due'] > 0.01) $reason .= 'reste=' . $avance['amount_due'] . ' ';
|
|
if ($avance['is_order'] == 1) $reason .= 'déjà_convertie ';
|
|
if ($avance['active'] == 0) $reason .= 'inactive ';
|
|
|
|
if (!empty($reason)) {
|
|
log_message('info', "ℹ️ [AUTO-CHECK] Avance {$avance_id} non éligible pour conversion : {$reason}");
|
|
}
|
|
}
|
|
|
|
return false;
|
|
|
|
} catch (\Exception $e) {
|
|
log_message('error', "❌ [AUTO-CHECK] Erreur vérification avance {$avance_id}: " . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function getAllAvanceData(int $id=null) {
|
|
$session = session();
|
|
$users = $session->get('user');
|
|
$isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction','DAF']);
|
|
if($isAdmin) {
|
|
if($id){
|
|
try {
|
|
return $this->where('user_id',$id)
|
|
->where('is_order',0)
|
|
->where('active',1)
|
|
->orderBy('avance_date', 'DESC')
|
|
->findAll();
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur lors de la récupération des recouvrements : ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
try {
|
|
return $this
|
|
->where('is_order',0)
|
|
->where('active',1)
|
|
->orderBy('avance_date', 'DESC')
|
|
->findAll();
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur lors de la récupération des recouvrements : ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
} else {
|
|
if($id){
|
|
try {
|
|
return $this->where('user_id',$id)
|
|
->where('is_order',0)
|
|
->where('active',1)
|
|
->where('store_id',$users['store_id'])
|
|
->orderBy('avance_date', 'DESC')
|
|
->findAll();
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur lors de la récupération des recouvrements : ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
try {
|
|
return $this
|
|
->where('is_order',0)
|
|
->where('active',1)
|
|
->where('store_id',$users['store_id'])
|
|
->orderBy('avance_date', 'DESC')
|
|
->findAll();
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur lors de la récupération des recouvrements : ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
public function fetchSingleAvance(int $avance_id){
|
|
return $this->select('avances.*, products.name as product_name_db, products.prix_vente as product_price')
|
|
->join('products', 'products.id = avances.product_id', 'left')
|
|
->where('avances.avance_id', $avance_id)
|
|
->first();
|
|
}
|
|
|
|
public function removeAvance(int $avance_id){
|
|
return $this->delete($avance_id);
|
|
}
|
|
|
|
// ✅ CORRECTION : getTotalAvance pour la caissière
|
|
public function getTotalAvance() {
|
|
$session = session();
|
|
$users = $session->get('user');
|
|
$isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction','DAF']);
|
|
|
|
try {
|
|
$builder = $this->select('SUM(avance_amount) AS ta')
|
|
->where('is_order', 0)
|
|
->where('active', 1); // ✅ Ajout du filtre active
|
|
|
|
if (!$isAdmin) {
|
|
$builder->where('store_id', $users['store_id']); // ✅ Filtre par store pour caissière
|
|
}
|
|
|
|
return $builder->get()->getRowObject();
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur lors du total du montant des avances : ' . $e->getMessage());
|
|
return (object) ['ta' => 0]; // ✅ Retourner un objet avec ta = 0 en cas d'erreur
|
|
}
|
|
}
|
|
|
|
// ✅ CORRECTION PRINCIPALE : getPaymentModesAvance pour la caissière
|
|
public function getPaymentModesAvance()
|
|
{
|
|
$session = session();
|
|
$users = $session->get('user');
|
|
$isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction','DAF']);
|
|
|
|
try {
|
|
$builder = $this->db->table('avances')
|
|
->select('
|
|
SUM(avance_amount) AS total,
|
|
SUM(CASE WHEN LOWER(type_payment) = "mvola" THEN avance_amount ELSE 0 END) AS total_mvola,
|
|
SUM(CASE WHEN LOWER(type_payment) = "en espèce" THEN avance_amount ELSE 0 END) AS total_espece,
|
|
SUM(CASE WHEN LOWER(type_payment) = "virement bancaire" THEN avance_amount ELSE 0 END) AS total_virement_bancaire
|
|
')
|
|
->where('active', 1)
|
|
->where('is_order', 0); // ✅ Exclure les avances devenues orders
|
|
|
|
// ✅ CORRECTION : Ajouter le filtre store_id pour la caissière
|
|
if (!$isAdmin) {
|
|
$builder->where('store_id', $users['store_id']);
|
|
}
|
|
|
|
$result = $builder->get()->getRowObject();
|
|
|
|
// ✅ Gérer le cas où il n'y a pas de résultats
|
|
if (!$result) {
|
|
return (object) [
|
|
'total' => 0,
|
|
'total_mvola' => 0,
|
|
'total_espece' => 0,
|
|
'total_virement_bancaire' => 0
|
|
];
|
|
}
|
|
|
|
return $result;
|
|
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur getPaymentModesAvance: ' . $e->getMessage());
|
|
return (object) [
|
|
'total' => 0,
|
|
'total_mvola' => 0,
|
|
'total_espece' => 0,
|
|
'total_virement_bancaire' => 0
|
|
];
|
|
}
|
|
}
|
|
|
|
public function getAllAvanceData1(int $id=null) {
|
|
$session = session();
|
|
$users = $session->get('user');
|
|
$isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction','DAF']);
|
|
if($isAdmin) {
|
|
if($id){
|
|
try {
|
|
return $this->where('user_id',$id)
|
|
->where('is_order',1)
|
|
->where('active',1)
|
|
->orderBy('avance_date', 'DESC')
|
|
->findAll();
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur lors de la récupération des recouvrements : ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
try {
|
|
return $this
|
|
->where('is_order',1)
|
|
->where('active',1)
|
|
->orderBy('avance_date', 'DESC')
|
|
->findAll();
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur lors de la récupération des recouvrements : ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
} else {
|
|
if($id){
|
|
try {
|
|
return $this->where('user_id',$id)
|
|
->where('is_order',1)
|
|
->where('active',1)
|
|
->where('store_id',$users['store_id'])
|
|
->orderBy('avance_date', 'DESC')
|
|
->findAll();
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur lors de la récupération des recouvrements : ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
try {
|
|
return $this
|
|
->where('is_order',1) // ✅ Correction: devrait être 1, pas 0
|
|
->where('active',1) // ✅ Ajout du filtre active
|
|
->where('store_id',$users['store_id']) // ✅ Ajout du filtre store
|
|
->orderBy('avance_date', 'DESC')
|
|
->findAll();
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur lors de la récupération des recouvrements : ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
public function getAllAvanceData2(int $id=null) {
|
|
$session = session();
|
|
$users = $session->get('user');
|
|
$isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction', 'DAF']);
|
|
if($isAdmin) {
|
|
if($id){
|
|
try {
|
|
return $this->where('user_id',$id)
|
|
->where('is_order',0)
|
|
->where('active',0)
|
|
->orderBy('avance_date', 'DESC')
|
|
->findAll();
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur lors de la récupération des recouvrements : ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
try {
|
|
return $this
|
|
->where('is_order',0)
|
|
->where('active',0)
|
|
->orderBy('avance_date', 'DESC')
|
|
->findAll();
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur lors de la récupération des recouvrements : ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
} else {
|
|
if($id){
|
|
try {
|
|
return $this->where('user_id',$id)
|
|
->where('is_order',0)
|
|
->where('active',0)
|
|
->where('store_id',$users['store_id'])
|
|
->orderBy('avance_date', 'DESC')
|
|
->findAll();
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur lors de la récupération des recouvrements : ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
try {
|
|
return $this
|
|
->where('is_order',0)
|
|
->where('active',0)
|
|
->where('store_id',$users['store_id'])
|
|
->orderBy('avance_date', 'DESC')
|
|
->findAll();
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur lors de la récupération des recouvrements : ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
public function checkExpiredAvance() {
|
|
$now = date('Y-m-d');
|
|
$avances = $this->where('active', '1')
|
|
->where('deadline <', $now)
|
|
->findAll();
|
|
|
|
if (!empty($avances)) {
|
|
$productModel = new Products();
|
|
|
|
foreach ($avances as $avance) {
|
|
$this->update($avance['avance_id'], ['active' => '0']);
|
|
if (!empty($avance['product_id'])) { // ✅ Vérifier que product_id existe
|
|
$productModel->update($avance['product_id'], ['product_sold' => 0]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public function getAvancesNearDeadline($days = 3)
|
|
{
|
|
$alertDate = date('Y-m-d', strtotime("+{$days} days"));
|
|
|
|
return $this->select('avances.*, users.store_id')
|
|
->join('users', 'users.id = avances.user_id')
|
|
->where('avances.is_order', 0)
|
|
->where('avances.active', 1)
|
|
->where('avances.amount_due >', 0)
|
|
->where('DATE(avances.deadline)', $alertDate)
|
|
->findAll();
|
|
}
|
|
|
|
public function getIncompleteAvances(int $id = null)
|
|
{
|
|
$session = session();
|
|
$users = $session->get('user');
|
|
$isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction', 'DAF']);
|
|
|
|
$builder = $this->where('is_order', 0)
|
|
->where('active', 1)
|
|
->where('amount_due >', 0);
|
|
|
|
if (!$isAdmin) {
|
|
$builder->where('store_id', $users['store_id']);
|
|
}
|
|
|
|
if ($id) {
|
|
$builder->where('user_id', $id);
|
|
}
|
|
|
|
return $builder->orderBy('avance_date', 'DESC')->findAll();
|
|
}
|
|
|
|
public function getCompletedAvances(int $id = null)
|
|
{
|
|
$session = session();
|
|
$users = $session->get('user');
|
|
$isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction', 'DAF']);
|
|
|
|
$builder = $this->where('is_order', 0)
|
|
->where('active', 1)
|
|
->where('amount_due', 0);
|
|
|
|
if (!$isAdmin) {
|
|
$builder->where('store_id', $users['store_id']);
|
|
}
|
|
|
|
if ($id) {
|
|
$builder->where('user_id', $id);
|
|
}
|
|
|
|
return $builder->orderBy('avance_date', 'DESC')->findAll();
|
|
}
|
|
|
|
public function markAsPrinted($avance_id)
|
|
{
|
|
try {
|
|
return $this->update($avance_id, [
|
|
'is_printed' => 1
|
|
]);
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur markAsPrinted: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Marquer une avance comme non imprimée (quand elle est modifiée)
|
|
*/
|
|
public function markAsNotPrinted($avance_id)
|
|
{
|
|
try {
|
|
return $this->update($avance_id, [
|
|
'is_printed' => 0,
|
|
'last_modified_at' => date('Y-m-d H:i:s')
|
|
]);
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur markAsNotPrinted: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Vérifier si une avance a déjà été imprimée
|
|
*/
|
|
public function isPrinted($avance_id)
|
|
{
|
|
try {
|
|
$avance = $this->find($avance_id);
|
|
return $avance ? (bool)$avance['is_printed'] : false;
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur isPrinted: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
/**
|
|
* Récupérer un produit avec le nom de sa marque
|
|
* @param int $product_id
|
|
* @return array|null
|
|
*/
|
|
public function getProductWithBrand($product_id)
|
|
{
|
|
try {
|
|
return $this->select('products.*, brands.name as brand_name')
|
|
->join('brands', 'brands.id = products.marque', 'left')
|
|
->where('products.id', $product_id)
|
|
->first();
|
|
} catch (\Exception $e) {
|
|
log_message('error', 'Erreur getProductWithBrand: ' . $e->getMessage());
|
|
return null;
|
|
}
|
|
}
|
|
// À ajouter dans App\Models\Avance.php
|
|
|
|
/**
|
|
* ✅ Convertir une avance complète en commande
|
|
* Appelé automatiquement quand amount_due atteint 0
|
|
*
|
|
* @param int $avance_id
|
|
* @return int|false ID de la commande créée ou false
|
|
*/
|
|
public function convertToOrder(int $avance_id)
|
|
{
|
|
$db = \Config\Database::connect();
|
|
|
|
try {
|
|
$db->transStart();
|
|
|
|
$avance = $this->find($avance_id);
|
|
|
|
if (!$avance) {
|
|
log_message('error', "❌ Avance {$avance_id} introuvable");
|
|
return false;
|
|
}
|
|
|
|
// ✅ VÉRIFICATION 1 : Type d'avance
|
|
if ($avance['type_avance'] !== 'terre') {
|
|
log_message('info', "⚠️ Avance {$avance_id} est MER, pas de conversion");
|
|
return false;
|
|
}
|
|
|
|
// ✅ VÉRIFICATION 2 : Paiement complet
|
|
if ($avance['amount_due'] > 0) {
|
|
log_message('warning', "⚠️ Avance {$avance_id} non complète (reste: {$avance['amount_due']})");
|
|
return false;
|
|
}
|
|
|
|
// ✅ VÉRIFICATION 3 : Déjà convertie ?
|
|
if ($avance['is_order'] == 1) {
|
|
log_message('info', "⚠️ Avance {$avance_id} déjà convertie");
|
|
|
|
// ✅ Récupérer l'ID de la commande existante
|
|
$existingOrder = $db->table('orders')
|
|
->select('id')
|
|
->where('customer_name', $avance['customer_name'])
|
|
->where('customer_phone', $avance['customer_phone'])
|
|
->where('source', 'Avance convertie')
|
|
->orderBy('id', 'DESC')
|
|
->limit(1)
|
|
->get()
|
|
->getRowArray();
|
|
|
|
return $existingOrder ? $existingOrder['id'] : false;
|
|
}
|
|
|
|
// ✅ VÉRIFICATION 4 : Produit existe ?
|
|
$Products = new \App\Models\Products();
|
|
$product = $Products->find($avance['product_id']);
|
|
|
|
if (!$product) {
|
|
log_message('error', "❌ Produit {$avance['product_id']} introuvable");
|
|
return false;
|
|
}
|
|
|
|
// ✅ Récupérer l'utilisateur actuel
|
|
$session = session();
|
|
$user = $session->get('user');
|
|
|
|
// ✅ Générer le numéro de commande
|
|
$bill_no = $this->generateBillNo($avance['store_id']);
|
|
|
|
// ✅ Préparer les données de commande
|
|
$orderData = [
|
|
'bill_no' => $bill_no,
|
|
'document_type' => 'facture',
|
|
'customer_name' => $avance['customer_name'],
|
|
'customer_address' => $avance['customer_address'],
|
|
'customer_phone' => $avance['customer_phone'],
|
|
'customer_cin' => $avance['customer_cin'],
|
|
'customer_type' => 'Particulier',
|
|
'source' => 'Avance convertie', // ✅ MARQUEUR IMPORTANT
|
|
'date_time' => date('Y-m-d H:i:s'),
|
|
'gross_amount' => $avance['gross_amount'],
|
|
'net_amount' => $avance['gross_amount'],
|
|
'discount' => 0,
|
|
'paid_status' => 2, // En attente de validation
|
|
'user_id' => $user['id'] ?? $avance['user_id'],
|
|
'store_id' => $avance['store_id'],
|
|
'tranche_1' => $avance['avance_amount'],
|
|
'tranche_2' => 0,
|
|
'order_payment_mode' => $avance['type_payment'] ?? 'En espèce',
|
|
'service_charge_rate' => 0,
|
|
'vat_charge_rate' => 0,
|
|
'vat_charge' => 0,
|
|
];
|
|
|
|
// ✅ Créer la commande
|
|
$db->table('orders')->insert($orderData);
|
|
$order_id = $db->insertID();
|
|
|
|
if (!$order_id) {
|
|
throw new \Exception("Échec création commande pour avance {$avance_id}");
|
|
}
|
|
|
|
// ✅ CORRECTION CRITIQUE : Créer l'item de commande SANS 'qty'
|
|
$orderItemData = [
|
|
'order_id' => $order_id,
|
|
'product_id' => $avance['product_id'],
|
|
'rate' => $avance['gross_amount'],
|
|
'amount' => $avance['gross_amount'],
|
|
'puissance' => $product['puissance'] ?? '',
|
|
];
|
|
|
|
$db->table('orders_item')->insert($orderItemData);
|
|
|
|
// ✅ MARQUER L'AVANCE COMME CONVERTIE
|
|
$this->update($avance_id, [
|
|
'is_order' => 1,
|
|
'active' => 0 // ✅ Désactiver pour ne plus apparaître dans les listes
|
|
]);
|
|
|
|
// ✅ Le produit RESTE product_sold = 1 (déjà marqué lors de la création de l'avance)
|
|
|
|
$db->transComplete();
|
|
|
|
if ($db->transStatus() === false) {
|
|
log_message('error', "❌ Transaction échouée pour avance {$avance_id}");
|
|
return false;
|
|
}
|
|
|
|
log_message('info', "✅ Avance {$avance_id} convertie en commande {$order_id}");
|
|
|
|
// ✅ Envoyer notification
|
|
$this->sendConversionNotification($avance, $order_id, $bill_no);
|
|
|
|
return $order_id;
|
|
|
|
} catch (\Exception $e) {
|
|
$db->transRollback();
|
|
log_message('error', "❌ Erreur conversion avance {$avance_id}: " . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private function sendConversionNotification($avance, $order_id, $bill_no)
|
|
{
|
|
try {
|
|
$Notification = new \App\Controllers\NotificationController();
|
|
$Stores = new \App\Models\Stores();
|
|
|
|
$allStores = $Stores->getActiveStore();
|
|
|
|
$message = "🔄 Avance TERRE convertie en commande<br>" .
|
|
"N° Avance : #{$avance['avance_id']}<br>" .
|
|
"Client : {$avance['customer_name']}<br>" .
|
|
"Commande : {$bill_no}<br>" .
|
|
"Montant : " . number_format($avance['gross_amount'], 0, ',', ' ') . " Ar";
|
|
|
|
// ✅ Notifier tous les stores (Direction, DAF, SuperAdmin)
|
|
if (is_array($allStores) && count($allStores) > 0) {
|
|
foreach ($allStores as $store) {
|
|
foreach (['Direction', 'DAF', 'SuperAdmin'] as $role) {
|
|
$Notification->createNotification(
|
|
$message,
|
|
$role,
|
|
(int)$store['id'],
|
|
'orders'
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ✅ Caissière du store concerné
|
|
$Notification->createNotification(
|
|
$message,
|
|
"Caissière",
|
|
(int)$avance['store_id'],
|
|
'orders'
|
|
);
|
|
|
|
} catch (\Exception $e) {
|
|
log_message('error', '❌ Erreur notification: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* ✅ Hook appelé automatiquement lors du paiement d'une avance
|
|
* Intégrer ceci dans votre fonction de paiement existante
|
|
*/
|
|
public function afterPayment(int $avance_id)
|
|
{
|
|
$avance = $this->find($avance_id);
|
|
|
|
if (!$avance) {
|
|
return false;
|
|
}
|
|
|
|
// ✅ Si l'avance est maintenant complète ET que c'est une avance TERRE
|
|
if ((float)$avance['amount_due'] <= 0 && $avance['type_avance'] === 'terre') {
|
|
log_message('info', "💰 Avance TERRE {$avance_id} complète ! Conversion automatique en commande...");
|
|
return $this->convertToOrder($avance_id);
|
|
}
|
|
|
|
// ✅ Si c'est une avance MER complète, on ne fait rien (elle reste dans la liste)
|
|
if ((float)$avance['amount_due'] <= 0 && $avance['type_avance'] === 'mere') {
|
|
log_message('info', "💰 Avance MER {$avance_id} complète ! Elle reste dans la liste des avances.");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* ✅ Générer un numéro de facture unique
|
|
*/
|
|
private function generateBillNo(int $store_id): string
|
|
{
|
|
$storePrefixes = [
|
|
1 => 'ANTS',
|
|
2 => 'BESA',
|
|
3 => 'BYPA',
|
|
4 => 'TOAM',
|
|
];
|
|
|
|
$prefix = $storePrefixes[$store_id] ?? 'STORE';
|
|
|
|
$db = \Config\Database::connect();
|
|
|
|
$lastBill = $db->table('orders')
|
|
->select('bill_no')
|
|
->like('bill_no', $prefix . '-', 'after')
|
|
->orderBy('id', 'DESC')
|
|
->limit(1)
|
|
->get()
|
|
->getRowArray();
|
|
|
|
if ($lastBill && !empty($lastBill['bill_no'])) {
|
|
preg_match('/-(\d+)$/', $lastBill['bill_no'], $matches);
|
|
$newNumber = isset($matches[1]) ? (int)$matches[1] + 1 : 1;
|
|
} else {
|
|
$newNumber = 1;
|
|
}
|
|
|
|
return $prefix . '-' . str_pad($newNumber, 3, '0', STR_PAD_LEFT);
|
|
}
|
|
/**
|
|
* ✅ Récupérer toutes les avances complètes non converties
|
|
*/
|
|
public function getCompletedNotConverted()
|
|
{
|
|
return $this->where('type_avance', 'terre')
|
|
->where('amount_due <=', 0)
|
|
->where('is_order', 0)
|
|
->where('active', 1)
|
|
->findAll();
|
|
}
|
|
|
|
|
|
/**
|
|
* ✅ NOUVELLE MÉTHODE : Récupérer les avances MER complètes (pour statistiques)
|
|
*/
|
|
public function getCompletedMerAvances()
|
|
{
|
|
$session = session();
|
|
$users = $session->get('user');
|
|
$isAdmin = in_array($users['group_name'], ['SuperAdmin', 'Direction', 'DAF']);
|
|
|
|
$builder = $this->where('amount_due', 0)
|
|
->where('active', 1)
|
|
->where('type_avance', 'mere');
|
|
|
|
if (!$isAdmin) {
|
|
$builder->where('store_id', $users['store_id']);
|
|
}
|
|
|
|
return $builder->orderBy('avance_date', 'DESC')->findAll();
|
|
}
|
|
|
|
|
|
|
|
}
|