|
- <?php
-
- namespace domain\Order\Order;
-
- use common\helpers\GlobalParam;
- use common\helpers\MeanPayment;
- use common\helpers\Price;
- use domain\Config\TaxRate\TaxRate;
- use domain\Distribution\Distribution\Distribution;
- use domain\Distribution\Distribution\DistributionRepository;
- use domain\Distribution\Distribution\DistributionSolver;
- use domain\Document\DeliveryNote\DeliveryNote;
- use domain\Document\DeliveryNote\DeliveryNoteBuilder;
- use domain\Document\Document\Document;
- use domain\Document\Document\DocumentInterface;
- use domain\Document\Document\DocumentSolver;
- use domain\Document\Invoice\Invoice;
- use domain\Order\Order\Event\OrderDeleteEvent;
- use domain\Order\OrderStatus\OrderStatus;
- use domain\Order\OrderStatus\OrderStatusRepository;
- use domain\Order\ProductOrder\ProductOrder;
- use domain\Order\ProductOrder\ProductOrderBuilder;
- use domain\Order\ProductOrder\ProductOrderSolver;
- use domain\Payment\Payment;
- use domain\Payment\PaymentBuilder;
- use domain\Payment\PaymentRepository;
- use domain\PointSale\PointSale\PointSale;
- use domain\PointSale\PointSale\PointSaleBuilder;
- use domain\PointSale\PointSale\PointSaleRepository;
- use domain\PointSale\UserPointSale\UserPointSaleRepository;
- use domain\Producer\Producer\Producer;
- use domain\Producer\Producer\ProducerRepository;
- use domain\Producer\Producer\ProducerSolver;
- use domain\Product\Product\Product;
- use domain\Product\Product\ProductRepository;
- use domain\Product\Product\ProductSolver;
- use domain\Subscription\Subscription\Subscription;
- use domain\Subscription\Subscription\SubscriptionBuilder;
- use domain\Subscription\Subscription\SubscriptionRepository;
- use domain\Subscription\Subscription\SubscriptionSolver;
- use domain\User\User\UserRepository;
- use domain\User\User\UserSolver;
- use domain\User\UserProducer\UserProducerRepository;
- use domain\_\AbstractBuilder;
- use yii\web\NotFoundHttpException;
-
- class OrderBuilder extends AbstractBuilder
- {
- protected UserSolver $userSolver;
- protected OrderSolver $orderSolver;
- protected PaymentRepository $paymentRepository;
- protected ProducerRepository $producerRepository;
- protected PaymentBuilder $paymentBuilder;
- protected ProductOrderBuilder $productOrderBuilder;
- protected OrderRepository $orderRepository;
- protected DistributionRepository $distributionRepository;
- protected SubscriptionBuilder $subscriptionBuilder;
- protected PointSaleRepository $pointSaleRepository;
- protected UserProducerRepository $userProducerRepository;
- protected UserPointSaleRepository $userPointSaleRepository;
- protected PointSaleBuilder $pointSaleBuilder;
- protected ProductOrderSolver $productOrderSolver;
- protected SubscriptionRepository $subscriptionRepository;
- protected SubscriptionSolver $subscriptionSolver;
- protected ProductSolver $productSolver;
- protected DistributionSolver $distributionSolver;
- protected UserRepository $userRepository;
- protected DeliveryNoteBuilder $deliveryNoteBuilder;
- protected DocumentSolver $documentSolver;
- protected ProducerSolver $producerSolver;
- protected OrderStatusRepository $orderStatusRepository;
- protected ProductRepository $productRepository;
-
- public function loadDependencies(): void
- {
- $this->userSolver = $this->loadService(UserSolver::class);
- $this->orderSolver = $this->loadService(OrderSolver::class);
- $this->paymentRepository = $this->loadService(PaymentRepository::class);
- $this->producerRepository = $this->loadService(ProducerRepository::class);
- $this->paymentBuilder = $this->loadService(PaymentBuilder::class);
- $this->productOrderBuilder = $this->loadService(ProductOrderBuilder::class);
- $this->orderRepository = $this->loadService(OrderRepository::class);
- $this->distributionRepository = $this->loadService(DistributionRepository::class);
- $this->subscriptionBuilder = $this->loadService(SubscriptionBuilder::class);
- $this->pointSaleRepository = $this->loadService(PointSaleRepository::class);
- $this->userProducerRepository = $this->loadService(UserProducerRepository::class);
- $this->userPointSaleRepository = $this->loadService(UserPointSaleRepository::class);
- $this->pointSaleBuilder = $this->loadService(PointSaleBuilder::class);
- $this->productOrderSolver = $this->loadService(ProductOrderSolver::class);
- $this->subscriptionRepository = $this->loadService(SubscriptionRepository::class);
- $this->subscriptionSolver = $this->loadService(SubscriptionSolver::class);
- $this->productSolver = $this->loadService(ProductSolver::class);
- $this->distributionSolver = $this->loadService(DistributionSolver::class);
- $this->userRepository = $this->loadService(UserRepository::class);
- $this->deliveryNoteBuilder = $this->loadService(DeliveryNoteBuilder::class);
- $this->documentSolver = $this->loadService(DocumentSolver::class);
- $this->producerSolver = $this->loadService(ProducerSolver::class);
- $this->orderStatusRepository = $this->loadService(OrderStatusRepository::class);
- $this->productRepository = $this->loadService(ProductRepository::class);
- }
-
- public function instanciateOrder(Distribution $distribution): Order
- {
- $order = new Order();
- $order->populateDistribution($distribution);
- $order->date = date('Y-m-d H:i:s');
- $order->id_user = 0;
-
- return $order;
- }
-
- public function createOrder(Distribution $distribution): Order
- {
- $order = $this->instanciateOrder($distribution);
-
- $this->createUserPointSale($order);
- $this->initOrderCommentPointSale($order);
- $this->generateOrderReference($order);
-
- $order->save();
-
- return $order;
- }
-
- public function instanciateOrderFromProductOrdersArray(array $productOrdersArray, Order $order = null): Order
- {
- if(!$order) {
- $order = new Order();
- $this->initOrderStatus($order);
- }
-
- $productOrderObjectArray = [];
- foreach($productOrdersArray as $idProduct => $productOrder) {
- if($productOrder['quantity']) {
- $product = $this->productRepository->findOneProductById($idProduct);
- $productOrderObject = $this->productOrderBuilder->instanciateProductOrder(
- $order,
- $product,
- $productOrder['quantity'],
- 0
- );
- $productOrderObjectArray[] = $productOrderObject;
- }
- }
-
- $order->populateRelation('productOrder', $productOrderObjectArray);
-
- return $order;
- }
-
- public function addOrUpdateOrIgnoreOrderFromArray(Order $orderOverride, array $ordersArray, bool $ignoreOrderCurrent = false): array
- {
- $override = false;
- foreach($ordersArray as $key => $order) {
- if($order->id == $orderOverride->id) {
- if($ignoreOrderCurrent) {
- unset($ordersArray[$key]);
- }
- else {
- $ordersArray[$key] = $orderOverride;
- $override = true;
- }
- }
- }
- if(!$override && !$ignoreOrderCurrent) {
- $ordersArray[] = $orderOverride;
- }
-
- return $ordersArray;
- }
-
- public function deleteProductOrderQuantity(Order $order, Product $product, float $quantity)
- {
- foreach($order->productOrder as $productOrder) {
- if($productOrder->id_product == $product->id) {
- $productOrder->quantity -= $quantity;
- }
- }
- }
-
- public function initDateUpdate(Order $order)
- {
- $order->date_update = date('Y-m-d H:i:s');;
- }
-
- public function addProductOrdersFromSubscription(Order $order, Subscription $subscription): bool
- {
- $productsAdd = false;
- $user = $subscription->user ?? null;
- foreach ($subscription->productSubscription as $productSubscription) {
-
- $this->productOrderBuilder->createProductOrder(
- $order,
- $productSubscription->product,
- $productSubscription->quantity,
- (float) $this->productSolver->getPrice($productSubscription->product, [
- 'user' => $user,
- 'point_sale' => $subscription->pointSale,
- 'quantity' => $productSubscription->quantity
- ])
- );
- $productsAdd = true;
- }
-
- return $productsAdd;
- }
-
- public function updateOrderFromSubscription(Order $order, Subscription $subscription): void
- {
- $this->initOrderBaseFromSubscription($order, $subscription);
- $this->initOrderAutoPaymentFromSubscription($order, $subscription);
- $this->addProductOrdersFromSubscription($order, $subscription);
-
- $this->update($order);
- }
-
- public function initOrderBaseFromSubscription(Order $order, Subscription $subscription): void
- {
- $order->origin = Order::ORIGIN_AUTO;
- $order->populatePointSale($subscription->pointSale);
- $order->populateSubscription($subscription);
-
- if (strlen($subscription->comment)) {
- $order->comment = $subscription->comment;
- }
-
- if (strlen($subscription->username)) {
- $order->username = $subscription->username;
- $order->id_user = 0;
- } else {
- $order->populateUser($subscription->user);
- }
- }
-
- public function initOrderAutoPaymentFromSubscription(Order $order, Subscription $subscription): void
- {
- $pointSale = $subscription->pointSale;
- if ($pointSale) {
- $creditFunctioning = $this->producerRepository->getPointSaleCreditFunctioning($pointSale);
-
- $order->auto_payment = 0;
- if ($subscription->auto_payment == Subscription::AUTO_PAYMENT_DEDUCTED) {
- if ($order->id_user && $this->producerSolver->getConfig('credit') && $pointSale->payment_method_credit) {
- if ($creditFunctioning == Producer::CREDIT_FUNCTIONING_OPTIONAL) {
- $order->auto_payment = 0;
- } elseif ($creditFunctioning == Producer::CREDIT_FUNCTIONING_MANDATORY) {
- $order->auto_payment = 1;
- } elseif ($creditFunctioning == Producer::CREDIT_FUNCTIONING_USER) {
-
- $userProducer = $this->userProducerRepository->findOneUserProducer($order->user);
-
- if ($userProducer) {
- $order->auto_payment = $userProducer->credit_active;
- }
- }
- }
- } elseif ($subscription->auto_payment == Subscription::AUTO_PAYMENT_YES) {
- $order->auto_payment = 1;
- } elseif ($subscription->auto_payment == Subscription::AUTO_PAYMENT_NO) {
- $order->auto_payment = 0;
- }
- }
-
- $order->tiller_synchronization = $order->auto_payment;
- }
-
- public function createUserPointSale(Order $order): void
- {
- if ($order->user) {
- $this->pointSaleBuilder->addUser($order->user, $order->pointSale);
- }
- }
-
- public function initOrderCommentPointSale(Order $order): void
- {
- if ($order->user && $order->pointSale) {
- $userPointSale = $this->userPointSaleRepository->findOneUserPointSale($order->user, $order->pointSale);
-
- if ($userPointSale && strlen($userPointSale->comment)) {
- $order->comment_point_sale = $userPointSale->comment;
- }
- }
- }
-
- /**
- * Initialise le montant total, le montant déjà payé et le poids de la commande.
- */
- public function initOrder(Order $order): void
- {
- $taxCalculationMethod = $this->getProducerContext()->option_tax_calculation_method;
- $this->initOrderAmount($order, $taxCalculationMethod);
- $this->initOrderPaidAmount($order);
- $this->initOrderStatus($order);
- }
-
- public function initOrderStatus(Order $order)
- {
- $orderStatusAlias = $order->getOrderStatusAlias() ?: OrderStatus::ALIAS_ORDERED;
- $orderStatus = $this->orderStatusRepository->getOrderStatusByAlias($orderStatusAlias);
- $order->setOrderStatus($orderStatus);
- }
-
- /**
- * Initialise le montant de la commande.
- */
- public function initOrderAmount(Order $order, string $taxCalculationMethod = Document::TAX_CALCULATION_METHOD_DEFAULT): void
- {
- $order->amount = 0;
- $order->amount_with_tax = 0;
- $order->amount_vat = [];
- $order->invoice_amount = 0;
- $order->invoice_amount_with_tax = 0;
- $order->invoice_amount_vat = [];
- $order->weight = 0;
-
- if (isset($order->productOrder)) {
- foreach ($order->productOrder as $productOrder) {
- $this->addProductOrderAmount($order, Order::AMOUNT_TOTAL, $productOrder, $taxCalculationMethod);
- $this->addProductOrderAmount($order, Order::INVOICE_AMOUNT_TOTAL, $productOrder, $taxCalculationMethod);
- $this->addProductOrderWeight($order, $productOrder);
- }
- }
- }
-
- public function addProductOrderWeight(Order $order, ProductOrder $productOrder): void
- {
- if ($productOrder->unit == 'piece') {
- if (isset($productOrder->product)) {
- $order->weight += ($productOrder->quantity * $productOrder->product->weight) / 1000;
- }
- } else {
- $order->weight += $productOrder->quantity;
- }
- }
-
- public function addProductOrderAmount(Order $order, string $typeTotal, ProductOrder $productOrder, string $taxCalculationMethod): void
- {
- $fieldNameAmount = $this->orderSolver->getFieldNameAmount($typeTotal);
- $fieldNameAmountWithTax = $this->orderSolver->getFieldNameAmount($typeTotal, 'with_tax');
- $price = $this->productOrderSolver->getPriceByTypeTotal($productOrder, $typeTotal);
- $order->$fieldNameAmount += $price * $productOrder->quantity;
- $order->$fieldNameAmountWithTax += Price::getPriceWithTax(
- $price,
- $productOrder->taxRate->value,
- $taxCalculationMethod
- ) * $productOrder->quantity;
- $this->addProductOrderVat($order, $typeTotal, $price * $productOrder->quantity, $productOrder->taxRate, $taxCalculationMethod);
- }
-
- public function addProductOrderVat(
- Order $order,
- string $typeTotal,
- float $priceTotalWithoutTax,
- TaxRate $taxRate,
- string $taxCalculationMethod): void
- {
- $fieldName = $this->orderSolver->getFieldNameAmount($typeTotal, 'vat');
-
- if (!isset($order->$fieldName[$taxRate->id])) {
- $order->$fieldName[$taxRate->id] = 0;
- }
-
- $order->$fieldName[$taxRate->id] += Price::getVat($priceTotalWithoutTax, $taxRate->value, $taxCalculationMethod);
- }
-
- /**
- * Initialise le montant payé de la commande et le retourne.
- */
- public function initOrderPaidAmount(Order $order): void
- {
- $history = $order->payment;
- $order->paid_amount = 0;
-
- if ($history && count($history)) {
- foreach ($order->payment as $ch) {
- if ($ch->type == Payment::TYPE_PAYMENT) {
- $order->paid_amount += $ch->amount;
- } elseif ($ch->type == Payment::TYPE_REFUND) {
- $order->paid_amount -= $ch->amount;
- }
- }
- }
- }
-
- /**
- * Ajuste le crédit pour que la commande soit payée.
- */
- public function processCredit(Order $order): void
- {
- if ($order->id_user) {
- $paymentStatus = $this->orderSolver->getPaymentStatus($order);
-
- if ($paymentStatus == Order::PAYMENT_PAID) {
- return;
- } elseif ($paymentStatus == Order::PAYMENT_SURPLUS) {
- $type = Payment::TYPE_REFUND;
- $amount = $this->orderSolver->getOrderAmount($order, Order::AMOUNT_SURPLUS);
- } elseif ($paymentStatus == Order::PAYMENT_UNPAID) {
- $type = Payment::TYPE_PAYMENT;
- $amount = $this->orderSolver->getOrderAmount($order, Order::AMOUNT_REMAINING);
- }
-
- $this->paymentBuilder->createPayment(
- $type,
- $amount,
- GlobalParam::getCurrentProducer(),
- $order->user,
- $this->userSolver->getCurrent(),
- MeanPayment::CREDIT,
- null,
- null,
- $order
- );
- }
- }
-
- public function updateOrderTillerSynchronization(Order $order, int $synchroTiller = null): void
- {
- if (!is_null($synchroTiller)) {
- $order->tiller_synchronization = $synchroTiller;
- } else {
- $amountPaid = $this->orderSolver->getOrderAmountPaidByCredit($order);
-
- if ($amountPaid >= 0.01) {
- $order->tiller_synchronization = 1;
- } else {
- $order->tiller_synchronization = 0;
- }
- }
-
- $this->saveUpdate($order);
- }
-
- // initReference
- // generateReference
- public function generateOrderReference(Order $order): void
- {
- $distribution = $this->distributionRepository->findOneDistributionById($order->id_distribution);
- $producer = $this->producerRepository->findOneProducerById($distribution->id_producer);
-
- if (!$order->reference && $producer->option_order_reference_type == Producer::ORDER_REFERENCE_TYPE_YEARLY) {
- $lastOrder = $this->orderRepository->findOneOrderLastOfYear($producer);
-
- if ($lastOrder && $lastOrder->reference && strlen($lastOrder->reference) > 0) {
- $pattern = '#A([0-9]+)C([0-9]+)#';
- preg_match($pattern, $lastOrder->reference, $matches, PREG_OFFSET_CAPTURE);
- $sizeNumReference = strlen($matches[2][0]);
- $numReference = ((int)$matches[2][0]) + 1;
- $numReference = str_pad($numReference, $sizeNumReference, '0', STR_PAD_LEFT);
-
- $order->reference = 'A' . $matches[1][0] . 'C' . $numReference;
- } else {
- $order->reference = 'A' . date('y') . 'C0001';
- }
-
- $this->saveUpdate($order);
- }
- }
-
- // initInvoicePrices
- // updateInvoicePrices
- public function updateOrderInvoicePrices(Order $order, array $params = []): void
- {
- foreach ($order->productOrder as $productOrder) {
- if ($productOrder->product) {
- $this->productOrderBuilder->updateProductOrderInvoicePrice($productOrder, $params);
- }
- }
- }
-
- /**
- * Initialise les commandes liées au point de vente.
- */
- public function initPointSaleOrders(PointSale $pointSale, array $ordersArray): void
- {
- $pointSale->orders = [];
- $pointSale->revenues = 0;
- $pointSale->revenues_with_tax = 0;
-
- if ($ordersArray) {
- foreach ($ordersArray as $order) {
- $this->initOrder($order);
-
- if ($pointSale->id == $order->id_point_sale) {
- $pointSale->orders[] = $order;
-
- if($this->orderSolver->isOrderStatusValid($order)) {
- $pointSale->revenues += (float)$order->amount;
- $pointSale->revenues_with_tax += (float)$order->amount_with_tax;
- }
- }
- }
- }
- }
-
- public function assignAllOrdersDeliveryNote(array $idOrders, DeliveryNote $deliveryNote)
- {
- $this->unassignAllOrdersDeliveryNote($deliveryNote);
-
- foreach ($idOrders as $idOrder) {
- $order = $this->orderRepository->findOneOrderById((int)$idOrder);
- if ($order) {
- $this->assignOrderDeliveryNote($order, $deliveryNote);
- }
- }
- }
-
- public function assignOrderDeliveryNote(Order $order, DeliveryNote $deliveryNote)
- {
- if ($this->orderSolver->isOrderFromProducer($order)) {
- $this->updateOrderDeliveryNote($order, $deliveryNote);
- $order = $this->orderRepository->findOneOrderById($order->id);
- $user = $this->userRepository->findOneUserById($deliveryNote->id_user);
- $userProducer = $this->userProducerRepository->findOneUserProducer($user);
- $this->updateOrderInvoicePrices($order,
- [
- 'user' => $user,
- 'user_producer' => $userProducer,
- 'point_sale' => $order->pointSale
- ]);
- }
- }
-
- public function unassignAllOrdersDeliveryNote(DeliveryNote $deliveryNote)
- {
- Order::updateAll([
- 'id_delivery_note' => null
- ], [
- 'id_delivery_note' => $deliveryNote->id
- ]);
- }
-
- public function unassignAllOrdersInvoiceByDeliveryNote(DeliveryNote $deliveryNote)
- {
- Order::updateAll([
- 'id_invoice' => null
- ], [
- 'id_delivery_note' => $deliveryNote->id
- ]);
- }
-
- public function assignAllOrdersInvoiceByDeliveryNote(Invoice $invoice, DeliveryNote $deliveryNote)
- {
- Order::updateAll([
- 'id_invoice' => $invoice->id
- ], [
- 'id_delivery_note' => $deliveryNote->id
- ]);
- }
-
- public function updateOrderIgnoreWhenInvoicing(Order $order, bool $ignoreWhenInvoicing)
- {
- $order->ignore_when_invoicing = $ignoreWhenInvoicing;
- $this->update($order);
- }
-
- public function updateOrderDocument(Order $order, DocumentInterface $document = null)
- {
- if($this->documentSolver->isDocumentInvoice($document)) {
- $this->updateOrderInvoice($order, $document);
- }
- elseif($this->documentSolver->isDocumentDeliveryNote($document)) {
- $this->updateOrderDeliveryNote($order, $document);
- }
- }
-
- public function updateOrderInvoice(Order $order, Invoice $invoice = null)
- {
- if($invoice) {
- $order->populateInvoice($invoice);
- }
- else {
- $order->id_invoice = null;
- }
-
- $this->update($order);
- }
-
- public function updateOrderDeliveryNote(Order $order, DeliveryNote $deliveryNote = null)
- {
- if($deliveryNote) {
- $order->populateDeliveryNote($deliveryNote);
- }
- else {
- $order->id_delivery_note = null;
- }
-
- $this->update($order);
- }
- }
|