@@ -81,32 +81,21 @@ class DevelopmentController extends Controller | |||
*/ | |||
public function actionIndex() | |||
{ | |||
$versionsArray = []; | |||
$pathVersions = Yii::getAlias('@common/versions'); | |||
if(is_dir($pathVersions)) | |||
{ | |||
$directory = opendir($pathVersions); | |||
while( $child = readdir($directory) ){ | |||
if($child != '.' && $child != '..'){ | |||
$version = str_replace('.php', '', $child); | |||
$versionsArray[$version] = [ | |||
'version' => str_replace('.php', '', $child), | |||
'content' => $this->renderFile('@common/versions/'.$child) | |||
]; | |||
} | |||
} | |||
$versionsArray = Opendistrib::getVersions(); | |||
$versionsRenderArray = []; | |||
foreach($versionsArray as $version) { | |||
$versionsRenderArray[$version] = [ | |||
'version' => $version, | |||
'content' => $this->renderFile('@common/versions/'.$version.'.php') | |||
]; | |||
} | |||
krsort($versionsArray); | |||
// Producer : set latest version d'Opendistrib | |||
$producer = GlobalParam::getCurrentProducer(); | |||
$producer->latest_version_opendistrib = array_values($versionsArray)[0]['version']; | |||
$producer->save(); | |||
$producer->updateOpendistribVersion(); | |||
return $this->render('index', [ | |||
'versionsArray' => $versionsArray | |||
'versionsArray' => $versionsRenderArray | |||
]); | |||
} | |||
@@ -366,33 +366,20 @@ class DocumentController extends BackendController | |||
]; | |||
if ($classDocument == 'Invoice') { | |||
if ($typeAction == 'create') { | |||
$deliveryNotesArray = DeliveryNote::searchAll([ | |||
'id_user' => $user->id, | |||
'status' => Document::STATUS_VALID | |||
]); | |||
} elseif ($typeAction == 'update' && $idDocument > 0) { | |||
$deliveryNotesArray = DeliveryNote::searchAll([ | |||
'id_user' => $user->id, | |||
'status' => Document::STATUS_VALID, | |||
'order.id_invoice' => $idDocument | |||
]); | |||
} | |||
if (isset($deliveryNotesArray)) { | |||
$json['delivery_notes'] = []; | |||
foreach ($deliveryNotesArray as $deliveryNote) { | |||
if (!$deliveryNote->isInvoiced()) { | |||
$json['delivery_notes'][] = array_merge( | |||
$deliveryNote->getAttributes(), | |||
[ | |||
'total' => $deliveryNote->getAmountWithTax(Order::INVOICE_AMOUNT_TOTAL) | |||
] | |||
); | |||
} | |||
} | |||
} | |||
$options = [ | |||
'orderby' => 'distribution.date ASC' | |||
]; | |||
$deliveryNotesCreateArray = DeliveryNote::searchAll([ | |||
'id_user' => $user->id, | |||
'status' => Document::STATUS_VALID | |||
], $options); | |||
$deliveryNotesUpdateArray = DeliveryNote::searchAll([ | |||
'id_user' => $user->id, | |||
'status' => Document::STATUS_VALID, | |||
'order.id_invoice' => $idDocument | |||
], $options); | |||
$json['delivery_note_create_array'] = $this->initDeliveryNoteArray('create', $deliveryNotesCreateArray); | |||
$json['delivery_note_update_array'] = $this->initDeliveryNoteArray('update', $deliveryNotesUpdateArray); | |||
} | |||
return $json; | |||
@@ -402,6 +389,43 @@ class DocumentController extends BackendController | |||
return ['return' => 'error']; | |||
} | |||
public function initDeliveryNoteArray($type, $deliveryNoteArrayResults) | |||
{ | |||
$deliveryNoteArray = []; | |||
$isCreate = false; | |||
if($type == 'create') { | |||
$isCreate = true; | |||
} | |||
if($deliveryNoteArrayResults) { | |||
foreach ($deliveryNoteArrayResults as $deliveryNote) { | |||
$deliveryNoteData = $this->addDeliveryNoteToArray($deliveryNote, $isCreate); | |||
if($deliveryNoteData) { | |||
$deliveryNoteArray[] = $deliveryNoteData; | |||
} | |||
} | |||
} | |||
return $deliveryNoteArray; | |||
} | |||
public function addDeliveryNoteToArray($deliveryNote, $isCreate = true) | |||
{ | |||
$deliveryNoteData = array_merge( | |||
$deliveryNote->getAttributes(), | |||
[ | |||
'url' => Yii::$app->urlManager->createUrl(['delivery-note/update', 'id' => $deliveryNote->id]), | |||
'total' => $deliveryNote->getAmountWithTax(Order::INVOICE_AMOUNT_TOTAL) | |||
] | |||
); | |||
if (($isCreate && !$deliveryNote->isInvoiced()) || !$isCreate) { | |||
return $deliveryNoteData; | |||
} | |||
return false; | |||
} | |||
public function actionValidate($id, $backUpdateForm = false) | |||
{ | |||
$classDocument = $this->getClass(); | |||
@@ -542,6 +566,7 @@ class DocumentController extends BackendController | |||
) == 'DeliveryNote') ? $document->getAmountWithTax( | |||
Order::INVOICE_AMOUNT_TOTAL | |||
) : $document->getAmountWithTax(Order::AMOUNT_TOTAL), | |||
'invoice_url' => ($document->getClass() == 'DeliveryNote' && $document->getInvoice()) ? Yii::$app->urlManager->createUrl(['invoice/update', 'id' => $document->getInvoice()->id]) : null | |||
]; | |||
} | |||
} |
@@ -38,6 +38,7 @@ termes. | |||
namespace backend\controllers; | |||
use common\models\Order; | |||
use Yii; | |||
@@ -59,4 +60,65 @@ class InvoiceController extends DocumentController | |||
]); | |||
} | |||
public function actionAjaxDeleteDeliveryNote($idInvoice, $idDeliveryNote) | |||
{ | |||
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; | |||
$invoice = Invoice::searchOne(['id' => $idInvoice]); | |||
if($invoice && $invoice->isStatusDraft()) { | |||
Order::updateAll([ | |||
'id_invoice' => null | |||
], [ | |||
'id_delivery_note' => $idDeliveryNote | |||
]); | |||
return [ | |||
'alert' => [ | |||
'type' => 'success', | |||
'message' => '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.' | |||
] | |||
]; | |||
} | |||
} | |||
public function actionAjaxAddDeliveryNote($idInvoice, $idDeliveryNote) | |||
{ | |||
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; | |||
$invoice = Invoice::searchOne(['id' => $idInvoice]); | |||
$deliveryNote = DeliveryNote::searchOne(['id' => $idDeliveryNote]); | |||
if($invoice && $invoice->isStatusDraft() && $deliveryNote) { | |||
Order::updateAll([ | |||
'id_invoice' => $idInvoice | |||
], [ | |||
'id_delivery_note' => $idDeliveryNote | |||
]); | |||
return [ | |||
'alert' => [ | |||
'type' => 'success', | |||
'message' => 'Bon de livraison ajouté à la facture.' | |||
] | |||
]; | |||
} | |||
else { | |||
return [ | |||
'alert' => [ | |||
'type' => 'error', | |||
'message' => 'Une erreur est survenue lors de l\'ajout du bon de livraison.' | |||
] | |||
]; | |||
} | |||
} | |||
} |
@@ -1,39 +1,39 @@ | |||
<?php | |||
/** | |||
Copyright distrib (2018) | |||
contact@opendistrib.net | |||
Ce logiciel est un programme informatique servant à aider les producteurs | |||
à distribuer leur production en circuits courts. | |||
Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||
respectant les principes de diffusion des logiciels libres. Vous pouvez | |||
utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||
de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||
sur le site "http://www.cecill.info". | |||
En contrepartie de l'accessibilité au code source et des droits de copie, | |||
de modification et de redistribution accordés par cette licence, il n'est | |||
offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||
seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||
titulaire des droits patrimoniaux et les concédants successifs. | |||
A cet égard l'attention de l'utilisateur est attirée sur les risques | |||
associés au chargement, à l'utilisation, à la modification et/ou au | |||
développement et à la reproduction du logiciel par l'utilisateur étant | |||
donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||
manipuler et qui le réserve donc à des développeurs et des professionnels | |||
avertis possédant des connaissances informatiques approfondies. Les | |||
utilisateurs sont donc invités à charger et tester l'adéquation du | |||
logiciel à leurs besoins dans des conditions permettant d'assurer la | |||
sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||
à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||
Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||
pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
termes. | |||
* Copyright distrib (2018) | |||
* | |||
* contact@opendistrib.net | |||
* | |||
* Ce logiciel est un programme informatique servant à aider les producteurs | |||
* à distribuer leur production en circuits courts. | |||
* | |||
* Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||
* respectant les principes de diffusion des logiciels libres. Vous pouvez | |||
* utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||
* sur le site "http://www.cecill.info". | |||
* | |||
* En contrepartie de l'accessibilité au code source et des droits de copie, | |||
* de modification et de redistribution accordés par cette licence, il n'est | |||
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||
* seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||
* titulaire des droits patrimoniaux et les concédants successifs. | |||
* | |||
* A cet égard l'attention de l'utilisateur est attirée sur les risques | |||
* associés au chargement, à l'utilisation, à la modification et/ou au | |||
* développement et à la reproduction du logiciel par l'utilisateur étant | |||
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||
* manipuler et qui le réserve donc à des développeurs et des professionnels | |||
* avertis possédant des connaissances informatiques approfondies. Les | |||
* utilisateurs sont donc invités à charger et tester l'adéquation du | |||
* logiciel à leurs besoins dans des conditions permettant d'assurer la | |||
* sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||
* | |||
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||
* pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
* termes. | |||
*/ | |||
namespace backend\controllers; | |||
@@ -58,159 +58,165 @@ use common\models\Invoice; | |||
class ProducerController extends BackendController | |||
{ | |||
public $enableCsrfValidation = false; | |||
public function behaviors() | |||
{ | |||
return [ | |||
'verbs' => [ | |||
'class' => VerbFilter::className(), | |||
'actions' => [ | |||
'delete' => ['post'], | |||
], | |||
], | |||
'access' => [ | |||
'class' => AccessControl::className(), | |||
'rules' => [ | |||
[ | |||
'allow' => true, | |||
'roles' => ['@'], | |||
'matchCallback' => function ($rule, $action) { | |||
return User::hasAccessBackend(); | |||
} | |||
] | |||
], | |||
], | |||
]; | |||
} | |||
/** | |||
* Modifie un producteur. | |||
* | |||
* @return mixed | |||
*/ | |||
public function actionUpdate() | |||
{ | |||
$request = Yii::$app->request; | |||
$model = $this->findModel(GlobalParam::getCurrentProducerId()); | |||
$logoFilenameOld = $model->logo; | |||
$photoFilenameOld = $model->photo; | |||
if (strlen($model->option_dashboard_date_start)) { | |||
$model->option_dashboard_date_start = date('d/m/Y', strtotime($model->option_dashboard_date_start)); | |||
} | |||
if (strlen($model->option_dashboard_date_end)) { | |||
$model->option_dashboard_date_end = date('d/m/Y', strtotime($model->option_dashboard_date_end)); | |||
} | |||
if ($model->load(Yii::$app->request->post()) && $model->save()) { | |||
if(strlen($model->option_dashboard_date_start)) { | |||
$model->option_dashboard_date_start = date( | |||
'Y-m-d', | |||
strtotime(str_replace('/', '-', $model->option_dashboard_date_start) | |||
)); | |||
$model->save() ; | |||
} | |||
if(strlen($model->option_dashboard_date_end)) { | |||
$model->option_dashboard_date_end = date( | |||
'Y-m-d', | |||
strtotime(str_replace('/', '-', $model->option_dashboard_date_end)) | |||
); | |||
$model->save() ; | |||
} | |||
Upload::uploadFile($model, 'logo', $logoFilenameOld); | |||
Upload::uploadFile($model, 'photo', $photoFilenameOld); | |||
$deleteLogo = $request->post('delete_logo', 0); | |||
if ($deleteLogo) { | |||
$model->logo = ''; | |||
$model->save(); | |||
} | |||
$deletePhoto = $request->post('delete_photo', 0); | |||
if ($deletePhoto) { | |||
$model->photo = ''; | |||
$model->save(); | |||
public $enableCsrfValidation = false; | |||
public function behaviors() | |||
{ | |||
return [ | |||
'verbs' => [ | |||
'class' => VerbFilter::className(), | |||
'actions' => [ | |||
'delete' => ['post'], | |||
], | |||
], | |||
'access' => [ | |||
'class' => AccessControl::className(), | |||
'rules' => [ | |||
[ | |||
'allow' => true, | |||
'roles' => ['@'], | |||
'matchCallback' => function ($rule, $action) { | |||
return User::hasAccessBackend(); | |||
} | |||
$model->savePrivateKeyApiStripe() ; | |||
$model->savePrivateKeyEndpointStripe() ; | |||
$model->option_stripe_private_key = ''; | |||
$model->option_stripe_endpoint_secret = ''; | |||
$model->save(); | |||
Yii::$app->getSession()->setFlash('success', 'Paramètres mis à jour.'); | |||
return $this->redirect(['update', 'id' => $model->id, 'edit_ok' => true]); | |||
} else { | |||
if($model->load(Yii::$app->request->post())) { | |||
Yii::$app->getSession()->setFlash('error', 'Le formulaire comporte des erreurs.'); | |||
} | |||
return $this->render('update', [ | |||
'model' => $model, | |||
]); | |||
} | |||
] | |||
], | |||
], | |||
]; | |||
} | |||
/** | |||
* Modifie un producteur. | |||
* | |||
* @return mixed | |||
*/ | |||
public function actionUpdate() | |||
{ | |||
$request = Yii::$app->request; | |||
$model = $this->findModel(GlobalParam::getCurrentProducerId()); | |||
$logoFilenameOld = $model->logo; | |||
$photoFilenameOld = $model->photo; | |||
if (strlen($model->option_dashboard_date_start)) { | |||
$model->option_dashboard_date_start = date('d/m/Y', strtotime($model->option_dashboard_date_start)); | |||
} | |||
/** | |||
* Affiche le formulaire permettant au producteur de définir le montant | |||
* de son abonnement. | |||
* | |||
* @return mixed | |||
*/ | |||
public function actionBilling() | |||
{ | |||
$datasInvoices = new ActiveDataProvider([ | |||
'query' => Invoice::find() | |||
->where(['id_producer' => GlobalParam::getCurrentProducerId()]) | |||
->orderBy('reference DESC'), | |||
'pagination' => [ | |||
'pageSize' => 1000, | |||
], | |||
]); | |||
$producer = Producer::findOne(GlobalParam::getCurrentProducerId()); | |||
if ($producer->load(Yii::$app->request->post())) { | |||
$producer->save(); | |||
if (!is_null($producer->free_price)) { | |||
$alertFreeprice = true; | |||
} | |||
} | |||
$dataProviderPrices = new ActiveDataProvider([ | |||
'query' => ProducerPriceRange::find() | |||
->orderBy('id ASC'), | |||
'pagination' => [ | |||
'pageSize' => 100, | |||
], | |||
]); | |||
return $this->render('billing', [ | |||
'dataProviderPrices' => $dataProviderPrices, | |||
'datasInvoices' => $datasInvoices, | |||
'producer' => $producer, | |||
'alertFreePrice' => (isset($alertFreeprice)) ? true : false | |||
]); | |||
if (strlen($model->option_dashboard_date_end)) { | |||
$model->option_dashboard_date_end = date('d/m/Y', strtotime($model->option_dashboard_date_end)); | |||
} | |||
/** | |||
* Recherche un établissement via son ID. | |||
* | |||
* @param integer $id | |||
* @return Etablissement | |||
* @throws NotFoundHttpException | |||
*/ | |||
protected function findModel($id) | |||
{ | |||
if (($model = Producer::findOne($id)) !== null) { | |||
return $model; | |||
} else { | |||
throw new NotFoundHttpException('The requested page does not exist.'); | |||
} | |||
if ($model->load(Yii::$app->request->post()) && $model->save()) { | |||
if (strlen($model->option_dashboard_date_start)) { | |||
$model->option_dashboard_date_start = date( | |||
'Y-m-d', | |||
strtotime(str_replace('/', '-', $model->option_dashboard_date_start) | |||
)); | |||
$model->save(); | |||
} | |||
if (strlen($model->option_dashboard_date_end)) { | |||
$model->option_dashboard_date_end = date( | |||
'Y-m-d', | |||
strtotime(str_replace('/', '-', $model->option_dashboard_date_end)) | |||
); | |||
$model->save(); | |||
} | |||
Upload::uploadFile($model, 'logo', $logoFilenameOld); | |||
Upload::uploadFile($model, 'photo', $photoFilenameOld); | |||
$deleteLogo = $request->post('delete_logo', 0); | |||
if ($deleteLogo) { | |||
$model->logo = ''; | |||
$model->save(); | |||
} | |||
$deletePhoto = $request->post('delete_photo', 0); | |||
if ($deletePhoto) { | |||
$model->photo = ''; | |||
$model->save(); | |||
} | |||
$model->savePrivateKeyApiStripe(); | |||
$model->savePrivateKeyEndpointStripe(); | |||
$model->option_stripe_private_key = ''; | |||
$model->option_stripe_endpoint_secret = ''; | |||
$model->save(); | |||
Yii::$app->getSession()->setFlash('success', 'Paramètres mis à jour.'); | |||
return $this->redirect(['update', 'id' => $model->id, 'edit_ok' => true]); | |||
} else { | |||
if ($model->load(Yii::$app->request->post())) { | |||
Yii::$app->getSession()->setFlash('error', 'Le formulaire comporte des erreurs.'); | |||
} | |||
return $this->render('update', [ | |||
'model' => $model, | |||
]); | |||
} | |||
} | |||
/** | |||
* Affiche le formulaire permettant au producteur de définir le montant | |||
* de son abonnement. | |||
* | |||
* @return mixed | |||
*/ | |||
public function actionBilling() | |||
{ | |||
$datasInvoices = new ActiveDataProvider([ | |||
'query' => Invoice::find() | |||
->where(['id_producer' => GlobalParam::getCurrentProducerId()]) | |||
->orderBy('reference DESC'), | |||
'pagination' => [ | |||
'pageSize' => 1000, | |||
], | |||
]); | |||
$producer = Producer::findOne(GlobalParam::getCurrentProducerId()); | |||
if ($producer->load(Yii::$app->request->post())) { | |||
$producer->save(); | |||
if (!is_null($producer->free_price)) { | |||
$alertFreeprice = true; | |||
} | |||
} | |||
$dataProviderPrices = new ActiveDataProvider([ | |||
'query' => ProducerPriceRange::find() | |||
->orderBy('id ASC'), | |||
'pagination' => [ | |||
'pageSize' => 100, | |||
], | |||
]); | |||
return $this->render('billing', [ | |||
'dataProviderPrices' => $dataProviderPrices, | |||
'datasInvoices' => $datasInvoices, | |||
'producer' => $producer, | |||
'alertFreePrice' => (isset($alertFreeprice)) ? true : false | |||
]); | |||
} | |||
/** | |||
* Recherche un établissement via son ID. | |||
* | |||
* @param integer $id | |||
* @return Etablissement | |||
* @throws NotFoundHttpException | |||
*/ | |||
protected function findModel($id) | |||
{ | |||
if (($model = Producer::findOne($id)) !== null) { | |||
return $model; | |||
} else { | |||
throw new NotFoundHttpException('The requested page does not exist.'); | |||
} | |||
} | |||
public function actionUpdateOpendistribVersion() | |||
{ | |||
$producer = GlobalParam::getCurrentProducer(); | |||
$producer->updateOpendistribVersion(); | |||
return $this->redirect(Yii::$app->request->referrer); | |||
} | |||
} |
@@ -357,6 +357,7 @@ class ProductController extends BackendController | |||
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; | |||
$product = $this->findModel($id); | |||
$product->active = (int) $active; | |||
$product->save(); | |||
Distribution::linkProductIncomingDistributions($product); | |||
@@ -444,11 +444,15 @@ class UserController extends BackendController | |||
} else { | |||
$bodyResponseSendMail = $responseSendMail->getBody(); | |||
$emailsErrorArray = []; | |||
foreach ($bodyResponseSendMail['Messages'] as $message) { | |||
if ($message['Status'] != 'success') { | |||
$emailsErrorArray[] = $message['To']['Email']; | |||
if(isset($bodyResponseSendMail['Messages'])) { | |||
foreach ($bodyResponseSendMail['Messages'] as $message) { | |||
if ($message['Status'] != 'success') { | |||
$emailsErrorArray[] = $message['To']['Email']; | |||
} | |||
} | |||
} | |||
$messageError = 'Un problème est survenu lors de l\'envoi de votre email.'; | |||
if (count($emailsErrorArray) > 0) { | |||
$messageError .= '<br />Problème détecté sur les adresses suivantes : ' . implode(',', $emailsErrorArray); |
@@ -52,6 +52,7 @@ class MailForm extends Model | |||
public $id_distribution ; | |||
public $subject; | |||
public $message; | |||
public $integrate_product_list = false; | |||
/** | |||
* @inheritdoc | |||
@@ -60,6 +61,7 @@ class MailForm extends Model | |||
{ | |||
return [ | |||
[['subject', 'message'], 'required', 'message' => 'Champs obligatoire'], | |||
[['integrate_product_list'], 'boolean'], | |||
[['id_distribution'],'integer'] | |||
]; | |||
} | |||
@@ -72,7 +74,8 @@ class MailForm extends Model | |||
return [ | |||
'subject' => 'Sujet', | |||
'message' => 'Message', | |||
'id_distribution' => 'Distribution' | |||
'id_distribution' => 'Distribution', | |||
'integrate_product_list' => 'Intégrer la liste des produits au message' | |||
]; | |||
} | |||
@@ -111,42 +114,44 @@ class MailForm extends Model | |||
$messageAutoHtml .= '<a href="'.$linkOrder.'">Passer ma commande du '.$dateOrder.'</a>' ; | |||
$messageAutoText .= 'Suivez ce lien pour passer votre commande du '.$dateOrder.' : | |||
'.$linkOrder ; | |||
$productsArray = Product::find() | |||
->where([ | |||
'id_producer' => GlobalParam::getCurrentProducerId(), | |||
]) | |||
->innerJoinWith(['productDistribution' => function($query) use($distribution) { | |||
$query->andOnCondition([ | |||
'product_distribution.id_distribution' => $distribution->id, | |||
'product_distribution.active' => 1 | |||
]); | |||
}]) | |||
->orderBy('product.name ASC') | |||
->all(); | |||
if(count($productsArray) > 1) { | |||
$messageAutoHtml .= '<br /><br />Produits disponibles : <br /><ul>' ; | |||
$messageAutoText .= ' | |||
if($this->integrate_product_list) { | |||
$productsArray = Product::find() | |||
->where([ | |||
'id_producer' => GlobalParam::getCurrentProducerId(), | |||
]) | |||
->innerJoinWith(['productDistribution' => function($query) use($distribution) { | |||
$query->andOnCondition([ | |||
'product_distribution.id_distribution' => $distribution->id, | |||
'product_distribution.active' => 1 | |||
]); | |||
}]) | |||
->orderBy('product.name ASC') | |||
->all(); | |||
if(count($productsArray) > 1) { | |||
$messageAutoHtml .= '<br /><br />Produits disponibles : <br /><ul>' ; | |||
$messageAutoText .= ' | |||
Produits disponibles : | |||
' ; | |||
foreach($productsArray as $product) { | |||
$productDescription = $product->name ; | |||
if(strlen($product->description)) { | |||
$productDescription .= ' / '.$product->description ; | |||
} | |||
if($product->price) { | |||
$productDescription .= ' / '.Price::format($product->getPriceWithTax()) ; | |||
$productDescription .= ' ('.Product::strUnit($product->unit, 'wording_unit').')' ; | |||
} | |||
$messageAutoText .= '- '.$productDescription.' | |||
foreach($productsArray as $product) { | |||
$productDescription = $product->name ; | |||
if(strlen($product->description)) { | |||
$productDescription .= ' / '.$product->description ; | |||
} | |||
if($product->price) { | |||
$productDescription .= ' / '.Price::format($product->getPriceWithTax()) ; | |||
$productDescription .= ' ('.Product::strUnit($product->unit, 'wording_unit').')' ; | |||
} | |||
$messageAutoText .= '- '.$productDescription.' | |||
' ; | |||
$messageAutoHtml .= '<li>'.Html::encode($productDescription).'</li>' ; | |||
$messageAutoHtml .= '<li>'.Html::encode($productDescription).'</li>' ; | |||
} | |||
$messageAutoHtml .= '</ul>' ; | |||
} | |||
$messageAutoHtml .= '</ul>' ; | |||
} | |||
} | |||
} | |||
@@ -160,7 +165,12 @@ Produits disponibles : | |||
$fromEmail = 'contact@opendistrib.net' ; | |||
$fromName = 'Opendistrib' ; | |||
} | |||
// Tests | |||
/*$usersArray = [ | |||
['email' => '', 'name' => '', 'lastname' => ''] | |||
];*/ | |||
foreach($usersArray as $user) { | |||
$body['Messages'][] = [ | |||
'From' => [ |
@@ -50,22 +50,44 @@ $this->addBreadcrumb($this->getTitle()); | |||
?> | |||
<div class="development-index"> | |||
<div class="alert alert-info"> | |||
Cette page liste les dernières versions du logiciel Opendistrib. Me | |||
<a href="mailto:contact@opendistrib.net">contacter</a> pour soumettre | |||
vos suggestions d'évolutions ou remontées de bug. | |||
</div> | |||
<?php foreach($versionsArray as $version): ?> | |||
<div class="panel panel-default"> | |||
<div class="panel-heading"> | |||
<h3 class="panel-title"> | |||
<?= $version['version'] ?> | |||
</h3> | |||
<div class="container-fluidd"> | |||
<div class="row"> | |||
<div class="col-md-8"> | |||
<?php foreach($versionsArray as $version): ?> | |||
<div class="panel panel-default"> | |||
<div class="panel-heading"> | |||
<h3 class="panel-title"> | |||
<?= $version['version'] ?> | |||
</h3> | |||
</div> | |||
<div class="panel-body"> | |||
<?= $version['content'] ?> | |||
</div> | |||
</div> | |||
<?php endforeach; ?> | |||
</div> | |||
<div class="panel-body"> | |||
<?= $version['content'] ?> | |||
<div class="col-md-4"> | |||
<div id="panel-participate" class="panel panel-default"> | |||
<div class="panel-heading"> | |||
<h3 class="panel-title">Participer</h3> | |||
</div> | |||
<div class="panel-body"> | |||
<p>Le logiciel Opendistrib se construit pour et avec vous. Toutes vos suggestions et remontées | |||
de bugs sont les bienvenues et forment le terreau des versions futures !</p> | |||
<p>Pour me contacter :</p> | |||
<ul class="contacts"> | |||
<li> | |||
<span class="glyphicon glyphicon-earphone"></span> | |||
<p><a href="mailto:contact@opendistrib.net?subject=Demande de rappel">Demander à être rappelé</a> en indiquant vos disponibilités.</p> | |||
</li> | |||
<li> | |||
<span class="glyphicon glyphicon-envelope"></span> | |||
<p><a href="mailto:contact@opendistrib.net">M'envoyer un message</a></p> | |||
</li> | |||
</ul> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<?php endforeach; ?> | |||
</div> | |||
</div> |
@@ -94,28 +94,24 @@ use common\models\Producer; | |||
<?= $form->field($model, 'address')->textarea(['rows' => 2, 'v-model' => 'document.address']) ?> | |||
<?php if ($action == 'update'): ?> | |||
<?= $form->field($model, 'comment')->textarea(['rows' => 2])->hint('Affiché en bas de la facture') ?> | |||
<?= $form->field($model, 'comment')->textarea(['rows' => 2])->hint('Affiché en bas du document') ?> | |||
<?php endif; ?> | |||
<?php if ($model->getClass() == 'Invoice'): ?> | |||
<?php if ($action == 'create' && $model->getClass() == 'Invoice'): ?> | |||
<template v-if="idUser > 0"> | |||
<strong>Bons de livraison</strong> | |||
<table v-if="deliveryNotes && deliveryNotes.length > 0" class="table table-bordered"> | |||
<table v-if="deliveryNoteCreateArray && deliveryNoteCreateArray.length > 0" class="table table-bordered"> | |||
<thead> | |||
<tr> | |||
<?php if ($action == 'create'): ?> | |||
<th></th><?php endif; ?> | |||
<th></th> | |||
<th>Libellé</th> | |||
<th v-if="taxRateProducer != 0">Montant (TTC)</th> | |||
<th v-else>Montant</th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<tr v-for="deliveryNote in deliveryNotes"> | |||
<?php if ($action == 'create'): ?> | |||
<td><input type="checkbox" name="Invoice[deliveryNotes][]" | |||
:value="deliveryNote.id"/></td> | |||
<?php endif; ?> | |||
<tr v-for="deliveryNote in deliveryNoteCreateArray"> | |||
<td><input type="checkbox" name="Invoice[deliveryNotes][]" :value="deliveryNote.id"/></td> | |||
<td>{{ deliveryNote.name }}</td> | |||
<td>{{ formatPrice(deliveryNote.total) }}</td> | |||
</tr> | |||
@@ -131,6 +127,49 @@ use common\models\Producer; | |||
<?php ActiveForm::end(); ?> | |||
</div> | |||
</div> | |||
<?php if ($action == 'update' && $model->getClass() == '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'): ?> | |||
@@ -154,6 +193,11 @@ use common\models\Producer; | |||
<div class="info-box-content"> | |||
<span class="info-box-text">Total<span v-if="taxRateProducer != 0"> (TTC)</span></span> | |||
<span class="info-box-number">{{ formatPrice(total_with_tax) }}</span> | |||
<p v-if="invoiceUrl"> | |||
<a class="btn btn-sm btn-default" :href="invoiceUrl"> | |||
<span class="glyphicon glyphicon-eye-open"></span> Voir la facture | |||
</a> | |||
</p> | |||
</div> | |||
</div> | |||
<div id="" class="info-box"> |
@@ -75,6 +75,15 @@ use dmstr\widgets\Alert; | |||
</section> | |||
<section class="content"> | |||
<?php $producer = GlobalParam::getCurrentProducer(); ?> | |||
<?php if(!$producer->isUpToDateWithOpendistribVersion() && $producer->option_display_message_new_opendistrib_version): ?> | |||
<div class="alert alert-warning"> | |||
<p>Opendistrib a été mis à jour vers la version <?= GlobalParam::getOpendistribVersion() ?> ! <a class="alert-link" href="<?= Yii::$app->urlManager->createUrl(['development/index']) ?>">Découvrir les nouveautés</a></p> | |||
<a href="<?= Yii::$app->urlManager->createUrl(['producer/update-opendistrib-version']) ?>" class="close"><span aria-hidden="true">×</span></a> | |||
</div> | |||
<?php endif; ?> | |||
<?= Alert::widget() ?> | |||
<?= $content ?> | |||
<div class="clr"></div> |
@@ -45,7 +45,7 @@ | |||
<?php | |||
$producer = GlobalParam::getCurrentProducer(); | |||
$newVersionOpendistribTemplate = ''; | |||
if($producer->latest_version_opendistrib != GlobalParam::getOpendistribVersion()) { | |||
if(!$producer->isUpToDateWithOpendistribVersion()) { | |||
$newVersionOpendistribTemplate = '<span class="pull-right-container"><small class="label pull-right bg-orange"> </small></span>'; | |||
} | |||
?> |
@@ -72,6 +72,13 @@ $this->addBreadcrumb($this->getTitle()); | |||
<div> | |||
<div v-show="currentSection == 'general'" class="panel panel-default"> | |||
<div class="panel-body"> | |||
<h4>Logiciel</h4> | |||
<?= $form->field($model, 'option_display_message_new_opendistrib_version') | |||
->dropDownList([ | |||
1 => 'Oui', | |||
0 => 'Non' | |||
], []); ?> | |||
<h4>Accès</h4> | |||
<?= $form->field($model, 'active') | |||
->dropDownList([ | |||
@@ -277,6 +284,11 @@ $this->addBreadcrumb($this->getTitle()); | |||
<h4>Exports</h4> | |||
<?= $form->field($model, 'option_csv_separator') | |||
->dropDownList([ | |||
';' => 'Point-virgule (;)', | |||
',' => 'Virgule (,)' | |||
], []); ?> | |||
<?= $form->field($model, 'option_csv_export_all_products') | |||
->dropDownList([ | |||
0 => 'Non', | |||
@@ -368,6 +380,9 @@ $this->addBreadcrumb($this->getTitle()); | |||
0 => 'Non', | |||
1 => 'Oui', | |||
], []); ?> | |||
<?= $form->field($model, 'option_online_payment_minimum_amount') | |||
->hint('Valeur par défaut si non défini : '.Producer::ONLINE_PAYMENT_MINIMUM_AMOUNT_DEFAULT.' €') | |||
->textInput(); ?> | |||
<?= $form->field($model, 'option_stripe_mode_test')->dropDownList([ | |||
0 => 'Non', | |||
1 => 'Oui' |
@@ -66,7 +66,8 @@ $this->render('_menu',[ | |||
<div class="panel-body"> | |||
<?php $form = ActiveForm::begin(); ?> | |||
<?= $form->field($mailForm, 'id_distribution')->dropDownList($incomingDistributionsArray) | |||
->hint("Sélectionnez une distribution pour ajouter automatiquement au message :<br /><ul><li>un lien vers la prise de commande de cette distribution</li><li>la liste des produits disponibles pour cette distribution</li></ul>"); ?> | |||
->hint("Sélectionnez une distribution pour ajouter automatiquement au message un lien vers la prise de commande de cette distribution"); ?> | |||
<?= $form->field($mailForm, 'integrate_product_list')->checkbox() ; ?> | |||
<?= $form->field($mailForm, 'subject')->textInput() ; ?> | |||
<?= $form->field($mailForm, 'message')->textarea(['rows' => '15']) ; ?> | |||
<div class="form-group"> |
@@ -1630,85 +1630,98 @@ body.skin-black .content-wrapper .alert a.btn { | |||
color: #333; | |||
text-decoration: none; | |||
} | |||
/* line 144, ../sass/_adminlte.scss */ | |||
/* line 142, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .alert .close { | |||
font-size: 30px; | |||
position: relative; | |||
top: -25px; | |||
text-decoration: none; | |||
color: white; | |||
opacity: 0.6; | |||
} | |||
/* line 150, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .alert .close:hover { | |||
opacity: 1; | |||
} | |||
/* line 157, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .callout h4 .fa { | |||
margin-right: 7px; | |||
} | |||
/* line 147, ../sass/_adminlte.scss */ | |||
/* line 160, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .callout a { | |||
color: white; | |||
} | |||
/* line 150, ../sass/_adminlte.scss */ | |||
/* line 163, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .callout .btn { | |||
color: #333; | |||
text-decoration: none; | |||
} | |||
/* line 157, ../sass/_adminlte.scss */ | |||
/* line 170, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .table th { | |||
font-size: 13px; | |||
} | |||
/* line 160, ../sass/_adminlte.scss */ | |||
/* line 173, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .table th.column-actions, body.skin-black .content-wrapper .table td.column-actions { | |||
width: 150px; | |||
text-align: right; | |||
} | |||
/* line 164, ../sass/_adminlte.scss */ | |||
/* line 177, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .table td.text-small, body.skin-black .content-wrapper .table th.text-small { | |||
font-size: 12px; | |||
} | |||
/* line 169, ../sass/_adminlte.scss */ | |||
/* line 182, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .pagination > .active > a, body.skin-black .content-wrapper .pagination > .active > span, body.skin-black .content-wrapper .pagination > .active > a:hover, body.skin-black .content-wrapper .pagination > .active > span:hover, body.skin-black .content-wrapper .pagination > .active > a:focus, body.skin-black .content-wrapper .pagination > .active > span:focus { | |||
background-color: #FF7F00; | |||
border: solid 1px #FF7F00; | |||
color: white; | |||
} | |||
/* line 174, ../sass/_adminlte.scss */ | |||
/* line 187, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .pagination > li > a, body.skin-black .content-wrapper .pagination > li > span { | |||
color: #FF7F00; | |||
} | |||
/* line 176, ../sass/_adminlte.scss */ | |||
/* line 189, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .pagination > li > a:hover, body.skin-black .content-wrapper .pagination > li > span:hover { | |||
color: #cc6600; | |||
} | |||
/* line 181, ../sass/_adminlte.scss */ | |||
/* line 194, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .submenu { | |||
margin-bottom: 25px; | |||
} | |||
/* line 187, ../sass/_adminlte.scss */ | |||
/* line 200, ../sass/_adminlte.scss */ | |||
body.skin-black .main-footer a { | |||
color: #FF7F00; | |||
} | |||
/* line 193, ../sass/_adminlte.scss */ | |||
/* line 206, ../sass/_adminlte.scss */ | |||
body.login-page { | |||
background: none; | |||
background-color: white; | |||
} | |||
/* line 197, ../sass/_adminlte.scss */ | |||
/* line 210, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-logo { | |||
text-align: center; | |||
font-family: "comfortaalight"; | |||
} | |||
/* line 200, ../sass/_adminlte.scss */ | |||
/* line 213, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-logo img { | |||
width: 50px; | |||
} | |||
/* line 205, ../sass/_adminlte.scss */ | |||
/* line 218, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body .btn-primary { | |||
background-color: #FF7F00; | |||
border-color: #FF7F00; | |||
padding: 5px 10px; | |||
} | |||
/* line 210, ../sass/_adminlte.scss */ | |||
/* line 223, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body .btn-primary:active { | |||
background-color: #ff8c1a; | |||
border-color: #FF7F00; | |||
} | |||
/* line 216, ../sass/_adminlte.scss */ | |||
/* line 229, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body a { | |||
color: #FF7F00; | |||
} | |||
/* line 218, ../sass/_adminlte.scss */ | |||
/* line 231, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body a:hover { | |||
color: #ff8c1a; | |||
} | |||
@@ -2480,6 +2493,26 @@ termes. | |||
width: 200px; | |||
} | |||
/* line 4, ../sass/development/_index.scss */ | |||
.development-index #panel-participate ul.contacts { | |||
padding: 0px; | |||
padding-left: 10px; | |||
margin: 0px; | |||
list-style-type: none; | |||
} | |||
/* line 10, ../sass/development/_index.scss */ | |||
.development-index #panel-participate ul.contacts li { | |||
padding-bottom: 10px; | |||
} | |||
/* line 13, ../sass/development/_index.scss */ | |||
.development-index #panel-participate ul.contacts li .glyphicon { | |||
float: left; | |||
} | |||
/* line 17, ../sass/development/_index.scss */ | |||
.development-index #panel-participate ul.contacts li p { | |||
padding-left: 25px; | |||
} | |||
/** | |||
Copyright distrib (2018) | |||
@@ -139,11 +139,13 @@ function opendistrib_products_event_price_with_tax() { | |||
taxRateSelected = 0; | |||
} | |||
var price = $('#product-price').val().replace(',', '.'); | |||
if (price) { | |||
$('#product-price-with-tax').val(getPriceWithTax(price, taxRateSelected)); | |||
// formattage | |||
$('#product-price').val(parseFloat(price).toFixed(3)); | |||
if($('#product-price').length) { | |||
var price = $('#product-price').val().replace(',', '.'); | |||
if (price) { | |||
$('#product-price-with-tax').val(getPriceWithTax(price, taxRateSelected)); | |||
// formattage | |||
$('#product-price').val(parseFloat(price).toFixed(3)); | |||
} | |||
} | |||
} | |||
@@ -39,7 +39,9 @@ var app = new Vue({ | |||
data: { | |||
taxRateProducer: null, | |||
document: [], | |||
deliveryNotes: [], | |||
deliveryNoteCreateArray: [], | |||
deliveryNoteUpdateArray: [], | |||
deliveryNoteAddId: 0, | |||
idDocument: 0, | |||
typeDocument: '', | |||
idUser: '', | |||
@@ -48,6 +50,7 @@ var app = new Vue({ | |||
productAddPrice: '', | |||
productAddQuantity: 1, | |||
ordersArray: [], | |||
invoiceUrl: null, | |||
total: 0, | |||
total_with_tax: 0 | |||
}, | |||
@@ -73,6 +76,7 @@ var app = new Vue({ | |||
app.idUser = response.data.id_user; | |||
app.productsArray = response.data.products; | |||
app.ordersArray = response.data.orders; | |||
app.invoiceUrl = response.data.invoice_url; | |||
app.total = response.data.total; | |||
app.total_with_tax = response.data.total_with_tax; | |||
@@ -129,7 +133,8 @@ var app = new Vue({ | |||
.then(function (response) { | |||
if (response.data.return == 'success') { | |||
Vue.set(app.document, 'address', response.data.address); | |||
app.deliveryNotes = response.data.delivery_notes; | |||
app.deliveryNoteCreateArray = response.data.delivery_note_create_array; | |||
app.deliveryNoteUpdateArray = response.data.delivery_note_update_array; | |||
} else { | |||
app.document.address = ''; | |||
} | |||
@@ -148,6 +153,35 @@ var app = new Vue({ | |||
app.init(); | |||
}); | |||
}, | |||
deleteDeliveryNoteOfInvoice: function(event) { | |||
var app = this; | |||
var idDeliveryNote = event.currentTarget.getAttribute('data-id'); | |||
axios.get(UrlManager.getBaseUrlAbsolute() + "invoice/ajax-delete-delivery-note", { | |||
params: { | |||
idInvoice: app.getDocumentId(), | |||
idDeliveryNote: idDeliveryNote | |||
} | |||
}) | |||
.then(function (response) { | |||
appAlerts.alertResponse(response); | |||
app.init(); | |||
}); | |||
}, | |||
submitDeliveryNoteAddToInvoice: function() { | |||
var app = this; | |||
axios.get(UrlManager.getBaseUrlAbsolute() + "invoice/ajax-add-delivery-note", { | |||
params: { | |||
idInvoice: this.getDocumentId(), | |||
idDeliveryNote: app.deliveryNoteAddId, | |||
} | |||
}) | |||
.then(function (response) { | |||
appAlerts.alertResponse(response); | |||
app.deliveryNoteAddId = 0; | |||
app.init(); | |||
}); | |||
}, | |||
getStepProductAdd: function () { | |||
var step = parseInt(this.getProductById(this.productAddId).step); | |||
if(!step) { | |||
@@ -178,8 +212,6 @@ var app = new Vue({ | |||
var price = pricesArray[i].price; | |||
var fromQuantity = pricesArray[i].from_quantity; | |||
console.log(pricesArray[i]); | |||
console.log(price+" / "+thePrice+" / "+fromQuantity+" / "+theQuantity+" / "); | |||
if (price < thePrice && fromQuantity <= theQuantity) { | |||
thePrice = price; | |||
} |
@@ -138,6 +138,19 @@ body.skin-black { | |||
color: #333 ; | |||
text-decoration: none ; | |||
} | |||
.close { | |||
font-size: 30px; | |||
position: relative; | |||
top: -25px; | |||
text-decoration: none; | |||
color: white; | |||
opacity: 0.6; | |||
&:hover { | |||
opacity: 1; | |||
} | |||
} | |||
} | |||
.callout { |
@@ -0,0 +1,23 @@ | |||
.development-index { | |||
#panel-participate { | |||
ul.contacts { | |||
padding: 0px; | |||
padding-left: 10px; | |||
margin: 0px; | |||
list-style-type: none; | |||
li { | |||
padding-bottom: 10px; | |||
.glyphicon { | |||
float: left; | |||
} | |||
p { | |||
padding-left: 25px; | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -1502,4 +1502,5 @@ a.btn, button.btn { | |||
@import "report/_index.scss" ; | |||
@import "document/_form.scss" ; | |||
@import "document/_index.scss" ; | |||
@import "development/_index.scss" ; | |||
@import "_responsive.scss" ; |
@@ -37,7 +37,7 @@ | |||
*/ | |||
return [ | |||
'version' => '22.11.A', | |||
'version' => '22.11.B', | |||
'adminEmail' => 'contact@opendistrib.net', | |||
'supportEmail' => 'contact@opendistrib.net', | |||
'user.passwordResetTokenExpire' => 3600, |
@@ -1,86 +1,80 @@ | |||
<?php | |||
/** | |||
Copyright distrib (2018) | |||
contact@opendistrib.net | |||
Ce logiciel est un programme informatique servant à aider les producteurs | |||
à distribuer leur production en circuits courts. | |||
Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||
respectant les principes de diffusion des logiciels libres. Vous pouvez | |||
utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||
de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||
sur le site "http://www.cecill.info". | |||
En contrepartie de l'accessibilité au code source et des droits de copie, | |||
de modification et de redistribution accordés par cette licence, il n'est | |||
offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||
seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||
titulaire des droits patrimoniaux et les concédants successifs. | |||
A cet égard l'attention de l'utilisateur est attirée sur les risques | |||
associés au chargement, à l'utilisation, à la modification et/ou au | |||
développement et à la reproduction du logiciel par l'utilisateur étant | |||
donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||
manipuler et qui le réserve donc à des développeurs et des professionnels | |||
avertis possédant des connaissances informatiques approfondies. Les | |||
utilisateurs sont donc invités à charger et tester l'adéquation du | |||
logiciel à leurs besoins dans des conditions permettant d'assurer la | |||
sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||
à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||
Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||
pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
termes. | |||
*/ | |||
/** | |||
* Copyright distrib (2018) | |||
* | |||
* contact@opendistrib.net | |||
* | |||
* Ce logiciel est un programme informatique servant à aider les producteurs | |||
* à distribuer leur production en circuits courts. | |||
* | |||
* Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||
* respectant les principes de diffusion des logiciels libres. Vous pouvez | |||
* utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||
* sur le site "http://www.cecill.info". | |||
* | |||
* En contrepartie de l'accessibilité au code source et des droits de copie, | |||
* de modification et de redistribution accordés par cette licence, il n'est | |||
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||
* seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||
* titulaire des droits patrimoniaux et les concédants successifs. | |||
* | |||
* A cet égard l'attention de l'utilisateur est attirée sur les risques | |||
* associés au chargement, à l'utilisation, à la modification et/ou au | |||
* développement et à la reproduction du logiciel par l'utilisateur étant | |||
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||
* manipuler et qui le réserve donc à des développeurs et des professionnels | |||
* avertis possédant des connaissances informatiques approfondies. Les | |||
* utilisateurs sont donc invités à charger et tester l'adéquation du | |||
* logiciel à leurs besoins dans des conditions permettant d'assurer la | |||
* sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||
* | |||
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||
* pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
* termes. | |||
*/ | |||
namespace common\helpers; | |||
class CSV | |||
class CSV | |||
{ | |||
public static function array2csv(array &$array) | |||
public static function array2csv(array &$array) | |||
{ | |||
if (count($array) == 0) { | |||
return null; | |||
} | |||
ob_start(); | |||
$df = fopen("php://output", 'w'); | |||
// clés | |||
//fputcsv($df, array_keys(reset($array))); | |||
foreach ($array as $row) { | |||
fputcsv($df, $row, ";"); | |||
} | |||
fclose($df); | |||
return ob_get_clean(); | |||
$separator = Producer::getConfig('option_csv_separator') ?: ';'; | |||
if (count($array) == 0) { | |||
return null; | |||
} | |||
ob_start(); | |||
$df = fopen("php://output", 'w'); | |||
// clés | |||
//fputcsv($df, array_keys(reset($array))); | |||
foreach ($array as $row) { | |||
fputcsv($df, $row, $separator); | |||
} | |||
fclose($df); | |||
return ob_get_clean(); | |||
} | |||
public static function downloadSendHeaders($filename) | |||
public static function downloadSendHeaders($filename) | |||
{ | |||
// disable caching | |||
$now = gmdate("D, d M Y H:i:s"); | |||
header("Expires: Tue, 03 Jul 2001 06:00:00 GMT"); | |||
header("Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate"); | |||
header("Last-Modified: {$now} GMT"); | |||
// disable caching | |||
$now = gmdate("D, d M Y H:i:s"); | |||
header("Expires: Tue, 03 Jul 2001 06:00:00 GMT"); | |||
header("Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate"); | |||
header("Last-Modified: {$now} GMT"); | |||
// force download | |||
header("Content-Type: application/force-download"); | |||
header("Content-Type: application/octet-stream"); | |||
header("Content-Type: application/download"); | |||
// force download | |||
header("Content-Type: application/force-download"); | |||
header("Content-Type: application/octet-stream"); | |||
header("Content-Type: application/download"); | |||
// disposition / encoding on response body | |||
header("Content-Disposition: attachment;filename={$filename}"); | |||
header("Content-Transfer-Encoding: binary"); | |||
// disposition / encoding on response body | |||
header("Content-Disposition: attachment;filename={$filename}"); | |||
header("Content-Transfer-Encoding: binary"); | |||
} | |||
/* | |||
* usage | |||
* download_send_headers("data_export_" . date("Y-m-d") . ".csv"); | |||
echo array2csv($array); | |||
die(); | |||
*/ | |||
} |
@@ -0,0 +1,65 @@ | |||
<?php | |||
/** | |||
* Copyright distrib (2018) | |||
* | |||
* contact@opendistrib.net | |||
* | |||
* Ce logiciel est un programme informatique servant à aider les producteurs | |||
* à distribuer leur production en circuits courts. | |||
* | |||
* Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||
* respectant les principes de diffusion des logiciels libres. Vous pouvez | |||
* utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||
* sur le site "http://www.cecill.info". | |||
* | |||
* En contrepartie de l'accessibilité au code source et des droits de copie, | |||
* de modification et de redistribution accordés par cette licence, il n'est | |||
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||
* seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||
* titulaire des droits patrimoniaux et les concédants successifs. | |||
* | |||
* A cet égard l'attention de l'utilisateur est attirée sur les risques | |||
* associés au chargement, à l'utilisation, à la modification et/ou au | |||
* développement et à la reproduction du logiciel par l'utilisateur étant | |||
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||
* manipuler et qui le réserve donc à des développeurs et des professionnels | |||
* avertis possédant des connaissances informatiques approfondies. Les | |||
* utilisateurs sont donc invités à charger et tester l'adéquation du | |||
* logiciel à leurs besoins dans des conditions permettant d'assurer la | |||
* sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||
* | |||
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||
* pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
* termes. | |||
*/ | |||
namespace common\helpers; | |||
class Opendistrib | |||
{ | |||
public static function getVersions() | |||
{ | |||
$versionsArray = []; | |||
$pathVersions = Yii::getAlias('@common/versions'); | |||
if(is_dir($pathVersions)) | |||
{ | |||
$directory = opendir($pathVersions); | |||
while( $child = readdir($directory) ){ | |||
if($child != '.' && $child != '..'){ | |||
$version = str_replace('.php', '', $child); | |||
$versionsArray[] = $version; | |||
} | |||
} | |||
} | |||
krsort($versionsArray); | |||
return $versionsArray; | |||
} | |||
} |
@@ -90,12 +90,12 @@ class DeliveryNote extends Document | |||
]; | |||
} | |||
public function isInvoiced() | |||
public function getInvoiceId() | |||
{ | |||
if($this->orders && count($this->orders) > 0) { | |||
foreach($this->orders as $order) { | |||
if($order->id_invoice) { | |||
return true; | |||
return $order->id_invoice; | |||
} | |||
} | |||
} | |||
@@ -103,4 +103,22 @@ class DeliveryNote extends Document | |||
return false; | |||
} | |||
public function isInvoiced() | |||
{ | |||
return (bool) $this->getInvoiceId(); | |||
} | |||
public function getInvoice() | |||
{ | |||
$invoice = null; | |||
$idInvoice = $this->getInvoiceId(); | |||
if($idInvoice) { | |||
$invoice = Invoice::searchOne([ | |||
'id' => $idInvoice | |||
]); | |||
} | |||
return $invoice; | |||
} | |||
} |
@@ -118,6 +118,8 @@ class Producer extends ActiveRecordCommon | |||
var $secret_key_payplug; | |||
const ONLINE_PAYMENT_MINIMUM_AMOUNT_DEFAULT = 25; | |||
/** | |||
* @inheritdoc | |||
*/ | |||
@@ -160,7 +162,8 @@ class Producer extends ActiveRecordCommon | |||
'order_deadline_sunday', | |||
'id_tax_rate_default', | |||
'document_quotation_duration', | |||
'option_dashboard_number_distributions' | |||
'option_dashboard_number_distributions', | |||
'option_online_payment_minimum_amount' | |||
], | |||
'integer' | |||
], | |||
@@ -179,6 +182,7 @@ class Producer extends ActiveRecordCommon | |||
'range' => [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] | |||
], | |||
['order_delay', 'in', 'range' => [1, 2, 3, 4, 5, 6, 7]], | |||
['option_csv_separator', 'in', 'range' => [',', ';']], | |||
[ | |||
'code', | |||
function ($attribute, $params) { | |||
@@ -225,7 +229,8 @@ class Producer extends ActiveRecordCommon | |||
'option_stripe_endpoint_secret', | |||
'option_online_payment_type', | |||
'option_tax_calculation_method', | |||
'latest_version_opendistrib' | |||
'latest_version_opendistrib', | |||
'option_csv_separator' | |||
], | |||
'string' | |||
], | |||
@@ -254,7 +259,8 @@ class Producer extends ActiveRecordCommon | |||
'option_stripe_mode_test', | |||
'option_notify_producer_order_summary', | |||
'option_billing_reduction', | |||
'option_export_evoliz' | |||
'option_export_evoliz', | |||
'option_display_message_new_opendistrib_version' | |||
], | |||
'boolean' | |||
], | |||
@@ -393,6 +399,9 @@ class Producer extends ActiveRecordCommon | |||
'option_tax_calculation_method' => 'Méthode de calcul de la TVA', | |||
'option_export_evoliz' => 'Activer l\'export vers Evoliz', | |||
'latest_version_opendistrib' => 'Dernière version d\'Opendistrib', | |||
'option_csv_separator' => 'Séparateur de colonnes (CSV)', | |||
'option_display_message_new_opendistrib_version' => 'Afficher les messages de mise à jour du logiciel Opendistrib', | |||
'option_online_payment_minimum_amount' => 'Paiement en ligne : montant minimum' | |||
]; | |||
} | |||
@@ -971,5 +980,26 @@ class Producer extends ActiveRecordCommon | |||
{ | |||
return $this->option_billing_type == self::BILLING_TYPE_FREE_PRICE; | |||
} | |||
public function isUpToDateWithOpendistribVersion() | |||
{ | |||
return $this->latest_version_opendistrib == GlobalParam::getOpendistribVersion(); | |||
} | |||
public function updateOpendistribVersion() { | |||
$versionsArray = Opendistrib::getVersions(); | |||
$this->latest_version_opendistrib = array_values($versionsArray)[0]; | |||
$this->save(); | |||
} | |||
public function getOnlinePaymentMinimumAmount() | |||
{ | |||
$onlinePaymentMinimumAmount = self::getConfig('option_online_payment_minimum_amount'); | |||
if(!$onlinePaymentMinimumAmount) { | |||
$onlinePaymentMinimumAmount = self::ONLINE_PAYMENT_MINIMUM_AMOUNT_DEFAULT; | |||
} | |||
return $onlinePaymentMinimumAmount; | |||
} | |||
} | |||
@@ -0,0 +1,14 @@ | |||
<h4>Date de sortie</h4> | |||
<ul> | |||
<li>22/11/2022</li> | |||
</ul> | |||
<h4>Évolutions</h4> | |||
<ul> | |||
<li>[Administration] Documents > factures : gestion des bons de livraison associés</li> | |||
<li>[Administration] Communiquer : possibilité de ne pas inclure la liste des produits dans le message</li> | |||
<li>[Administration] Paramètres : possibilité de configurer le séparateur CSV</li> | |||
<li>[Administration] Paramètres > paiement en ligne : montant minimum configurable</li> | |||
<li>[Administration] Développement : mise en avant des nouvelles versions et des informations de contact</li> | |||
</ul> |
@@ -0,0 +1,26 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
/** | |||
* Class m221109_082051_producer_add_option_csv_separator | |||
*/ | |||
class m221109_082051_producer_add_option_csv_separator extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('producer', 'option_csv_separator', Schema::TYPE_STRING.' DEFAULT \';\''); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('producer', 'option_csv_separator'); | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
/** | |||
* Class m221109_100033_producer_add_option_display_message_new_opendistrib_version | |||
*/ | |||
class m221109_100033_producer_add_option_display_message_new_opendistrib_version extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('producer', 'option_display_message_new_opendistrib_version', Schema::TYPE_BOOLEAN.' DEFAULT 1'); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('producer', 'option_display_message_new_opendistrib_version'); | |||
} | |||
/* | |||
// Use up()/down() to run migration code without a transaction. | |||
public function up() | |||
{ | |||
} | |||
public function down() | |||
{ | |||
echo "m221109_100033_producer_add_option_display_message_new_opendistrib_version cannot be reverted.\n"; | |||
return false; | |||
} | |||
*/ | |||
} |
@@ -0,0 +1,26 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
/** | |||
* Class m221115_085843_producer_add_option_online_payment_minimum_amount | |||
*/ | |||
class m221115_085843_producer_add_option_online_payment_minimum_amount extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('producer', 'option_online_payment_minimum_amount', Schema::TYPE_INTEGER); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('producer', 'option_online_payment_minimum_amount'); | |||
} | |||
} |
@@ -53,7 +53,7 @@ class CreditForm extends Model | |||
{ | |||
return [ | |||
[['amount'], 'required'], | |||
[['amount'], 'double', 'min' => 25], | |||
[['amount'], 'double', 'min' => Producer::getOnlinePaymentMinimumAmount()], | |||
]; | |||
} | |||
@@ -62,7 +62,7 @@ $this->addButton( | |||
'template' => '{label}<div class="input-group input-group-lg">{input}<span class="input-group-addon"><span class="glyphicon glyphicon-euro"></span></span></div>{hint}', | |||
]) | |||
->label('Quel montant souhaitez-vous créditer ?') | |||
->hint('Montant minimum : 25 €'); ?> | |||
->hint('Montant minimum : '.Producer::getOnlinePaymentMinimumAmount().' €'); ?> | |||
<div class="form-group"> | |||
<?= Html::submitButton('<span class="glyphicon glyphicon-lock"></span> Payer', ['class' => 'btn btn-primary'] |