namespace backend\controllers; | namespace backend\controllers; | ||||
use common\models\Product; | |||||
use common\models\User ; | use common\models\User ; | ||||
use common\models\Document ; | |||||
use common\helpers\GlobalParam ; | use common\helpers\GlobalParam ; | ||||
use common\models\Order ; | |||||
class DocumentController extends BackendController | class DocumentController extends BackendController | ||||
{ | { | ||||
]) ; | ]) ; | ||||
if($document) { | 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 [ | ||||
'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) | |||||
] ; | ] ; | ||||
} | } | ||||
} | } | ||||
return ['return' => 'error'] ; | 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() | protected function getClass() | ||||
{ | { | ||||
$class = get_class($this); | $class = get_class($this); |
* pris connaissance de la licence CeCILL, et que vous en avez accepté les | * pris connaissance de la licence CeCILL, et que vous en avez accepté les | ||||
* termes. | * termes. | ||||
*/ | */ | ||||
use yii\helpers\Html; | use yii\helpers\Html; | ||||
use yii\widgets\ActiveForm; | use yii\widgets\ActiveForm; | ||||
use common\models\Product; | use common\models\Product; | ||||
?> | ?> | ||||
<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 panel-default"> | ||||
<div class="panel-heading"> | <div class="panel-heading"> | ||||
Informations | |||||
Général | |||||
</div> | </div> | ||||
<div class="panel-body"> | <div class="panel-body"> | ||||
<?php $form = ActiveForm::begin(); ?> | <?php $form = ActiveForm::begin(); ?> | ||||
<?= $form->field($model, 'name')->label('Nom du document') ?> | <?= $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( | ->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"> | <div class="form-group"> | ||||
<?= Html::submitButton($model->isNewRecord ? 'Ajouter' : 'Modifier', ['class' => 'btn btn-primary']) ?> | <?= Html::submitButton($model->isNewRecord ? 'Ajouter' : 'Modifier', ['class' => 'btn btn-primary']) ?> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </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 panel-default"> | ||||
<div class="panel-heading"> | <div class="panel-heading"> | ||||
Produits | Produits | ||||
</div> | </div> | ||||
<div class="panel-body"> | <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> | </div> | ||||
</div> | </div> | ||||
<?php endif; ?> | <?php endif; ?> | ||||
</div> | </div> |
.report-index #report .section .comma:last-child { | .report-index #report .section .comma:last-child { | ||||
display: none; | 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; | |||||
} |
var app = new Vue({ | var app = new Vue({ | ||||
el: '#app-document-form', | el: '#app-document-form', | ||||
data: { | data: { | ||||
document: [], | |||||
idDocument: 0, | idDocument: 0, | ||||
typeDocument: '', | typeDocument: '', | ||||
idUser: '', | |||||
address : '' | |||||
idUser: '', | |||||
productsArray: [], | |||||
productAddId: 0, | |||||
productAddPrice: '', | |||||
productAddQuantity: 1, | |||||
ordersArray: [], | |||||
total: 0 | |||||
}, | }, | ||||
mounted: function() { | mounted: function() { | ||||
this.init() ; | this.init() ; | ||||
}, | }, | ||||
methods: { | methods: { | ||||
formatPrice: formatPrice, | |||||
init: function() { | init: function() { | ||||
var idDocument = $('#app-document-form').attr('data-id-document') ; | var idDocument = $('#app-document-form').attr('data-id-document') ; | ||||
this.idDocument = idDocument ; | |||||
var classDocument = $('#app-document-form').attr('data-class-document') ; | var classDocument = $('#app-document-form').attr('data-class-document') ; | ||||
this.classDocument = classDocument ; | |||||
if(idDocument) { | if(idDocument) { | ||||
var app = this ; | var app = this ; | ||||
}}) | }}) | ||||
.then(function(response) { | .then(function(response) { | ||||
if(response.data.return == 'success') { | if(response.data.return == 'success') { | ||||
app.address = response.data.address ; | |||||
app.document = response.data.document ; | |||||
app.idUser = response.data.idUser ; | app.idUser = response.data.idUser ; | ||||
app.productsArray = response.data.products ; | |||||
app.ordersArray = response.data.orders ; | |||||
app.total = response.data.total ; | |||||
} | } | ||||
}) ; | }) ; | ||||
} | } | ||||
app.address = '' ; | 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é') ; | |||||
}) ; | |||||
} | } | ||||
} | } | ||||
}); | }); |
.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 ; | |||||
} | |||||
} | |||||
} | |||||
} |
@import "user/_form.scss" ; | @import "user/_form.scss" ; | ||||
@import "producer/_update.scss" ; | @import "producer/_update.scss" ; | ||||
@import "point_sale/_index.scss" ; | @import "point_sale/_index.scss" ; | ||||
@import "report/_index.scss" ; | |||||
@import "report/_index.scss" ; | |||||
@import "document/_form.scss" ; |
return str_replace('common\models\\','',get_class($this)) ; | return str_replace('common\models\\','',get_class($this)) ; | ||||
} | } | ||||
public function isValidClass($typeDocument) | |||||
{ | |||||
return in_array($typeDocument, ['Invoice', 'DeliveryNote', 'Quotation']) ; | |||||
} | |||||
public function generateReference() | public function generateReference() | ||||
{ | { | ||||
$class = $this->getClass() ; | $class = $this->getClass() ; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
public function isValidClass($typeDocument) | |||||
{ | |||||
return in_array($typeDocument, ['Invoice', 'DeliveryNote', 'Quotation']) ; | |||||
} | |||||
} | } |
public function rules() | public function rules() | ||||
{ | { | ||||
return [ | 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'], | [['auto_payment', 'tiller_synchronization'], 'boolean'], | ||||
[['date', 'date_update', 'comment', 'comment_point_sale', 'mean_payment'], 'safe'] | [['date', 'date_update', 'comment', 'comment_point_sale', 'mean_payment'], 'safe'] | ||||
]; | ]; | ||||
'id_point_sale' => 'Point de vente', | 'id_point_sale' => 'Point de vente', | ||||
'id_distribution' => 'Date de distribution', | 'id_distribution' => 'Date de distribution', | ||||
'id_subscription' => 'Abonnement', | 'id_subscription' => 'Abonnement', | ||||
'id_order_status' => 'Statut', | |||||
'id_invoice' => 'Facture', | 'id_invoice' => 'Facture', | ||||
'id_quotation' => 'Devis', | 'id_quotation' => 'Devis', | ||||
'id_delivery_note' => 'Bon de livraison' | 'id_delivery_note' => 'Bon de livraison' |
<?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) ; | |||||
} | |||||
} |