Browse Source

[Administration] Factures > édition : gestion des modification de prix facturés

feature/souke
Guillaume Bourgeois 9 months ago
parent
commit
1e0eec7aed
8 changed files with 168 additions and 72 deletions
  1. +15
    -2
      backend/controllers/DocumentController.php
  2. +27
    -12
      backend/views/document/_form.php
  3. +21
    -7
      backend/web/css/screen.css
  4. +27
    -1
      backend/web/js/vuejs/document-form.js
  5. +62
    -40
      backend/web/sass/document/_form.scss
  6. +7
    -6
      common/helpers/Ajax.php
  7. +8
    -3
      common/logic/Order/ProductOrder/Service/ProductOrderBuilder.php
  8. +1
    -1
      common/logic/Order/ProductOrder/Service/ProductOrderSolver.php

+ 15
- 2
backend/controllers/DocumentController.php View File



foreach ($order->productOrder as $productOrder) { foreach ($order->productOrder as $productOrder) {
$productsOrderArray[$productOrder->id] = array_merge($productOrder->getAttributes(), [ $productsOrderArray[$productOrder->id] = array_merge($productOrder->getAttributes(), [
'url_product' => $this->getUrlManagerBackend()->createUrl(['product/update', 'id' => $productOrder->id_product]),
'url_order' => $this->getUrlManagerBackend()->createUrl(['distribution/index', 'idOrderUpdate' => $productOrder->id_order]) 'url_order' => $this->getUrlManagerBackend()->createUrl(['distribution/index', 'idOrderUpdate' => $productOrder->id_order])
]); ]);
} }
public function actionAjaxDeleteProductOrder($idProductOrder) public function actionAjaxDeleteProductOrder($idProductOrder)
{ {
$productOrderModule = $this->getProductOrderModule(); $productOrderModule = $this->getProductOrderModule();

$productOrder = $productOrderModule->findOneProductOrderById($idProductOrder); $productOrder = $productOrderModule->findOneProductOrderById($idProductOrder);


if ($productOrder) { if ($productOrder) {
$productOrderModule->delete($productOrder); $productOrderModule->delete($productOrder);

return Ajax::responseSuccess('Produit supprimé'); return Ajax::responseSuccess('Produit supprimé');
} }


} }
} }


public function actionAjaxUpdateProductOrderInvoicePrice($idProductOrder, $invoicePrice)
{
$productOrderModule = $this->getProductOrderModule();
$productOrder = $productOrderModule->getRepository()->findOneProductOrderById((int) $idProductOrder);
if($productOrder) {
$productOrderModule->getBuilder()->updateProductOrderInvoicePriceByValue($productOrder, (float) $invoicePrice);
return Ajax::responseSuccess("Prix mis à jour", [
'invoice_price' => $productOrder->invoice_price
]);
}

return Ajax::responseError("Une erreur est survenue.");
}

public function getClass() public function getClass()
{ {
$class = get_class($this); $class = get_class($this);

+ 27
- 12
backend/views/document/_form.php View File

class="btn btn-sm btn-default"><span class="glyphicon glyphicon-download-alt"></span> Télécharger class="btn btn-sm btn-default"><span class="glyphicon glyphicon-download-alt"></span> Télécharger
(PDF)</a> (PDF)</a>


<?php if ($documentModule->isStatusValid($model)): ?>
<a href="<?= Yii::$app->urlManager->createUrl([Yii::$app->controller->getControllerUrl() . '/regenerate', 'id' => $model->id]) ?>"
class="btn btn-sm btn-default"><span class="glyphicon glyphicon-repeat"></span> Regénérer
(PDF)</a>
<?php endif; ?>

<?php if ($documentClass == 'Invoice' && $producerModule->getConfig('option_export_evoliz')): ?> <?php if ($documentClass == 'Invoice' && $producerModule->getConfig('option_export_evoliz')): ?>
<a href="<?= Yii::$app->urlManager->createUrl([Yii::$app->controller->getControllerUrl() . '/export-csv-evoliz', 'id' => $model->id]) ?>" <a href="<?= Yii::$app->urlManager->createUrl([Yii::$app->controller->getControllerUrl() . '/export-csv-evoliz', 'id' => $model->id]) ?>"
class="btn btn-sm btn-default"><span class="glyphicon glyphicon-save-file"></span> Export Evoliz class="btn btn-sm btn-default"><span class="glyphicon glyphicon-save-file"></span> Export Evoliz
href="<?= Yii::$app->urlManager->createUrl([Yii::$app->controller->getControllerUrl() . '/validate', 'id' => $model->id, 'backUpdateForm' => 1]) ?>" href="<?= Yii::$app->urlManager->createUrl([Yii::$app->controller->getControllerUrl() . '/validate', 'id' => $model->id, 'backUpdateForm' => 1]) ?>"
class="btn btn-sm btn-default"><span class="glyphicon glyphicon-ok"></span> Valider le document</a> class="btn btn-sm btn-default"><span class="glyphicon glyphicon-ok"></span> Valider le document</a>


<?php if ($documentModule->isStatusValid($model)): ?>
<a href="<?= Yii::$app->urlManager->createUrl([Yii::$app->controller->getControllerUrl() . '/regenerate', 'id' => $model->id]) ?>"
class="btn btn-sm btn-default"><span class="glyphicon glyphicon-repeat"></span> Regénérer
(PDF)</a>
<?php endif; ?>

<?php if (isset($model->user) && strlen($model->user->email) > 0): ?> <?php if (isset($model->user) && strlen($model->user->email) > 0): ?>
<a v-if="!document.is_sent" <a v-if="!document.is_sent"
href="<?= Yii::$app->urlManager->createUrl([Yii::$app->controller->getControllerUrl() . '/send', 'id' => $model->id, 'backUpdateForm' => 1]) ?>" href="<?= Yii::$app->urlManager->createUrl([Yii::$app->controller->getControllerUrl() . '/send', 'id' => $model->id, 'backUpdateForm' => 1]) ?>"
<template v-for="order in ordersArray"> <template v-for="order in ordersArray">
<tr v-for="productOrder in order.productOrder"> <tr v-for="productOrder in order.productOrder">
<td class="col-md-4"> <td class="col-md-4">
<div class="product-name">{{ getProductById(productOrder.id_product).name }}
<div class="product-name">
<a :href="productOrder.url_product" target="_blank">
{{ getProductById(productOrder.id_product).name }}
</a>
</div> </div>
<ul class="product-order-meta"> <ul class="product-order-meta">
<li v-if="order.distribution_date">Commande : <a class="btn btn-sm btn-default"
:href="productOrder.url_order">{{
<li v-if="order.distribution_date">Commande : <a :href="productOrder.url_order">{{
order.distribution_date }}</a></li> order.distribution_date }}</a></li>
<li>Utilisateur : {{ order.username }}</li> <li>Utilisateur : {{ order.username }}</li>
<li v-if="order.point_sale_name">Point de vente : {{ order.point_sale_name }}</li> <li v-if="order.point_sale_name">Point de vente : {{ order.point_sale_name }}</li>
</ul> </ul>
</td> </td>
<td class="col-md-2"> <td class="col-md-2">
{{ formatPrice(getProductOrderPrice(productOrder)) }}
<template v-if="document.status == 'draft'">
<div class="input-group input-group-edit-invoice-price">
<input type="text" class="form-control" :id="'input-product-order-invoice-price-'+productOrder.id" :value="getProductOrderPrice(productOrder)" :data-id-product-order="productOrder.id" @keyup="showProductOrderInvoicePriceButtonApply" />
<span class="input-group-addon">€</span>
</div>
<div class="product-order-invoice-price-button-apply" :id="'product-order-invoice-price-button-apply-'+productOrder.id">
<button class="btn btn-success" type="button" :data-id-product-order="productOrder.id" @click="updateProductOrderInvoicePrice">
<span class="glyphicon glyphicon-ok"></span>
</button>
</div>
</template>
<template v-else>
{{ formatPrice(getProductOrderPrice(productOrder)) }}
</template>
<template <template
v-if="document.status == 'draft' && getProductOrderPrice(productOrder) != getBestProductPrice(productOrder.id_product, productOrder.quantity)"> v-if="document.status == 'draft' && getProductOrderPrice(productOrder) != getBestProductPrice(productOrder.id_product, productOrder.quantity)">
<i class="fa fa-exclamation-triangle"
title="Prix différent de celui défini au niveau du produit"></i>
<i class="different-price fa fa-exclamation-triangle"
:title="'Prix différent de celui défini au niveau du produit ('+getBestProductPrice(productOrder.id_product, productOrder.quantity)+' €)'"></i>
</template> </template>
</td> </td>
<td class="col-md-2">{{ productOrder.quantity }}</td> <td class="col-md-2">{{ productOrder.quantity }}</td>

+ 21
- 7
backend/web/css/screen.css View File

.document-form .info-box .info-box-text { .document-form .info-box .info-box-text {
font-size: 13px; font-size: 13px;
} }
/* line 7, ../sass/document/_form.scss */
/* line 8, ../sass/document/_form.scss */
.document-form .info-box .info-box-number { .document-form .info-box .info-box-number {
font-size: 15px; font-size: 15px;
} }
/* line 12, ../sass/document/_form.scss */
/* line 14, ../sass/document/_form.scss */
.document-form #block-add-product .input-price { .document-form #block-add-product .input-price {
text-align: center; text-align: center;
} }
/* line 16, ../sass/document/_form.scss */
/* line 19, ../sass/document/_form.scss */
.document-form #block-add-product .input-group-quantity .input-quantity { .document-form #block-add-product .input-group-quantity .input-quantity {
text-align: center; text-align: center;
} }
/* line 22, ../sass/document/_form.scss */
/* line 25, ../sass/document/_form.scss */
.document-form #block-add-product .total .input-group { .document-form #block-add-product .total .input-group {
margin-bottom: 10px; margin-bottom: 10px;
} }
/* line 25, ../sass/document/_form.scss */
/* line 29, ../sass/document/_form.scss */
.document-form #block-add-product .total .btn { .document-form #block-add-product .total .btn {
float: right; float: right;
} }
/* line 32, ../sass/document/_form.scss */
/* line 36, ../sass/document/_form.scss */
.document-form #block-list-products ul.product-order-meta { .document-form #block-list-products ul.product-order-meta {
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
padding-left: 20px; padding-left: 20px;
} }
/* line 37, ../sass/document/_form.scss */
/* line 41, ../sass/document/_form.scss */
.document-form #block-list-products ul.product-order-meta li { .document-form #block-list-products ul.product-order-meta li {
color: gray; color: gray;
font-size: 11px; font-size: 11px;
} }
/* line 51, ../sass/document/_form.scss */
.document-form #block-list-products .product-order-invoice-price-button-apply {
display: none;
}
/* line 54, ../sass/document/_form.scss */
.document-form #block-list-products .product-order-invoice-price-button-apply .btn {
display: block;
width: 100%;
}
/* line 60, ../sass/document/_form.scss */
.document-form #block-list-products .different-price {
position: relative;
top: 5px;
}


/* line 7, ../sass/document/_index.scss */ /* line 7, ../sass/document/_index.scss */
.quotation-index .content-wrapper .content table.table .column-actions, .quotation-index .content-wrapper .content table.table .column-actions,

+ 27
- 1
backend/web/js/vuejs/document-form.js View File

var price = 0; var price = 0;
if (documentClass == 'DeliveryNote' || documentClass == 'Invoice') { if (documentClass == 'DeliveryNote' || documentClass == 'Invoice') {
price = productOrder.invoice_price; price = productOrder.invoice_price;
if (!price) {
if (isNaN(price) || price === null) {
price = productOrder.price; price = productOrder.price;
} }
} else { } else {
if (isNaN(this.productAddQuantity)) { if (isNaN(this.productAddQuantity)) {
this.productAddQuantity = 1; this.productAddQuantity = 1;
} }
},
showProductOrderInvoicePriceButtonApply: function(event) {
if(event.key == 'Enter') {
this.updateProductOrderInvoicePrice(event);
}
else {
var idProductOrder = event.currentTarget.getAttribute('data-id-product-order');
$('#product-order-invoice-price-button-apply-'+idProductOrder).show();
}
},
updateProductOrderInvoicePrice: function (event) {
var idProductOrder = event.currentTarget.getAttribute('data-id-product-order');
var invoicePrice = $('#input-product-order-invoice-price-'+idProductOrder).val();

axios.get(UrlManager.getBaseUrlAbsolute() + "document/ajax-update-product-order-invoice-price", {
params: {
idProductOrder: idProductOrder,
invoicePrice: invoicePrice
}
})
.then(function (response) {
appAlerts.alertResponse(response);
$('#input-product-order-invoice-price-'+idProductOrder).val(response.data.datas.invoice_price);
$('#product-order-invoice-price-button-apply-'+idProductOrder).hide();
app.init();
});
} }
} }
}); });

+ 62
- 40
backend/web/sass/document/_form.scss View File



.document-form { .document-form {
.info-box {
.info-box-text {
font-size: 13px ;
}
.info-box-number {
font-size: 15px ;
}
}
#block-add-product {
.input-price {
text-align: center ;
}
.input-group-quantity {
.input-quantity {
text-align: center ;
}
}

.total {
.input-group {
margin-bottom: 10px ;
}
.btn {
float: right ;
}
}
}

#block-list-products {
ul.product-order-meta {
padding: 0px ;
margin: 0px ;
padding-left: 20px ;

li {
color: gray ;
font-size: 11px ;
}
}
}
.info-box {
.info-box-text {
font-size: 13px;
}

.info-box-number {
font-size: 15px;
}
}

#block-add-product {
.input-price {
text-align: center;
}

.input-group-quantity {
.input-quantity {
text-align: center;
}
}

.total {
.input-group {
margin-bottom: 10px;
}

.btn {
float: right;
}
}
}

#block-list-products {
ul.product-order-meta {
padding: 0px;
margin: 0px;
padding-left: 20px;

li {
color: gray;
font-size: 11px;
}
}

.input-group-edit-invoice-price {

}

.product-order-invoice-price-button-apply {
display: none;

.btn {
display: block;
width: 100%;
}
}

.different-price {
position: relative;
top: 5px;
}
}
} }

+ 7
- 6
common/helpers/Ajax.php View File

const RESPONSE_TYPE_ERROR = 'error'; const RESPONSE_TYPE_ERROR = 'error';
const RESPONSE_TYPE_SUCCESS = 'success'; const RESPONSE_TYPE_SUCCESS = 'success';


public static function responseSuccess(string $message): array
public static function responseSuccess(string $message, array $datas = []): array
{ {
return self::response(self::RESPONSE_TYPE_SUCCESS, $message);
return self::response(self::RESPONSE_TYPE_SUCCESS, $message, $datas);
} }


public static function responseError(string $message): array
public static function responseError(string $message, array $datas = []): array
{ {
return self::response(self::RESPONSE_TYPE_ERROR, $message);
return self::response(self::RESPONSE_TYPE_ERROR, $message, $datas);
} }


private static function response(string $responseType, string $message): array
private static function response(string $responseType, string $message, array $datas = []): array
{ {
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;


'alert' => [ 'alert' => [
'type' => self::getAlertClass($responseType), 'type' => self::getAlertClass($responseType),
'message' => $message 'message' => $message
]
],
'datas' => $datas
]; ];
} }



+ 8
- 3
common/logic/Order/ProductOrder/Service/ProductOrderBuilder.php View File

'quantity' => $quantity 'quantity' => $quantity
]); ]);


$this->saveUpdate($productOrder);
$this->update($productOrder);


return $productOrder; return $productOrder;
} }


public function updateProductOrderInvoicePrice(ProductOrder $productOrder, array $params = []): void public function updateProductOrderInvoicePrice(ProductOrder $productOrder, array $params = []): void
{ {

$productOrder->invoice_price = $this->productSolver->getPrice($productOrder->product, [ $productOrder->invoice_price = $this->productSolver->getPrice($productOrder->product, [
'user' => (isset($params['user']) && $params['user']) ? $params['user'] : null, 'user' => (isset($params['user']) && $params['user']) ? $params['user'] : null,
'user_producer' => (isset($params['user_producer']) && $params['user_producer']) ? $params['user_producer'] : null, 'user_producer' => (isset($params['user_producer']) && $params['user_producer']) ? $params['user_producer'] : null,
'point_sale' => (isset($params['point_sale']) && $params['point_sale']) ? $params['point_sale'] : null, 'point_sale' => (isset($params['point_sale']) && $params['point_sale']) ? $params['point_sale'] : null,
'quantity' => $productOrder->quantity 'quantity' => $productOrder->quantity
]); ]);
$this->saveUpdate($productOrder);
$this->update($productOrder);
}

public function updateProductOrderInvoicePriceByValue(ProductOrder $productOrder, float $invoicePrice)
{
$productOrder->invoice_price = $invoicePrice;
$this->update($productOrder);
} }


public function deleteProductOrdersByOrder(Order $order): void public function deleteProductOrdersByOrder(Order $order): void

+ 1
- 1
common/logic/Order/ProductOrder/Service/ProductOrderSolver.php View File



public function getPriceByTypeTotal(ProductOrder $productOrder, string $typeTotal = Order::AMOUNT_TOTAL) public function getPriceByTypeTotal(ProductOrder $productOrder, string $typeTotal = Order::AMOUNT_TOTAL)
{ {
if ($typeTotal == Order::INVOICE_AMOUNT_TOTAL && $productOrder->invoice_price) {
if ($typeTotal == Order::INVOICE_AMOUNT_TOTAL && $productOrder->invoice_price !== null) {
return $productOrder->invoice_price; return $productOrder->invoice_price;
} }



Loading…
Cancel
Save