Add phone limit creation to phone creation

This commit is contained in:
osaajani 2023-02-02 01:12:30 +01:00
parent fd1e7b5519
commit 298bba0c39
8 changed files with 231 additions and 21 deletions

View File

@ -311,7 +311,8 @@ footer img
}
/* SCHEDULEDS */
.add-number-button
.add-number-button,
.add-phone-limit-button
{
display: inline-block;
color: #DADFE1;
@ -319,7 +320,8 @@ footer img
vertical-align: top;
}
.add-number-button:hover
.add-number-button:hover,
.add-phone-limit-button:hover
{
color: #3498DB;
cursor: pointer;
@ -373,7 +375,8 @@ footer img
text-align: right;
}
.scheduleds-number-groupe
.scheduleds-number-groupe,
.phone-limits-group
{
padding-top: 15px;
padding-bottom: 15px;
@ -383,7 +386,8 @@ footer img
position: relative;
}
.scheduleds-number-groupe-remove
.scheduleds-number-groupe-remove,
.phone-limits-group-remove
{
position: absolute;
top: 15px;
@ -391,7 +395,8 @@ footer img
color: #888;
}
.scheduleds-number-groupe-remove:hover
.scheduleds-number-groupe-remove:hover,
.phone-limits-group-remove:hover
{
color: #555;
}

View File

@ -44,15 +44,15 @@ namespace controllers\internals;
}
/**
* Return a phone by his name.
* Return a list of phone limits
*
* @param string $name : Phone name
* @param int $id_phone : Phone id
*
* @return array
*/
public function get_by_name(string $name)
public function get_limits(int $id_phone)
{
return $this->get_model()->get_by_name($name);
return $this->get_model()->get_limits($id_phone);
}
/**
@ -137,10 +137,11 @@ namespace controllers\internals;
* @param string $name : The name of the phone
* @param string $adapter : The adapter to use the phone
* @param string json $adapter_data : A JSON string representing adapter's data (for example credentials for an api)
* @param array $limits : An array of limits for this phone. Each limit must be an array with a key volume and a key startpoint
*
* @return bool|int : false on error, new id on success
*/
public function create(int $id_user, string $name, string $adapter, string $adapter_data)
public function create(int $id_user, string $name, string $adapter, string $adapter_data, array $limits = [])
{
$phone = [
'id_user' => $id_user,
@ -149,7 +150,31 @@ namespace controllers\internals;
'adapter_data' => $adapter_data,
];
return $this->get_model()->insert($phone);
//Use transaction to garanty atomicity
$this->bdd->beginTransaction();
$new_phone_id = $this->get_model()->insert($phone);
if (!$new_phone_id)
{
$this->bdd->rollBack();
return false;
}
foreach ($limits as $limit)
{
$limit_id = $this->get_model()->insert_phone_limit($new_phone_id, $limit['volume'], $limit['startpoint']);
if (!$limit_id)
{
$this->bdd->rollBack();
return false;
}
}
$success = $this->bdd->commit();
return ($success ? $new_phone_id : false);
}
/**

View File

@ -165,6 +165,24 @@ namespace controllers\internals;
return $objectDate && $objectDate->format($format) === $date;
}
/**
* Check if a relative format date (see https://www.php.net/manual/en/datetime.formats.relative.php) is valid.
*
* @param string $date : Relative date
*
* @return bool : True if valid, false else
*/
public static function validate_relative_date($date)
{
try {
$d = new \DateTime($date);
} catch (\Throwable $th) {
return false;
}
return true;
}
/**
* Check if a sting represent a valid PHP period for creating an interval.
*

View File

@ -535,7 +535,7 @@ namespace controllers\publics;
return $this->json($return);
}
$name_exist = $this->internal_phone->get_by_name($name);
$name_exist = $this->internal_phone->get_by_name_and_user($this->user['id'], $name);
if ($name_exist)
{
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
@ -683,7 +683,7 @@ namespace controllers\publics;
}
$phone_with_same_name = $this->internal_phone->get_by_name($name);
$phone_with_same_name = $this->internal_phone->get_by_name_and_user($this->user['id'], $name);
if ($phone_with_same_name && $phone_with_same_name['id'] != $phone['id'])
{
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];

View File

@ -131,9 +131,10 @@ class Phone extends \descartes\Controller
* Create a new phone.
*
* @param $csrf : CSRF token
* @param string $_POST['name'] : Phone name
* @param string $_POST['adapter'] : Phone adapter
* @param array $_POST['adapter_data'] : Phone adapter data
* @param string $_POST['name'] : Phone name
* @param string $_POST['adapter'] : Phone adapter
* @param ?array $_POST['adapter_data'] : Phone adapter data
* @param ?array $_POST['limits'] : Limits in number of SMS for a period to be applied to this phone.
*/
public function create($csrf)
{
@ -148,6 +149,8 @@ class Phone extends \descartes\Controller
$name = $_POST['name'] ?? false;
$adapter = $_POST['adapter'] ?? false;
$adapter_data = !empty($_POST['adapter_data']) ? $_POST['adapter_data'] : [];
$limits = $_POST['limits'] ?? [];
$limits = is_array($limits) ? $limits : [$limits];
if (!$name || !$adapter)
{
@ -156,7 +159,7 @@ class Phone extends \descartes\Controller
return $this->redirect(\descartes\Router::url('Phone', 'add'));
}
$name_exist = $this->internal_phone->get_by_name($name);
$name_exist = $this->internal_phone->get_by_name_and_user($id_user, $name);
if ($name_exist)
{
\FlashMessage\FlashMessage::push('danger', 'Ce nom est déjà utilisé pour un autre téléphone.');
@ -164,6 +167,30 @@ class Phone extends \descartes\Controller
return $this->redirect(\descartes\Router::url('Phone', 'add'));
}
if ($limits)
{
foreach ($limits as $key => $limit)
{
$startpoint = $limit['startpoint'] ?? false;
$volume = $limit['volume'] ?? false;
if (!$startpoint || !$volume)
{
unset($limits[$key]);
continue;
}
$volume = (int) $volume;
$limits[$key]['volume'] = max($volume, 1);
if (!\controllers\internals\Tool::validate_relative_date($startpoint))
{
unset($limits[$key]);
continue;
}
}
}
$adapters = $this->internal_adapter->list_adapters();
$find_adapter = false;
foreach ($adapters as $metas)
@ -245,7 +272,7 @@ class Phone extends \descartes\Controller
return $this->redirect(\descartes\Router::url('Phone', 'add'));
}
$success = $this->internal_phone->create($id_user, $name, $adapter, $adapter_data);
$success = $this->internal_phone->create($id_user, $name, $adapter, $adapter_data, $limits);
if (!$success)
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer ce téléphone.');

View File

@ -0,0 +1,43 @@
<?php
use Phinx\Migration\AbstractMigration;
class AddPhoneLimits extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* addCustomColumn
* renameColumn
* addIndex
* addForeignKey
*
* Any other destructive changes will result in an error when trying to
* rollback the migration.
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('phone_limit');
$table->addColumn('id_phone', 'integer', ['null' => false])
->addColumn('volume', 'integer', ['null' => false])
->addColumn('startpoint', 'string', ['null' => false, 'limit' => 254]) # A relative time to use as startpoint for counting volume. See https://www.php.net/manual/en/datetime.formats.relative.php
->addColumn('created_at', 'timestamp', ['null' => false, 'default' => 'CURRENT_TIMESTAMP'])
->addColumn('updated_at', 'timestamp', ['null' => true, 'update' => 'CURRENT_TIMESTAMP'])
->addForeignKey('id_phone', 'phone', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
->create();
}
}

View File

@ -15,7 +15,7 @@ namespace models;
{
/**
* Return all hones that belongs to active users
* Return all phones that belongs to active users
*
* @return array
*/
@ -63,6 +63,48 @@ namespace models;
return $this->_select_one('phone', ['name' => $name]);
}
/**
* Return a list of phone limits
*
* @param int $id_phone : Phone id
*
* @return array
*/
public function get_limits(int $id_phone)
{
return $this->_select('phone_limit', ['id_phone' => $id_phone]);
}
/**
* Add a limit for a phone.
*
* @param int $id_phone : Phone id
* @param int $volume : Limit in volume of SMS
* @param string $startpoint : A relative time to use as startpoint for counting volume. See https://www.php.net/manual/en/datetime.formats.relative.php
*
* @return mixed (bool|int) : False on error, new row id else
*/
public function insert_phone_limit(int $id_phone, int $volume, string $startpoint)
{
$success = $this->_insert('phone_limit', ['id_phone' => $id_phone, 'volume' => $volume, 'startpoint' => $startpoint]);
return $success ? $this->_last_id() : false;
}
/**
* Delete limits for a phone
*
* @param array $id_phone : Phone id
*
* @return array
*/
public function delete_phone_limits(int $id_phone)
{
return $this->_delete('phone_limit', ['id_phone' => $id_phone]);
}
/**
* Return table name.
*/

View File

@ -48,7 +48,7 @@
</div>
</div>
<div class="form-group">
<label>Type de téléphone : </label>
<label>Type de téléphone</label>
<p class="italic small help" id="description-adapter-general">
Le type de téléphone utilisé par RaspiSMS pour envoyer ou recevoir les SMS. Pour plus d'information, consultez <a href="https://documentation.raspisms.fr/users/adapters/overview.html" target="_blank">la documentation de RaspiSMS</a> concernant les différents types de téléphones.
</p>
@ -67,7 +67,7 @@
<?php } ?>
</select>
</div>
<div id="adapter-data-container" class="form-group">
<div id="adapter-data-container" class="form-group well">
<div id="adapter-data-description-container">
<h4>Description du téléphone</h4>
<div id="adapter-data-description"></div>
@ -77,6 +77,15 @@
<h4>Réglages du téléphone</h4>
<div id="adapter-data-fields"></div>
</div>
</div>
<div class="form-group">
<label>Limites des volumes d'envoi du téléphone</label>
<p class="italic small help">
Défini le nombre maximum de SMS qui pourront être envoyés avec ce téléphone sur des périodes de temps données.
</p>
<div class="form-group phone-limits-container container-fluid">
<div class="text-center"><div class="add-phone-limit-button fa fa-plus-circle"></div></div>
</div>
</div>
<a class="btn btn-danger" href="<?php echo \descartes\Router::url('Phone', 'list'); ?>">Annuler</a>
<input type="submit" class="btn btn-success" value="Enregistrer le téléphone" />
@ -174,6 +183,47 @@
{
change_adapter();
});
jQuery('body').on('click', '.phone-limits-group-remove', function (e)
{
e.preventDefault();
jQuery(this).parent('.phone-limits-group').remove();
return false;
});
jQuery('body').on('click', '.add-phone-limit-button', function(e)
{
var random_id = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
var newLimit = '' +
'<div class="row phone-limits-group">'+
'<div class="col-xs-4">'+
'<label>Période</label><br/>'+
'<select name="limits[' + random_id + '][startpoint]" class="form-control" id="adapter-select" required>'+
'<option value="" disabled selected>Période sur laquelle appliquer la limite</option>'+
'<option value="today">Par jour</option>'+
'<option value="-24 hours">24 heures glissantes</option>'+
'<option value="this week midnight">Cette semaine</option>'+
'<option value="-7 days">7 jours glissants</option>'+
'<option value="this week midnight -1 week">Ces deux dernières semaines</option>'+
'<option value="-14 days">14 jours glissants</option>'+
'<option value="this month midnight">Ce mois</option>'+
'<option value="-1 month">1 mois glissant</option>'+
'<option value="-28 days">28 jours glissants</option>'+
'<option value="-30 days">30 jours glissants</option>'+
'<option value="-31 days">31 jours glissants</option>'+
'</select>'+
'</div>'+
'<div class="scheduleds-number-data-container col-xs-8">'+
'<label>Volume</label>'+
'<div class="form-group">'+
'<input name="limits[' + random_id + '][volume]" class="form-control" type="number" min="1" placeholder="Nombre de SMS maximum sur la période.">'+
'</div>'+
'</div>'+
'<a href="#" class="phone-limits-group-remove"><span class="fa fa-times"></span></a>'+
'</div>';
jQuery(this).parent('div').before(newLimit);
});
});
</script>
<?php