Parcourir la source

[Administration] Documents > Factures : génération sur base des commandes #1218

feature/souke
Guillaume Bourgeois il y a 1 an
Parent
révision
a97d3a35d1
7 fichiers modifiés avec 238 ajouts et 76 suppressions
  1. +21
    -0
      backend/controllers/DocumentController.php
  2. +42
    -30
      backend/controllers/InvoiceController.php
  3. +92
    -43
      backend/views/document/_form.php
  4. +35
    -1
      backend/web/js/vuejs/document-form.js
  5. +22
    -0
      common/logic/Order/Order/Repository/OrderRepository.php
  6. +16
    -0
      common/logic/Order/Order/Repository/OrderRepositoryQuery.php
  7. +10
    -2
      common/logic/Order/Order/Service/OrderBuilder.php

+ 21
- 0
backend/controllers/DocumentController.php Voir le fichier

@@ -376,6 +376,7 @@ class DocumentController extends BackendController
{
$userManager = $this->getUserManager();
$documentManager = $this->getDocumentManager();
$orderManager = $this->getOrderManager();

\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

@@ -417,6 +418,9 @@ class DocumentController extends BackendController
], $options);
$json['delivery_note_create_array'] = $this->initDeliveryNoteArray('create', $deliveryNotesCreateArray);
$json['delivery_note_update_array'] = $this->initDeliveryNoteArray('update', $deliveryNotesUpdateArray);

$json['orders_create_array'] = $this->initOrdersArray($orderManager->findOrdersByUserNotInvoiced($user));
$json['orders_update_array'] = $this->initOrdersArray($orderManager->findOrdersByUserAndInvoice($user, $document));
}

return $json;
@@ -426,6 +430,23 @@ class DocumentController extends BackendController
return ['return' => 'error'];
}

public function initOrdersArray(array $ordersArray)
{
$orderManager = $this->getOrderManager();
$ordersReturnArray = [];

foreach($ordersArray as &$order) {
$orderManager->initOrder($order);
$ordersReturnArray[] = [
'id' => $order->id,
'date' => $order->distribution->date,
'amount_with_tax' => $order->invoice_amount_with_tax
];
}

return $ordersReturnArray;
}

public function initDeliveryNoteArray($type, $deliveryNoteArrayResults)
{
$deliveryNoteArray = [];

+ 42
- 30
backend/controllers/InvoiceController.php Voir le fichier

@@ -38,6 +38,7 @@

namespace backend\controllers;

use common\helpers\Ajax;
use common\logic\Document\Invoice\Model\InvoiceSearch;
use common\logic\Order\Order\Model\Order;

@@ -59,8 +60,6 @@ class InvoiceController extends DocumentController

public function actionAjaxDeleteDeliveryNote($idInvoice, $idDeliveryNote)
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

$invoiceManager = $this->getInvoiceManager();

$invoice = $invoiceManager->findOneInvoiceById($idInvoice);
@@ -71,27 +70,14 @@ class InvoiceController extends DocumentController
], [
'id_delivery_note' => $idDeliveryNote
]);

return [
'alert' => [
'type' => 'success',
'message' => 'Bon de livraison supprimé de la facture.'
]
];
return Ajax::responseSuccess('Bon de livraison supprimé de la facture.');
} else {
return [
'alert' => [
'type' => 'error',
'message' => 'Une erreur est survenue lors de la suppression du bon de livraison.'
]
];
return Ajax::responseError('Une erreur est survenue lors de la suppression du bon de livraison.');
}
}

public function actionAjaxAddDeliveryNote($idInvoice, $idDeliveryNote)
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

$invoiceManager = $this->getInvoiceManager();
$deliveryNoteManager = $this->getDeliveryNoteManager();

@@ -104,21 +90,47 @@ class InvoiceController extends DocumentController
], [
'id_delivery_note' => $idDeliveryNote
]);

return [
'alert' => [
'type' => 'success',
'message' => 'Bon de livraison ajouté à la facture.'
]
];
return Ajax::responseSuccess("Bon de livraison ajouté à la facture.");
} else {
return [
'alert' => [
'type' => 'error',
'message' => 'Une erreur est survenue lors de l\'ajout du bon de livraison.'
]
];
return Ajax::responseError("Une erreur est survenue lors de l'ajout du bon de livraison.");
}
}

public function actionAjaxAddOrder($idInvoice, $idOrder)
{
$invoiceManager = $this->getInvoiceManager();
$orderManager = $this->getOrderManager();

$invoice = $invoiceManager->findOneInvoiceById($idInvoice);
$order = $orderManager->findOneOrderById($idOrder);

if ($invoice && $invoiceManager->isStatusDraft($invoice) && $order) {
$order->id_invoice = $idInvoice;
$order->update();

return Ajax::responseSuccess("Commande ajoutée à la facture.");
}
else {
return Ajax::responseError("Une erreur est survenue lors de l'ajout de la commande.");
}
}

public function actionAjaxDeleteOrder($idInvoice, $idOrder)
{
$invoiceManager = $this->getInvoiceManager();
$orderManager = $this->getOrderManager();

$invoice = $invoiceManager->findOneInvoiceById($idInvoice);
$order = $orderManager->findOneOrderById($idOrder);

if ($invoice && $invoiceManager->isStatusDraft($invoice)) {
$order->id_invoice = null;
$order->update();

return Ajax::responseSuccess('Commande supprimée de la facture.');
}
else {
return Ajax::responseError('Une erreur est survenue lors de la suppression de la commande.');
}
}
}

+ 92
- 43
backend/views/document/_form.php Voir le fichier

@@ -124,49 +124,6 @@ $documentClass = $documentManager->getClass($model);
<?php ActiveForm::end(); ?>
</div>
</div>

<?php if ($action == 'update' && $documentClass == 'Invoice'): ?>
<div class="panel panel-default">
<div class="panel-heading">
Bons de livraison
</div>
<div class="panel-body">
<table v-if="deliveryNoteUpdateArray && deliveryNoteUpdateArray.length > 0" class="table table-bordered">
<thead>
<tr>
<th>Libellé</th>
<th v-if="taxRateProducer != 0">Montant (TTC)</th>
<th v-else>Montant</th>
<th v-if="document.status == 'draft'"></th>
</tr>
</thead>
<tbody>
<tr v-for="deliveryNote in deliveryNoteUpdateArray">
<td><a :href="deliveryNote.url">{{ deliveryNote.name }}</a></td>
<td>{{ formatPrice(deliveryNote.total) }}</td>
<td v-if="document.status == 'draft'"><a class="btn btn-default" href="javascript:void(0);" @click="deleteDeliveryNoteOfInvoice" :data-id="deliveryNote.id"><span class="glyphicon glyphicon-trash"></span></a></td>
</tr>
</tbody>
</table>
<div v-else class="alert alert-warning">Aucun bon de livraison associé.</div>

<div v-if="document.status == 'draft'" id="delivery-note-add">
<div class="col-md-8">
<select class="form-control" v-model="deliveryNoteAddId">
<option value="0" selected="selected">--</option>
<option v-for="deliveryNote in deliveryNoteCreateArray" :value="deliveryNote.id">
{{ deliveryNote.name }}
</option>
</select>
</div>
<div class="col-md-4">
<button class="btn btn-primary" value="Ajouter" @click="submitDeliveryNoteAddToInvoice">Ajouter</button>
</div>
</div>
</div>
</div>
<?php endif; ?>

</div>

<?php if ($action == 'update'): ?>
@@ -245,6 +202,98 @@ $documentClass = $documentManager->getClass($model);
</div>
<div class="clr"></div>

<?php if ($action == 'update' && $documentClass == 'Invoice'): ?>
<div class="row">
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
Bons de livraison
</div>
<div class="panel-body">
<table v-if="deliveryNoteUpdateArray && deliveryNoteUpdateArray.length > 0" class="table table-bordered">
<thead>
<tr>
<th>Libellé</th>
<th v-if="taxRateProducer != 0">Montant (TTC)</th>
<th v-else>Montant</th>
<th v-if="document.status == 'draft'"></th>
</tr>
</thead>
<tbody>
<tr v-for="deliveryNote in deliveryNoteUpdateArray">
<td><a :href="deliveryNote.url">{{ deliveryNote.name }}</a></td>
<td>{{ formatPrice(deliveryNote.total) }}</td>
<td v-if="document.status == 'draft'"><a class="btn btn-default" href="javascript:void(0);" @click="deleteDeliveryNoteFromInvoice" :data-id="deliveryNote.id"><span class="glyphicon glyphicon-trash"></span></a></td>
</tr>
</tbody>
</table>
<div v-else class="alert alert-warning">Aucun bon de livraison associé.</div>

<div v-if="document.status == 'draft'" id="delivery-note-add">
<div class="col-md-8">
<select class="form-control" v-model="deliveryNoteAddId">
<option value="0" selected="selected">--</option>
<option v-for="deliveryNote in deliveryNoteCreateArray" :value="deliveryNote.id">
{{ deliveryNote.name }}
</option>
</select>
</div>
<div class="col-md-4">
<button class="btn btn-primary" value="Ajouter" @click="submitDeliveryNoteAddToInvoice">Ajouter</button>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
Commandes
</div>
<div class="panel-body">
<table v-if="ordersUpdateArray && ordersUpdateArray.length > 0" class="table table-bordered">
<thead>
<tr>
<th>Libellé</th>
<th v-if="taxRateProducer != 0">Montant (TTC)</th>
<th v-else>Montant</th>
<th v-if="document.status == 'draft'"></th>
</tr>
</thead>
<tbody>
<tr v-for="order in ordersUpdateArray">
<td>{{ order.date }}</td>
<td>{{ formatPrice(order.amount_with_tax) }}</td>
<td v-if="document.status == 'draft'">
<a class="btn btn-default" href="javascript:void(0);" @click="deleteOrderFromInvoice" :data-id="order.id">
<span class="glyphicon glyphicon-trash"></span>
</a>
</td>
</tr>
</tbody>
</table>
<div v-else class="alert alert-warning">Aucune commande associée.</div>

<div v-if="document.status == 'draft'" id="order-add">
<div class="col-md-8">
<select class="form-control" v-model="orderAddId">
<option value="0" selected="selected">--</option>
<option v-for="order in ordersCreateArray" :value="order.id">
{{ order.date }}
</option>
</select>
</div>
<div class="col-md-4">
<button class="btn btn-primary" value="Ajouter" @click="submitOrderAddToInvoice">Ajouter</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="clr"></div>
<?php endif; ?>

<div class="">
<div class="panel panel-default" id="block-add-product">
<div class="panel-heading">

+ 35
- 1
backend/web/js/vuejs/document-form.js Voir le fichier

@@ -42,6 +42,9 @@ var app = new Vue({
deliveryNoteCreateArray: [],
deliveryNoteUpdateArray: [],
deliveryNoteAddId: 0,
ordersCreateArray: [],
ordersUpdateArray: [],
orderAddId: 0,
idDocument: 0,
typeDocument: '',
idUser: '',
@@ -143,6 +146,8 @@ var app = new Vue({
Vue.set(app.document, 'address', response.data.address);
app.deliveryNoteCreateArray = response.data.delivery_note_create_array;
app.deliveryNoteUpdateArray = response.data.delivery_note_update_array;
app.ordersCreateArray = response.data.orders_create_array;
app.ordersUpdateArray = response.data.orders_update_array;
} else {
app.document.address = '';
}
@@ -161,7 +166,7 @@ var app = new Vue({
app.init();
});
},
deleteDeliveryNoteOfInvoice: function(event) {
deleteDeliveryNoteFromInvoice: function(event) {
var app = this;
var idDeliveryNote = event.currentTarget.getAttribute('data-id');

@@ -190,6 +195,35 @@ var app = new Vue({
app.init();
});
},
submitOrderAddToInvoice: function() {
var app = this;
axios.get(UrlManager.getBaseUrlAbsolute() + "invoice/ajax-add-order", {
params: {
idInvoice: this.getDocumentId(),
idOrder: app.orderAddId,
}
})
.then(function (response) {
appAlerts.alertResponse(response);
app.deliveryNoteAddId = 0;
app.init();
});
},
deleteOrderFromInvoice: function() {
var app = this;
var idOrder = event.currentTarget.getAttribute('data-id');

axios.get(UrlManager.getBaseUrlAbsolute() + "invoice/ajax-delete-order", {
params: {
idInvoice: app.getDocumentId(),
idOrder: idOrder
}
})
.then(function (response) {
appAlerts.alertResponse(response);
app.init();
});
},
getStepProductAdd: function () {
var step = parseInt(this.getProductById(this.productAddId).step);
if(!step) {

+ 22
- 0
common/logic/Order/Order/Repository/OrderRepository.php Voir le fichier

@@ -8,6 +8,7 @@ use common\logic\AbstractRepository;
use common\logic\Distribution\Distribution\Model\Distribution;
use common\logic\Distribution\Distribution\Repository\DistributionRepository;
use common\logic\Distribution\ProductDistribution\Repository\ProductDistributionRepository;
use common\logic\Document\Invoice\Model\Invoice;
use common\logic\Order\Order\Model\Order;
use common\logic\Order\Order\Service\OrderSolver;
use common\logic\Order\ProductOrder\Repository\ProductOrderRepository;
@@ -113,6 +114,27 @@ class OrderRepository extends AbstractRepository
->find();
}

public function findOrdersByUserAndInvoice(User $user, Invoice $invoice)
{
return $this
->createDefaultQuery()
->filterByUser($user)
->filterIsInvoiced($invoice)
->filterIsValid()
->find();
}

public function findOrdersByUserNotInvoiced(User $user)
{
return $this
->createDefaultQuery()
->filterByUser($user)
->filterIsNotInvoiced()
->filterIsPassed()
->filterIsValid()
->find();
}

public function queryOrdersHistory(Producer $producer, User $user)
{
$queryIncoming = clone $this->createDefaultQuery()

+ 16
- 0
common/logic/Order/Order/Repository/OrderRepositoryQuery.php Voir le fichier

@@ -3,6 +3,7 @@
namespace common\logic\Order\Order\Repository;

use common\logic\AbstractRepositoryQuery;
use common\logic\Document\Invoice\Model\Invoice;
use common\logic\Order\Order\Service\OrderDefinition;
use common\logic\User\User\Model\User;

@@ -74,4 +75,19 @@ class OrderRepositoryQuery extends AbstractRepositoryQuery

return $this;
}

public function filterIsInvoiced(Invoice $invoice): self
{
$this->andWhere('order.id_invoice IS NOT NULL AND order.id_invoice = :id_invoice')
->params([':id_invoice' => $invoice->id]);

return $this;
}

public function filterIsNotInvoiced(): self
{
$this->andWhere('order.id_invoice IS NULL');

return $this;
}
}

+ 10
- 2
common/logic/Order/Order/Service/OrderBuilder.php Voir le fichier

@@ -337,17 +337,25 @@ class OrderBuilder extends AbstractBuilder
/**
* Initialise le montant total, le montant déjà payé et le poids de la commande.
*/
// init
public function initOrder(Order $order, string $taxCalculationMethod = Document::TAX_CALCULATION_METHOD_DEFAULT): void
{
// @TODO : récupérer le bon taxCalculationMethod
//$taxCalculationMethod = Document::TAX_CALCULATION_METHOD_SUM_OF_ROUNDINGS;

$this->initOrderAmount($order, $taxCalculationMethod);
$this->initOrderPaidAmount($order);

// @TODO : faire le bon calcul pour la TVA
/*$totalVat = 0;
foreach($order->invoice_amount_vat as $vat) {
$totalVat += $vat;
}
$order->invoice_amount_with_tax = Price::round($order->invoice_amount + $totalVat);*/
}

/**
* Initialise le montant de la commande.
*/
// initAmount
public function initOrderAmount(Order $order, string $taxCalculationMethod = Document::TAX_CALCULATION_METHOD_DEFAULT): void
{
$order->amount = 0;

Chargement…
Annuler
Enregistrer