'ID', 'id_user' => 'Utilisateur', 'id_producer' => 'Etablissement', 'id_point_sale' => 'Point de vente', 'date_begin' => 'Date de début', 'date_end' => 'Date de fin', 'monday' => 'Lundi', 'tuesday' => 'Mardi', 'wednesday' => 'Mercredi', 'thursday' => 'Jeudi', 'friday' => 'Vendredi', 'saturday' => 'Samedi', 'sunday' => 'Dimanche', 'week_frequency' => 'Périodicité', 'auto_payment' => 'Paiement automatique', 'comment' => 'Commentaire' ]; } /* * Relations */ public function getUser() { return $this->hasOne(User::className(), ['id' => 'id_user']); } public function getProducer() { return $this->hasOne( Producer::className(), ['id' => 'id_producer'] ); } public function getPointSale() { return $this->hasOne( PointSale::className(), ['id' => 'id_point_sale'] ); } public function getProductSubscription() { return $this->hasMany( ProductSubscription::className(), ['id_subscription' => 'id'] )->with('product'); } /** * Retourne les options de base nécessaires à la fonction de recherche. * * @return array */ public static function defaultOptionsSearch() { return [ 'with' => ['producer'], 'join_with' => ['user', 'productSubscription', 'productSubscription.product', 'pointSale'], 'orderby' => 'user.name ASC', 'attribute_id_producer' => 'subscription.id_producer' ]; } /** * Ajoute la commande pour une date donnée. * * @param string $date */ public function add($date) { // distribution $distribution = Distribution::searchOne([ 'distribution.date' => date('Y-m-d', strtotime($date)) ]); if ($distribution && count($this->productSubscription)) { // commande $order = new Order; if (strlen($this->username)) { $order->username = $this->username; $order->id_user = 0; } else { $order->id_user = $this->id_user; } $order->date = date('Y-m-d H:i:s'); $order->origin = Order::ORIGIN_AUTO; $order->id_point_sale = $this->id_point_sale; $order->id_distribution = $distribution->id; $order->id_subscription = $this->id; $order->status = 'tmp-order' ; if (strlen($this->comment)) { $order->comment = $this->comment; } $pointSale = PointSale::findOne($this->id_point_sale); $creditFunctioning = $pointSale->getCreditFunctioning(); $order->auto_payment = 0; if ($order->id_user && Producer::getConfig('credit') && $pointSale->credit) { if ($creditFunctioning == Producer::CREDIT_FUNCTIONING_OPTIONAL) { $order->auto_payment = $this->auto_payment; } elseif ($creditFunctioning == Producer::CREDIT_FUNCTIONING_MANDATORY) { $order->auto_payment = 1; } elseif ($creditFunctioning == Producer::CREDIT_FUNCTIONING_USER) { $user = User::findOne($order->id_user); $userProducer = UserProducer::searchOne([ 'id_user' => $order->id_user, 'id_producer' => $distribution->id_producer ]); if ($userProducer) { $order->auto_payment = $userProducer->credit_active; } } } $order->tiller_synchronization = $order->auto_payment ; $userPointSale = UserPointSale::searchOne([ 'id_point_sale' => $this->id_point_sale, 'id_user' => $this->id_user ]); if ($userPointSale && strlen($userPointSale->comment)) { $order->comment_point_sale = $userPointSale->comment; } $order->save(); // liaison utilisateur / point de vente if ($order->id_user) { $pointSale = PointSale::findOne($this->id_point_sale); $pointSale->linkUser($order->id_user); } // produits $amountTotal = 0; $productsAdd = false; foreach ($this->productSubscription as $productSubscription) { $productOrder = new ProductOrder; $productOrder->id_order = $order->id; $productOrder->id_product = $productSubscription->product->id; $productOrder->quantity = $productSubscription->quantity; $productOrder->price = $productSubscription->product->price; $productOrder->unit = $productSubscription->product->unit; $productOrder->step = $productSubscription->product->step; $productOrder->id_tax_rate = $productSubscription->product->taxRate->id; $productOrder->save(); $productsAdd = true; } if (!$productsAdd) { $order->delete(); } } } /** * Ajoute les commandes pour une date donnée à partir des abonnements. * * @param string $date * @param boolean $force */ public static function addAll($date, $force = false) { $distribution = Distribution::searchOne([ 'date' => date('Y-m-d', strtotime($date)), 'id_producer' => GlobalParam::getCurrentProducerId(), ]); if ($distribution) { $arrayOrdersDistribution = Order::searchAll([ Order::tableName() . '.id_distribution' => $distribution->id ]); $arraySubscriptions = self::searchByDate($date); foreach ($arraySubscriptions as $subscription) { if (!$subscription->hasOrderAlreadyExist($arrayOrdersDistribution)) { $subscription->add($date); } } } } /** * Informe s'il existe une commande correspond à l'abonnement courant. * * @param array $arrayOrders * @return boolean */ public function hasOrderAlreadyExist($arrayOrders) { if (is_array($arrayOrders) && count($arrayOrders) > 0) { foreach ($arrayOrders as $order) { if ((($order->id_user > 0 && $order->id_user == $this->id_user) || (!$order->id_user && $order->username == $this->username)) && $order->id_point_sale == $this->id_point_sale) { return true; } } } return false; } /** * Retourne les abonnements pour une date donnée. * * @param string $date * @return array */ public static function searchByDate($date) { $date = date('Y-m-d', strtotime($date)); $subscriptions = Subscription::searchAll(); $arrSubscriptions = []; foreach ($subscriptions as $s) { if ($date >= $s->date_begin && (!$s->date_end || $date <= $s->date_end) && $s->matchWith($date)) { $arrSubscriptions[] = $s; } } return $arrSubscriptions; } /** * Valide le fait qu'un abonnement est bien compatible avec une date donnée. * * @param string $date * @return boolean */ public function matchWith($date) { $arrayDays = [ 1 => 'monday', 2 => 'tuesday', 3 => 'wednesday', 4 => 'thursday', 5 => 'friday', 6 => 'saturday', 7 => 'sunday' ]; $nbDays = (strtotime($date) - strtotime($this->date_begin)) / (24 * 60 * 60); if (round($nbDays) % ($this->week_frequency * 7) < 7) { $numDay = date('N', strtotime($date)); $day = $arrayDays[$numDay]; if ($this->$day) { return true; } } return false; } /** * Recherche les distributions futures où l'abonnement peut s'appliquer. * * @return array */ public function searchMatchedIncomingDistributions() { $producer = GlobalParam::getCurrentProducer(); $params = [ ':date_earliest_order' => date('Y-m-d'), ':date_begin' => date('Y-m-d', strtotime($this->date_begin)), ':id_producer' => GlobalParam::getCurrentProducerId() ]; $incomingDistributions = Distribution::find() ->where('id_producer = :id_producer') ->andWhere('date >= :date_begin') ->andWhere('date >= :date_earliest_order'); if ($this->date_end) { $incomingDistributions->andWhere('date < :date_end'); $params[':date_end'] = date('Y-m-d', strtotime($this->date_end)); } $incomingDistributions->orderBy('date ASC'); $incomingDistributions->params($params); $incomingDistributionsArray = $incomingDistributions->all(); $incomingDistributions = Distribution::filterDistributionsByDateDelay($incomingDistributionsArray) ; $matchedIncomingDistributionsArray = []; foreach ($incomingDistributionsArray as $incomingDistribution) { if ($this->matchWith($incomingDistribution->date)) { $matchedIncomingDistributionsArray[] = $incomingDistribution; } } return $matchedIncomingDistributionsArray; } public function deleteOrdersIncomingDistributions() { $params = [ ':id_producer' => GlobalParam::getCurrentProducerId(), ':date_today' => date('Y-m-d'), ':date_begin' => $this->date_begin, ':id_subscription' => $this->id ]; $orderDeadline = Producer::getConfig('order_deadline'); $hour = date('G'); if ($hour >= $orderDeadline) { $conditionDistributionDate = 'distribution.date > :date_today'; } else { $conditionDistributionDate = 'distribution.date >= :date_today'; } $orders = Order::find() ->joinWith('distribution') ->where('distribution.id_producer = :id_producer') ->andWhere($conditionDistributionDate) ->andWhere('distribution.date >= :date_begin') ->andWhere('order.id_subscription = :id_subscription'); if ($this->date_end) { $orders->andWhere('distribution.date <= :date_end'); $params[':date_end'] = $this->date_end; } $orders->params($params); $ordersArray = $orders->all(); $configCredit = Producer::getConfig('credit'); if ($ordersArray && count($ordersArray)) { foreach ($ordersArray as $order) { $theOrder = Order::searchOne(['id' => $order->id]); // remboursement de la commande if ($theOrder->id_user && $theOrder->getAmount(Order::AMOUNT_PAID) && $configCredit) { $theOrder->saveCreditHistory( CreditHistory::TYPE_REFUND, $theOrder->getAmount(Order::AMOUNT_PAID), $theOrder->distribution->id_producer, $theOrder->id_user, User::getCurrentId() ); } ProductOrder::deleteAll(['id_order' => $order->id]); $order->delete(); } } } public function updateIncomingDistributions($update = false) { $matchedDistributionsArray = $this->searchMatchedIncomingDistributions(); if ($update) { $this->deleteOrdersIncomingDistributions(); } if (count($matchedDistributionsArray)) { foreach ($matchedDistributionsArray as $distribution) { $this->add($distribution->date); } } } }