Browse Source

Modification d'un document : affichage des informations relatives au document, ajout et liste des produits #166

refactoring
Guillaume Bourgeois 5 years ago
parent
commit
65c31530ba
9 changed files with 341 additions and 32 deletions
  1. +87
    -3
      backend/controllers/DocumentController.php
  2. +139
    -17
      backend/views/document/_form.php
  3. +17
    -0
      backend/web/css/screen.css
  4. +48
    -3
      backend/web/js/vuejs/document-form.js
  5. +21
    -0
      backend/web/sass/document/_form.scss
  6. +2
    -1
      backend/web/sass/screen.scss
  7. +5
    -5
      common/models/Document.php
  8. +2
    -3
      common/models/Order.php
  9. +20
    -0
      console/migrations/m200109_070952_module_devis_bl_factures_champs_order_valeur_default.php

+ 87
- 3
backend/controllers/DocumentController.php View File

@@ -38,8 +38,11 @@

namespace backend\controllers;

use common\models\Product;
use common\models\User ;
use common\models\Document ;
use common\helpers\GlobalParam ;
use common\models\Order ;

class DocumentController extends BackendController
{
@@ -152,10 +155,36 @@ class DocumentController extends BackendController
]) ;
if($document) {
$productsArray = Product::searchAll([], [
'as_array' => true,
]) ;
$ordersArray = [] ;
foreach($document->orders as $order) {
$order->init() ;
$productsOrderArray = [] ;
foreach($order->productOrder as $productOrder) {
$productsOrderArray[$productOrder->id] = $productOrder->getAttributes() ;
}
$ordersArray[$order->id] = array_merge(
$order->getAttributes(),
[
'productOrder' => $productsOrderArray,
]
);
}
return [
'return' => 'success',
'address' => $document->address,
'idUser' => $document->user->id
'return' => 'success',
'document' => $document->getAttributes(),
'idUser' => $document->user->id,
'products' => ArrayHelper::map($productsArray, 'id', function($product) {
$product['wording_unit'] = Product::strUnit($product['unit']) ;
return $product;
}),
'orders' => $ordersArray,
'total' => $document->getAmount(Order::AMOUNT_TOTAL)
] ;
}
}
@@ -163,6 +192,61 @@ class DocumentController extends BackendController
return ['return' => 'error'] ;
}
public function actionAjaxAddProduct($idDocument, $classDocument, $idProduct, $quantity, $price)
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
if(Document::isValidClass($classDocument)) {
$document = $classDocument::searchOne([
'id' => $idDocument
]) ;
$product = Product::searchOne([
'id' => $idProduct
]) ;
if($document && $product) {
if(count($document->orders) == 0) {
$order = new Order ;
$order->id_user = $document->id_user ;
$order->id_point_sale = null ;
$order->id_distribution = null ;
$order->origin = Order::ORIGIN_ADMIN ;
$order->date = date('Y-m-d H:i:s');
$fieldIdDocument = 'id_'.$classDocument::tableName() ;
$order->$fieldIdDocument = $document->id ;
$order->save() ;
}
else {
$order = $document->orders[0] ;
}

if($order) {
$productOrder = new ProductOrder ;
$productOrder->id_order = $order->id ;
$productOrder->id_product = $idProduct ;
$quantity = $quantity / Product::$unitsArray[$product->unit]['coefficient'];
$productOrder->quantity = $quantity ;
$productOrder->price = (float) $price ;
$productOrder->unit = $product->unit ;
$productOrder->step = $product->step ;
$productOrder->id_tax_rate = $productOrder->id_tax_rate ?
$product->taxRate->id : GlobalParam::getCurrentProducer()->taxRate->id ;
$productOrder->save() ;
return [
'return' => 'success',
] ;
}
}
}
return [
'return' => 'error'
] ;
}
protected function getClass()
{
$class = get_class($this);

+ 139
- 17
backend/views/document/_form.php View File

@@ -35,6 +35,7 @@
* pris connaissance de la licence CeCILL, et que vous en avez accepté les
* termes.
*/

use yii\helpers\Html;
use yii\widgets\ActiveForm;
use common\models\Product;
@@ -46,29 +47,32 @@ use common\models\Producer;

?>

<div class="document-form" id="app-document-form" data-class-document="<?= $model->getClass() ?>" data-id-document="<?= ($model->id > 0) ? $model->id : $model->id ?>">
<div class="document-form" id="app-document-form" data-class-document="<?= $model->getClass() ?>"
data-id-document="<?= ($model->id > 0) ? $model->id : $model->id ?>">

<div class="<?php if($action == 'create') : ?>col-md-12<?php else : ?>col-md-4<?php endif; ?>">
<div class="<?= ($action == 'update') ? 'col-md-6' : '' ?>">
<div class="panel panel-default">
<div class="panel-heading">
Informations
Général
</div>
<div class="panel-body">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'name')->label('Nom du document') ?>
<?php $usersArray = User::findBy()->all() ; ?>
<?= $form->field($model, 'id_user', [
'template' => '{label} <a href="'.Yii::$app->urlManager->createUrl(['user/create']).'" class="btn btn-xs btn-default">Nouvel utilisateur <span class="glyphicon glyphicon-plus"></span></a><div>{input}</div>{hint}',
])
<?php $usersArray = User::findBy()->all(); ?>
<?= $form->field($model, 'id_user', [
'template' => '{label} <a href="' . Yii::$app->urlManager->createUrl(['user/create']) . '" class="btn btn-xs btn-default">Nouvel utilisateur <span class="glyphicon glyphicon-plus"></span></a><div>{input}</div>{hint}',
])
->dropDownList(
ArrayHelper::map($usersArray, 'user_id', function($model) { return $model['lastname'].' '.$model['name']; }),
ArrayHelper::map($usersArray, 'user_id', function ($model) {
return $model['lastname'] . ' ' . $model['name'];
}),
[
'@change' => 'changeUser',
'prompt' => '--',
'v-model' => 'idUser',
'@change' => 'changeUser',
'prompt' => '--',
'v-model' => 'idUser',
]
); ?>
<?= $form->field($model, 'address')->textarea(['rows' => 3, 'v-model' => 'address']) ?>
<?= $form->field($model, 'address')->textarea(['rows' => 3, 'v-model' => 'document.address']) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Ajouter' : 'Modifier', ['class' => 'btn btn-primary']) ?>
</div>
@@ -76,18 +80,136 @@ use common\models\Producer;
</div>
</div>
</div>
<?php if($action == 'update'): ?>
<div class="col-md-8">

<?php if ($action == 'update'): ?>

<div class="col-md-6">
<div id="" class="info-box">
<span class="info-box-icon bg-green"><i class="fa fa-sticky-note-o"></i></span>
<div class="info-box-content">
<span class="info-box-text">Référence</span>
<span class="info-box-number">{{ document.reference }}</span>
<span class="info-box-text">Date</span>
<span class="info-box-number">{{ document.date }}</span>
</div>
</div>
<div id="" class="info-box">
<span class="info-box-icon bg-yellow"><i class="fa fa-euro"></i></span>
<div class="info-box-content">
<span class="info-box-text">Total (TTC)</span>
<span class="info-box-number">{{ formatPrice(total) }}</span>
</div>
</div>
<div id="" class="info-box">
<span class="info-box-icon bg-blue"><i class="fa fa-download"></i></span>
<div class="info-box-content">
<a href="#" class="btn btn-default">Télécharger (PDF)</a>
</div>
</div>
<div id="" class="info-box">
<span class="info-box-icon bg-red"><i class="fa fa-flash"></i></span>
<div class="info-box-content">
<a href="#" class="btn btn-default">Action 1</a>
<a href="#" class="btn btn-default">Action 2</a>
</div>
</div>
</div>
<div class="clr"></div>

<div class="">
<div class="panel panel-default" id="block-add-product">
<div class="panel-heading">
Ajouter un produit
</div>
<div class="panel-body">
<div class="col-md-5">
<select class="form-control" v-model="productAddId"
@change="changeProductAdd">
<option value="0" selected="selected">--</option>
<option v-for="product in productsArray" :value="product.id">
{{ product.name }}
</option>
</select>
</div>
<template v-if="productAddId > 0">
<div class="col-md-2">
<div class="input-group">
<input type="text" class="form-control input-price"
v-model="productAddPrice"/>
<span class="input-group-addon"><span
class="glyphicon glyphicon-euro"></span></span>
</div>
</div>
<div class="col-md-3">
<div class="input-group input-group-quantity">
<span class="input-group-btn">
<button class="btn btn-default" type="button"
@click="changeQuantityProductAdd(-1)">-</button>
</span>
<input type="text" class="form-control input-quantity"
v-model="productAddQuantity"/>
<span class="input-group-addon">{{ productsArray[productAddId].wording_unit }}</span>
<span class="input-group-btn">
<button class="btn btn-default"
type="button"
@click="changeQuantityProductAdd(1)">+</button>
</span>
</div>
</div>
<div class="col-md-2">
<button class="btn btn-primary" value="Ajouter"
@click="submitProductAdd">Ajouter
</button>
</div>
</template>
<div class="clr"></div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
Produits
</div>
<div class="panel-body">
<div id="block-list-products">
<table class="table table-bordered">
<thead>
<tr>
<td>Nom</td>
<td>Prix (unité)</td>
<td>Quantité</td>
<td>Total</td>
<td>Supprimer</td>
</tr>
</thead>
<tbody>
<template v-for="order in ordersArray">
<tr v-for="productOrder in order.productOrder">
<td>{{
productsArray[productOrder.id_product].name
}}
</td>
<td>{{ formatPrice(productOrder.price) }}</td>
<td>{{ productOrder.quantity }}</td>
<td>{{ formatPrice(productOrder.quantity *
productOrder.price) }}
</td>
<td><a class="btn btn-default"><span
class="glyphicon glyphicon-trash"></span></a>
</td>
</tr>
</template>
<tr>
<td colspan="3"><strong>Total</strong></td>
<td><strong>{{ formatPrice(total) }}</strong></td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<?php endif; ?>
</div>

+ 17
- 0
backend/web/css/screen.css View File

@@ -2265,3 +2265,20 @@ termes.
.report-index #report .section .comma:last-child {
display: none;
}

/* line 4, ../sass/document/_form.scss */
.document-form .info-box .info-box-text {
font-size: 13px;
}
/* line 7, ../sass/document/_form.scss */
.document-form .info-box .info-box-number {
font-size: 15px;
}
/* line 12, ../sass/document/_form.scss */
.document-form #block-add-product .input-price {
text-align: center;
}
/* line 16, ../sass/document/_form.scss */
.document-form #block-add-product .input-group-quantity .input-quantity {
text-align: center;
}

+ 48
- 3
backend/web/js/vuejs/document-form.js View File

@@ -38,18 +38,27 @@ termes.
var app = new Vue({
el: '#app-document-form',
data: {
document: [],
idDocument: 0,
typeDocument: '',
idUser: '',
address : ''
idUser: '',
productsArray: [],
productAddId: 0,
productAddPrice: '',
productAddQuantity: 1,
ordersArray: [],
total: 0
},
mounted: function() {
this.init() ;
},
methods: {
formatPrice: formatPrice,
init: function() {
var idDocument = $('#app-document-form').attr('data-id-document') ;
this.idDocument = idDocument ;
var classDocument = $('#app-document-form').attr('data-class-document') ;
this.classDocument = classDocument ;
if(idDocument) {
var app = this ;
@@ -59,8 +68,11 @@ var app = new Vue({
}})
.then(function(response) {
if(response.data.return == 'success') {
app.address = response.data.address ;
app.document = response.data.document ;
app.idUser = response.data.idUser ;
app.productsArray = response.data.products ;
app.ordersArray = response.data.orders ;
app.total = response.data.total ;
}
}) ;
}
@@ -78,6 +90,39 @@ var app = new Vue({
app.address = '' ;
}
}) ;
},
formatPrice: formatPrice,
getStepProductAdd: function() {
return parseInt(this.productsArray[this.productAddId].step) ;
},
changeProductAdd: function(event) {
var idProduct = event.currentTarget.value ;
this.productAddId = idProduct ;
this.productAddPrice = parseFloat(this.productsArray[idProduct].price).toFixed(2) ;
this.productAddQuantity = this.getStepProductAdd() ;
},
changeQuantityProductAdd: function(quantity) {
var step = this.getStepProductAdd() ;
quantity = quantity * step ;
this.productAddQuantity += quantity ;
if(this.productAddQuantity < 1) {
this.productAddQuantity = step ;
}
},
submitProductAdd: function() {
var app = this ;
axios.get(UrlManager.getBaseUrlAbsolute()+"document/ajax-add-product",{params: {
idDocument: app.idDocument,
classDocument: app.classDocument,
idProduct: app.productAddId,
quantity: app.productAddQuantity,
price: app.productAddPrice,
}})
.then(function(response) {
app.productAddId = 0 ;
app.init() ;
alert('Produit ajouté') ;
}) ;
}
}
});

+ 21
- 0
backend/web/sass/document/_form.scss View File

@@ -0,0 +1,21 @@

.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 ;
}
}
}
}

+ 2
- 1
backend/web/sass/screen.scss View File

@@ -1480,4 +1480,5 @@ a.btn, button.btn {
@import "user/_form.scss" ;
@import "producer/_update.scss" ;
@import "point_sale/_index.scss" ;
@import "report/_index.scss" ;
@import "report/_index.scss" ;
@import "document/_form.scss" ;

+ 5
- 5
common/models/Document.php View File

@@ -142,6 +142,11 @@ class Document extends ActiveRecordCommon
return str_replace('common\models\\','',get_class($this)) ;
}
public function isValidClass($typeDocument)
{
return in_array($typeDocument, ['Invoice', 'DeliveryNote', 'Quotation']) ;
}
public function generateReference()
{
$class = $this->getClass() ;
@@ -174,9 +179,4 @@ class Document extends ActiveRecordCommon
}
}
}
public function isValidClass($typeDocument)
{
return in_array($typeDocument, ['Invoice', 'DeliveryNote', 'Quotation']) ;
}
}

+ 2
- 3
common/models/Order.php View File

@@ -92,8 +92,8 @@ class Order extends ActiveRecordCommon
public function rules()
{
return [
[['id_user', 'date', 'id_point_sale', 'id_distribution'], 'required', 'message' => ''],
[['id_user', 'id_point_sale', 'id_distribution', 'id_subscription', 'id_order_status', 'id_invoice', 'id_quotation', 'id_delivery_note'], 'integer'],
[['id_user', 'date'], 'required', 'message' => ''],
[['id_user', 'id_point_sale', 'id_distribution', 'id_subscription', 'id_invoice', 'id_quotation', 'id_delivery_note'], 'integer'],
[['auto_payment', 'tiller_synchronization'], 'boolean'],
[['date', 'date_update', 'comment', 'comment_point_sale', 'mean_payment'], 'safe']
];
@@ -112,7 +112,6 @@ class Order extends ActiveRecordCommon
'id_point_sale' => 'Point de vente',
'id_distribution' => 'Date de distribution',
'id_subscription' => 'Abonnement',
'id_order_status' => 'Statut',
'id_invoice' => 'Facture',
'id_quotation' => 'Devis',
'id_delivery_note' => 'Bon de livraison'

+ 20
- 0
console/migrations/m200109_070952_module_devis_bl_factures_champs_order_valeur_default.php View File

@@ -0,0 +1,20 @@
<?php

use yii\db\Migration;
use yii\db\Schema;

class m200109_070952_module_devis_bl_factures_champs_order_valeur_default extends Migration
{
public function safeUp()
{
$this->alterColumn('order', 'id_point_sale', Schema::TYPE_INTEGER.' DEFAULT NULL') ;
$this->alterColumn('order', 'id_distribution', Schema::TYPE_INTEGER.' DEFAULT NULL') ;
}

public function safeDown()
{
$this->alterColumn('order', 'id_point_sale', Schema::TYPE_INTEGER) ;
$this->alterColumn('order', 'id_distribution', Schema::TYPE_INTEGER) ;
}

}

Loading…
Cancel
Save