mirror of
https://github.com/devcode-it/openstamanager.git
synced 2025-02-16 19:40:44 +01:00
Merge branch 'master' of https://github.com/devcode-it/openstamanager
This commit is contained in:
commit
5999abf86e
11
CHANGELOG.md
11
CHANGELOG.md
@ -4,6 +4,7 @@ Tutti i maggiori cambiamenti di questo progetto saranno documentati in questo fi
|
||||
|
||||
Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://keepachangelog.com/), e il progetto segue il [Semantic Versioning](http://semver.org/) per definire le versioni delle release.
|
||||
|
||||
- [2.4.26 (2021-09-24)](#2426-2021-09-24)
|
||||
- [2.4.25 (2021-08-25)](#2425-2021-08-25)
|
||||
- [2.4.24 (2021-07-28)](#2424-2021-07-28)
|
||||
- [2.4.23 (2021-05-18)](#2423-2021-05-18)
|
||||
@ -36,15 +37,21 @@ Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://k
|
||||
- [2.2 (2016-11-10)](#22-2016-11-10)
|
||||
- [2.1 (2015-04-02)](#21-2015-04-02)
|
||||
|
||||
## 2.4.26 (2021-00-00)
|
||||
## 2.4.26 (2021-09-24)
|
||||
|
||||
### Aggiunto (Added)
|
||||
- Aggiunto modal in fase di **Stampa Bilancio** per visualizzare o meno l'elenco analitico dei clienti e fornitori
|
||||
- Aggiunta scelta del tipo documento in fase di creazione fattura da un altro documento
|
||||
- Aggiunta possibilità di creare delle ricorrenze per gli **Interventi** in fase di aggiunta
|
||||
- Aggiunta scelta del tipo documento in fase di creazione fattura da un azione di gruppo di un altro documento
|
||||
- Aggiunta sistema di gestione Combinazioni Articoli
|
||||
### Modificato (Changed)
|
||||
|
||||
- Modificata query per generare liste in **Newsletter**
|
||||
### Fixed
|
||||
- Fix orario della modifica del listino di riferimento dell'articolo
|
||||
- Fix movimentazione articoli tra due sedi tramite **DDT**
|
||||
- Fix duplicazione **Pagamenti**
|
||||
|
||||
## 2.4.25 (2021-08-25)
|
||||
|
||||
### Aggiunto (Added)
|
||||
|
@ -293,6 +293,14 @@ Input.prototype.set = function (value) {
|
||||
CKEDITOR.instances[name].setData(value);
|
||||
} else {
|
||||
this.element.val(value).trigger("change");
|
||||
|
||||
// Impostazione valore per checkbox
|
||||
let group = this.element.closest(".form-group");
|
||||
if (group.find("input[type=checkbox]").length) {
|
||||
value = value === true || parseInt(value) !== 1;
|
||||
group.find("[type=hidden]").val(+value).trigger('change')
|
||||
group.find("[type=checkbox]").prop("checked", value);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
|
@ -399,6 +399,7 @@ function release(done) {
|
||||
'!include/custom/**',
|
||||
'!backup/**',
|
||||
'!files/**',
|
||||
'files/temp/.gitkeep',
|
||||
'!logs/**',
|
||||
'!config.inc.php',
|
||||
'!update/structure.php',
|
||||
|
@ -202,7 +202,7 @@ if (filter('action') == 'do_update') {
|
||||
|
||||
foreach ($updates as $update) {
|
||||
if ($update['sql'] && (!empty($update['done']) || is_null($update['done']))) {
|
||||
$queries = readSQLFile(base_dir().$update['directory'].$update['filename'].'.sql', ';');
|
||||
$queries = readSQLFile(base_dir().'/'.$update['directory'].$update['filename'].'.sql', ';');
|
||||
$total += count($queries);
|
||||
|
||||
if (intval($update['done']) > 1) {
|
||||
@ -214,7 +214,7 @@ if (filter('action') == 'do_update') {
|
||||
$total += $scriptValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
echo '
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
|
@ -35,6 +35,10 @@ if (!isset($_SESSION['module_'.$id_fatture]['id_segment'])) {
|
||||
}
|
||||
$id_segment = $_SESSION['module_'.$id_fatture]['id_segment'];
|
||||
$idconto = setting('Conto predefinito fatture di vendita');
|
||||
$idtipodocumento = $dbo->selectOne('co_tipidocumento', ['id'], [
|
||||
'predefined' => 1,
|
||||
'dir' => 'entrata',
|
||||
])['id'];
|
||||
|
||||
switch (post('op')) {
|
||||
case 'crea_fattura':
|
||||
@ -42,8 +46,7 @@ switch (post('op')) {
|
||||
$numero_totale = 0;
|
||||
|
||||
// Informazioni della fattura
|
||||
$descrizione_tipo = 'Fattura immediata di vendita';
|
||||
$tipo_documento = Tipo::where('descrizione', $descrizione_tipo)->first();
|
||||
$tipo_documento = Tipo::where('id', post('idtipodocumento'))->first();
|
||||
|
||||
$stato_documenti_accodabili = Stato::where('descrizione', 'Bozza')->first();
|
||||
$accodare = post('accodare');
|
||||
@ -125,7 +128,9 @@ $operations['crea_fattura'] = [
|
||||
'text' => '<span><i class="fa fa-file-code-o"></i> '.tr('Fattura _TYPE_', ['_TYPE_' => strtolower($module['name'])]),
|
||||
'data' => [
|
||||
'title' => tr('Fatturare i _TYPE_ selezionati?', ['_TYPE_' => strtolower($module['name'])]),
|
||||
'msg' => '{[ "type": "checkbox", "label": "<small>'.tr('Aggiungere alle fatture di vendita non ancora emesse?').'</small>", "placeholder": "'.tr('Aggiungere alle fatture esistenti non ancora emesse?').'", "name": "accodare" ]}<br>{[ "type": "select", "label": "'.tr('Sezionale').'", "name": "id_segment", "required": 1, "values": "query=SELECT id, name AS descrizione FROM zz_segments WHERE id_module=\''.$id_fatture.'\' AND is_fiscale = 1 ORDER BY name", "value": "'.$id_segment.'" ]}',
|
||||
'msg' => '{[ "type": "checkbox", "label": "<small>'.tr('Aggiungere alle fatture di vendita non ancora emesse?').'</small>", "placeholder": "'.tr('Aggiungere alle fatture esistenti non ancora emesse?').'", "name": "accodare" ]}<br>
|
||||
{[ "type": "select", "label": "'.tr('Sezionale').'", "name": "id_segment", "required": 1, "values": "query=SELECT id, name AS descrizione FROM zz_segments WHERE id_module=\''.$id_fatture.'\' AND is_fiscale = 1 ORDER BY name", "value": "'.$id_segment.'" ]}<br>
|
||||
{[ "type": "select", "label": "'.tr('Tipo documento').'", "name": "idtipodocumento", "required": 1, "values": "query=SELECT id, CONCAT(codice_tipo_documento_fe, \' - \', descrizione) AS descrizione FROM co_tipidocumento WHERE enabled = 1 AND dir =\'entrata\' ORDER BY codice_tipo_documento_fe", "value": "'.$idtipodocumento.'" ]}',
|
||||
'button' => tr('Procedi'),
|
||||
'class' => 'btn btn-lg btn-warning',
|
||||
'blank' => false,
|
||||
|
@ -50,8 +50,10 @@ class Contratto extends Document
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = [
|
||||
'data_bozza',
|
||||
'data_conclusione',
|
||||
'data_accettazione',
|
||||
'data_rifiuto',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -41,6 +41,10 @@ if (!isset($_SESSION['module_'.$id_fatture]['id_segment'])) {
|
||||
}
|
||||
$id_segment = $_SESSION['module_'.$id_fatture]['id_segment'];
|
||||
$idconto = setting('Conto predefinito fatture di vendita');
|
||||
$idtipodocumento = $dbo->selectOne('co_tipidocumento', ['id'], [
|
||||
'predefined' => 1,
|
||||
'dir' => $dir,
|
||||
])['id'];
|
||||
|
||||
switch (post('op')) {
|
||||
case 'crea_fattura':
|
||||
@ -48,13 +52,7 @@ switch (post('op')) {
|
||||
$numero_totale = 0;
|
||||
|
||||
// Informazioni della fattura
|
||||
if ($dir == 'entrata') {
|
||||
$descrizione_tipo = 'Fattura immediata di vendita';
|
||||
} else {
|
||||
$descrizione_tipo = 'Fattura immediata di acquisto';
|
||||
}
|
||||
|
||||
$tipo_documento = Tipo::where('descrizione', $descrizione_tipo)->first();
|
||||
$tipo_documento = Tipo::where('id', post('idtipodocumento'))->first();
|
||||
|
||||
$stato_documenti_accodabili = Stato::where('descrizione', 'Bozza')->first();
|
||||
$accodare = post('accodare');
|
||||
@ -180,8 +178,9 @@ $operations['crea_fattura'] = [
|
||||
'text' => '<span><i class="fa fa-file-code-o"></i> '.tr('Fattura _TYPE_', ['_TYPE_' => strtolower($module['name'])]),
|
||||
'data' => [
|
||||
'title' => tr('Fatturare i _TYPE_ selezionati?', ['_TYPE_' => strtolower($module['name'])]),
|
||||
'msg' => '{[ "type": "checkbox", "label": "<small>'.tr('Aggiungere alle _TYPE_ non ancora emesse?', ['_TYPE_' => strtolower($module_fatture)]).'", "placeholder": "'.tr('Aggiungere alle _TYPE_ nello stato bozza?', ['_TYPE_' => strtolower($module_fatture)]).'</small>", "name": "accodare" ]}
|
||||
<br>{[ "type": "select", "label": "'.tr('Sezionale').'", "name": "id_segment", "required": 1, "values": "query=SELECT id, name AS descrizione FROM zz_segments WHERE id_module=\''.$id_fatture.'\' AND is_fiscale = 1 ORDER BY name", "value": "'.$id_segment.'" ]}',
|
||||
'msg' => '{[ "type": "checkbox", "label": "<small>'.tr('Aggiungere alle _TYPE_ non ancora emesse?', ['_TYPE_' => strtolower($module_fatture)]).'", "placeholder": "'.tr('Aggiungere alle _TYPE_ nello stato bozza?', ['_TYPE_' => strtolower($module_fatture)]).'</small>", "name": "accodare" ]}<br>
|
||||
{[ "type": "select", "label": "'.tr('Sezionale').'", "name": "id_segment", "required": 1, "values": "query=SELECT id, name AS descrizione FROM zz_segments WHERE id_module=\''.$id_fatture.'\' AND is_fiscale = 1 ORDER BY name", "value": "'.$id_segment.'" ]}<br>
|
||||
{[ "type": "select", "label": "'.tr('Tipo documento').'", "name": "idtipodocumento", "required": 1, "values": "query=SELECT id, CONCAT(codice_tipo_documento_fe, \' - \', descrizione) AS descrizione FROM co_tipidocumento WHERE enabled = 1 AND dir ='.prepare($dir).' ORDER BY codice_tipo_documento_fe", "value": "'.$idtipodocumento.'" ]}',
|
||||
'button' => tr('Procedi'),
|
||||
'class' => 'btn btn-lg btn-warning',
|
||||
'blank' => false,
|
||||
|
@ -23,6 +23,8 @@ use Carbon\Carbon;
|
||||
use Common\SimpleModelTrait;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Modules\Emails\OAuth2\Google;
|
||||
use Modules\Emails\OAuth2\Microsoft;
|
||||
use Notifications\EmailNotification;
|
||||
use Traits\LocalPoolTrait;
|
||||
|
||||
@ -32,14 +34,20 @@ class Account extends Model
|
||||
use LocalPoolTrait;
|
||||
use SoftDeletes;
|
||||
|
||||
protected $table = 'em_accounts';
|
||||
|
||||
protected $casts = [
|
||||
'oauth2_config' => 'array',
|
||||
public static $providers = [
|
||||
'microsoft' => [
|
||||
'name' => 'Microsoft',
|
||||
'class' => Microsoft::class,
|
||||
'help' => 'https://docs.openstamanager.com/faq/configurazione-oauth2#microsoft',
|
||||
],
|
||||
'google' => [
|
||||
'name' => 'Google',
|
||||
'class' => Google::class,
|
||||
'help' => 'https://docs.openstamanager.com/faq/configurazione-oauth2#google',
|
||||
],
|
||||
];
|
||||
|
||||
/** @var OAuth2 */
|
||||
protected $gestoreOAuth2;
|
||||
protected $table = 'em_accounts';
|
||||
|
||||
public function testConnection()
|
||||
{
|
||||
@ -61,17 +69,6 @@ class Account extends Model
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getGestoreOAuth2()
|
||||
{
|
||||
if (isset($this->gestoreOAuth2)) {
|
||||
return $this->gestoreOAuth2;
|
||||
}
|
||||
|
||||
$this->gestoreOAuth2 = new OAuth2($this);
|
||||
|
||||
return $this->gestoreOAuth2;
|
||||
}
|
||||
|
||||
/* Relazioni Eloquent */
|
||||
|
||||
public function templates()
|
||||
@ -79,6 +76,11 @@ class Account extends Model
|
||||
return $this->hasMany(Template::class, 'id_account');
|
||||
}
|
||||
|
||||
public function oauth2()
|
||||
{
|
||||
return $this->belongsTo(\Models\OAuth2::class, 'id_oauth2');
|
||||
}
|
||||
|
||||
public function emails()
|
||||
{
|
||||
return $this->hasMany(Mail::class, 'id_account');
|
||||
|
@ -95,9 +95,9 @@ class EmailHook extends Manager
|
||||
}
|
||||
|
||||
// Invio effettivo
|
||||
foreach ($lista as $lista_account) {
|
||||
foreach ($lista as $mail) {
|
||||
try {
|
||||
$email = EmailNotification::build($lista_account);
|
||||
$email = EmailNotification::build($mail);
|
||||
$email->send();
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
@ -1,170 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Emails;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
|
||||
use League\OAuth2\Client\Token\AccessToken;
|
||||
use Modules\Emails\OAuth2\Google;
|
||||
use Modules\Emails\OAuth2\Microsoft;
|
||||
|
||||
class OAuth2
|
||||
{
|
||||
public static $providers = [
|
||||
'microsoft' => [
|
||||
'name' => 'Microsoft',
|
||||
'class' => Microsoft::class,
|
||||
'help' => 'https://docs.openstamanager.com/faq/configurazione-oauth2#microsoft',
|
||||
],
|
||||
'google' => [
|
||||
'name' => 'Google',
|
||||
'class' => Google::class,
|
||||
'help' => 'https://docs.openstamanager.com/faq/configurazione-oauth2#google',
|
||||
],
|
||||
];
|
||||
|
||||
protected $provider;
|
||||
protected $account;
|
||||
|
||||
public function __construct(Account $account)
|
||||
{
|
||||
$this->account = $account;
|
||||
|
||||
// Inizializza il provider per l'autenticazione OAuth2.
|
||||
$redirect_uri = base_url().'/oauth2.php';
|
||||
|
||||
$class = $this->getProviderConfiguration()['class'];
|
||||
$this->provider = new $class($this->account, $redirect_uri);
|
||||
}
|
||||
|
||||
public function getProvider()
|
||||
{
|
||||
return $this->provider;
|
||||
}
|
||||
|
||||
public function getProviderConfiguration()
|
||||
{
|
||||
return self::$providers[$this->account->provider];
|
||||
}
|
||||
|
||||
public function needsConfiguration()
|
||||
{
|
||||
$access_token = $this->getAccessToken();
|
||||
|
||||
return empty($access_token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gestisce le operazioni di configurazione per l'autenticazione OAuth2.
|
||||
* Restituisce l'URL di redirect per le operazioni di aggiornamento dei dati, lancia un eccezione in caso di errori e restituisce null in caso di completamento della configurazione.
|
||||
*
|
||||
* Nota: l'autenticazione OAuth2 richiede una serie di richieste su una singola pagina
|
||||
* - Richiesta di autenticazione al server remoto (code, state vuoti)
|
||||
* - Conferma di autenticazione alla pagina di redirect (code, state impostati)
|
||||
* - Richiesta del token di accesso dalla pagina di redirect al server remoto
|
||||
*
|
||||
* @param string|null $code
|
||||
* @param string|null $state
|
||||
*
|
||||
* @throws IdentityProviderException
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function configure($code, $state)
|
||||
{
|
||||
if (!$this->needsConfiguration()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$provider = $this->getProvider();
|
||||
$options = $provider->getOptions();
|
||||
if (empty($code)) {
|
||||
// Fetch the authorization URL from the provider; this returns the
|
||||
// urlAuthorize option and generates and applies any necessary parameters
|
||||
// (e.g. state).
|
||||
$authorization_url = $provider->getAuthorizationUrl($options);
|
||||
|
||||
// Get the state generated for you and store it to the session.
|
||||
$this->account->oauth2_state = $provider->getState();
|
||||
$this->account->save();
|
||||
|
||||
// Redirect the user to the authorization URL.
|
||||
return $authorization_url;
|
||||
} elseif (!empty($this->account->oauth2_state) && $this->account->oauth2_state !== $state) {
|
||||
$this->account->oauth2_state = null;
|
||||
$this->account->save();
|
||||
|
||||
throw new InvalidArgumentException();
|
||||
} else {
|
||||
$this->account->oauth2_state = null;
|
||||
$this->account->save();
|
||||
|
||||
// Try to get an access token using the authorization code grant
|
||||
$access_token = $provider->getAccessToken('authorization_code', [
|
||||
'code' => $code,
|
||||
]);
|
||||
$refresh_token = $access_token->getRefreshToken();
|
||||
|
||||
$this->updateTokens($access_token, $refresh_token);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getRefreshToken()
|
||||
{
|
||||
$this->checkTokens();
|
||||
|
||||
return $this->account->refresh_token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restituisce l'access token per l'autenticazione OAuth2.
|
||||
*
|
||||
* @return AccessToken|null
|
||||
*/
|
||||
public function getAccessToken()
|
||||
{
|
||||
$this->checkTokens();
|
||||
|
||||
return unserialize($this->account->access_token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Imposta l'access token per l'autenticazione OAuth2.
|
||||
*
|
||||
* @param AccessToken|null
|
||||
*/
|
||||
public function updateTokens($access_token, $refresh_token)
|
||||
{
|
||||
$this->account->access_token = serialize($access_token);
|
||||
|
||||
$previous_refresh_token = $this->account->refresh_token;
|
||||
$this->account->refresh_token = $refresh_token ?: $previous_refresh_token;
|
||||
|
||||
$this->account->save();
|
||||
}
|
||||
|
||||
protected function checkTokens()
|
||||
{
|
||||
$access_token = unserialize($this->account->access_token);
|
||||
|
||||
if (!empty($access_token) && $access_token->hasExpired()) {
|
||||
// Tentativo di refresh del token di accesso
|
||||
$refresh_token = $this->account->refresh_token;
|
||||
if (!empty($refresh_token)) {
|
||||
$access_token = $this->getProvider()->getAccessToken('refresh_token', [
|
||||
'refresh_token' => $this->account->refresh_token,
|
||||
]);
|
||||
|
||||
$refresh_token = $access_token->getRefreshToken();
|
||||
} else {
|
||||
$access_token = null;
|
||||
$refresh_token = null;
|
||||
}
|
||||
|
||||
$this->updateTokens($access_token, $refresh_token);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@
|
||||
namespace Modules\Emails\OAuth2;
|
||||
|
||||
use League\OAuth2\Client\Provider\Google as OriginalProvider;
|
||||
use Modules\Emails\Account;
|
||||
|
||||
class Google extends OriginalProvider implements ProviderInterface
|
||||
{
|
||||
@ -12,16 +11,6 @@ class Google extends OriginalProvider implements ProviderInterface
|
||||
'accessType' => 'offline',
|
||||
];
|
||||
|
||||
public function __construct(Account $account, $redirect_uri)
|
||||
{
|
||||
parent::__construct([
|
||||
'clientId' => $account->client_id,
|
||||
'clientSecret' => $account->client_secret,
|
||||
'redirectUri' => $redirect_uri,
|
||||
'accessType' => 'offline',
|
||||
]);
|
||||
}
|
||||
|
||||
public function getOptions()
|
||||
{
|
||||
return self::$options;
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
namespace Modules\Emails\OAuth2;
|
||||
|
||||
use Modules\Emails\Account;
|
||||
use TheNetworg\OAuth2\Client\Provider\Azure;
|
||||
|
||||
class Microsoft extends Azure implements ProviderInterface
|
||||
@ -24,18 +23,15 @@ class Microsoft extends Azure implements ProviderInterface
|
||||
],
|
||||
];
|
||||
|
||||
public function __construct(Account $account, $redirect_uri)
|
||||
public function __construct(array $options = [], array $collaborators = [])
|
||||
{
|
||||
parent::__construct([
|
||||
'clientId' => $account->client_id,
|
||||
'clientSecret' => $account->client_secret,
|
||||
'redirectUri' => $redirect_uri,
|
||||
'accessType' => 'offline',
|
||||
// Configurazioni specifiche per il provider di Microsoft Azure
|
||||
$config = array_merge($options, [
|
||||
'defaultEndPointVersion' => parent::ENDPOINT_VERSION_2_0,
|
||||
'tenant' => $options['tenant_id'],
|
||||
]);
|
||||
|
||||
// Configurazioni specifiche per il provider di Microsoft Azure
|
||||
$this->defaultEndPointVersion = parent::ENDPOINT_VERSION_2_0;
|
||||
$this->tenant = $account->oauth2_config['tenant_id'];
|
||||
parent::__construct($config, $collaborators);
|
||||
}
|
||||
|
||||
public function getOptions()
|
||||
|
@ -2,12 +2,8 @@
|
||||
|
||||
namespace Modules\Emails\OAuth2;
|
||||
|
||||
use Modules\Emails\Account;
|
||||
|
||||
interface ProviderInterface
|
||||
{
|
||||
public function __construct(Account $account, $redirect_uri);
|
||||
|
||||
/**
|
||||
* Restituisce l'array di configurazione per la connessione remota al servizio del provider.
|
||||
*
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
include_once __DIR__.'/../../core.php';
|
||||
|
||||
use Modules\Fatture\Fattura;
|
||||
|
||||
$module = Modules::get($id_module);
|
||||
|
||||
if ($module['name'] == 'Fatture di vendita') {
|
||||
@ -29,9 +31,9 @@ if ($module['name'] == 'Fatture di vendita') {
|
||||
$conti = 'conti-acquisti';
|
||||
}
|
||||
|
||||
$info = $dbo->fetchOne('SELECT * FROM co_documenti WHERE id='.prepare($id_record));
|
||||
$numero = ($info['numero_esterno'] != '') ? $info['numero_esterno'] : $info['numero'];
|
||||
$idanagrafica = $info['idanagrafica'];
|
||||
$fattura = Fattura::find($id_record);
|
||||
$numero = ($fattura->numero_esterno != '') ? $fattura->numero_esterno : $fattura->numero;
|
||||
$idanagrafica = $fattura->idanagrafica;
|
||||
|
||||
$idconto = ($dir == 'entrata') ? setting('Conto predefinito fatture di vendita') : setting('Conto predefinito fatture di acquisto');
|
||||
|
||||
@ -108,7 +110,7 @@ $options['id_ritenuta_acconto_predefined'] = $ritenuta_acconto['id_ritenuta_acco
|
||||
echo App::internalLoad('conti.php', [], $options);
|
||||
|
||||
// Leggo l'iva predefinita dall'articolo e se non c'è leggo quella predefinita generica
|
||||
$idiva = $idiva ?: setting('Iva predefinita');
|
||||
$idiva = $fattura->anagrafica->idiva_vendite ?: setting('Iva predefinita');
|
||||
|
||||
// Iva
|
||||
echo '
|
||||
|
@ -23,6 +23,7 @@ use Modules\Anagrafiche\Nazione;
|
||||
use Modules\Fatture\Gestori\Bollo;
|
||||
use Modules\Interventi\Intervento;
|
||||
use Modules\Iva\Aliquota;
|
||||
use Plugins\ExportFE\Interaction;
|
||||
|
||||
include_once __DIR__.'/../../core.php';
|
||||
|
||||
@ -228,7 +229,7 @@ elseif ($record['stato'] == 'Bozza') {
|
||||
?>
|
||||
|
||||
<div class="col-md-2" <?php echo ($is_fiscale) ? '' : 'hidden'; ?> >
|
||||
{[ "type": "select", "label": "<?php echo tr('Stato FE'); ?>", "name": "codice_stato_fe", "values": "query=SELECT codice as id, CONCAT_WS(' - ',codice,descrizione) as text FROM fe_stati_documento", "value": "$codice_stato_fe$", "disabled": <?php echo intval(API\Services::isEnabled() || ($record['stato'] == 'Bozza' && $abilita_genera)); ?>, "class": "unblockable", "help": "<?php echo (!empty($record['data_stato_fe'])) ? Translator::timestampToLocale($record['data_stato_fe']) : ''; ?>" ]}
|
||||
{[ "type": "select", "label": "<?php echo tr('Stato FE'); ?>", "name": "codice_stato_fe", "values": "query=SELECT codice as id, CONCAT_WS(' - ',codice,descrizione) as text FROM fe_stati_documento", "value": "$codice_stato_fe$", "disabled": <?php echo intval(Interaction::isEnabled() || ($record['stato'] == 'Bozza' && $abilita_genera)); ?>, "class": "unblockable", "help": "<?php echo (!empty($record['data_stato_fe'])) ? Translator::timestampToLocale($record['data_stato_fe']) : ''; ?>" ]}
|
||||
</div>
|
||||
|
||||
<?php
|
||||
|
@ -214,6 +214,97 @@ switch (post('op')) {
|
||||
'id_tecnico' => $tecnici_assegnati,
|
||||
]);
|
||||
|
||||
if (!empty(post('ricorsiva'))) {
|
||||
$periodicita = post('periodicita');
|
||||
$data = post('data_inizio_ricorrenza');
|
||||
$interval = post('tipo_periodicita') != 'manual' ? post('tipo_periodicita') : 'days';
|
||||
$stato = Stato::find(post('idstatoricorrenze'));
|
||||
|
||||
// Estraggo le date delle ricorrenze
|
||||
if (post('metodo_ricorrenza') == 'data') {
|
||||
$data_fine = post('data_fine_ricorrenza');
|
||||
while (strtotime($data) <= strtotime($data_fine)) {
|
||||
$data = date('Y-m-d', strtotime('+'.$periodicita.' '.$interval.'', strtotime($data)));
|
||||
$w = date('w', strtotime($data));
|
||||
//Escludo sabato e domenica
|
||||
if ($w == '6') {
|
||||
$data = date('Y-m-d', strtotime('+2 day', strtotime($data)));
|
||||
} elseif ($w == '0') {
|
||||
$data = date('Y-m-d', strtotime('+1 day', strtotime($data)));
|
||||
}
|
||||
if ($data <= $data_fine) {
|
||||
$date_ricorrenze[] = $data;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$ricorrenze = post('numero_ricorrenze');
|
||||
for ($i = 0; $i < $ricorrenze; ++$i) {
|
||||
$data = date('Y-m-d', strtotime('+'.$periodicita.' '.$interval.'', strtotime($data)));
|
||||
$w = date('w', strtotime($data));
|
||||
//Escludo sabato e domenica
|
||||
if ($w == '6') {
|
||||
$data = date('Y-m-d', strtotime('+2 day', strtotime($data)));
|
||||
} elseif ($w == '0') {
|
||||
$data = date('Y-m-d', strtotime('+1 day', strtotime($data)));
|
||||
}
|
||||
|
||||
$date_ricorrenze[] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($date_ricorrenze as $data_ricorrenza) {
|
||||
$intervento = Intervento::find($id_record);
|
||||
$new = $intervento->replicate();
|
||||
// Calcolo il nuovo codice
|
||||
$new->codice = Intervento::getNextCodice($data_ricorrenza);
|
||||
$new->data_richiesta = $data_ricorrenza;
|
||||
$new->idstatointervento = $stato->idstatointervento;
|
||||
$new->save();
|
||||
$idintervento = $new->id;
|
||||
|
||||
// Inserimento sessioni
|
||||
if (!empty(post('riporta_sessioni'))) {
|
||||
$numero_sessione = 0;
|
||||
$sessioni = $intervento->sessioni;
|
||||
foreach ($sessioni as $sessione) {
|
||||
// Se è la prima sessione che copio importo la data con quella della richiesta
|
||||
if ($numero_sessione == 0) {
|
||||
$orario_inizio = date('Y-m-d', strtotime($data_ricorrenza)).' '.date('H:i:s', strtotime($sessione->orario_inizio));
|
||||
} else {
|
||||
$diff = strtotime($sessione->orario_inizio) - strtotime($inizio_old);
|
||||
$orario_inizio = date('Y-m-d H:i:s', (strtotime($sessione->orario_inizio) + $diff));
|
||||
}
|
||||
|
||||
$diff_fine = strtotime($sessione->orario_fine) - strtotime($sessione->orario_inizio);
|
||||
$orario_fine = date('Y-m-d H:i:s', (strtotime($orario_inizio) + $diff_fine));
|
||||
|
||||
$new_sessione = $sessione->replicate();
|
||||
$new_sessione->idintervento = $new->id;
|
||||
$new_sessione->orario_inizio = $orario_inizio;
|
||||
$new_sessione->orario_fine = $orario_fine;
|
||||
$new_sessione->save();
|
||||
|
||||
++$numero_sessione;
|
||||
$inizio_old = $sessione->orario_inizio;
|
||||
}
|
||||
}
|
||||
|
||||
// Assegnazione dei tecnici all'intervento
|
||||
$tecnici_assegnati = (array) post('tecnici_assegnati');
|
||||
$dbo->sync('in_interventi_tecnici_assegnati', [
|
||||
'id_intervento' => $new->id,
|
||||
], [
|
||||
'id_tecnico' => $tecnici_assegnati,
|
||||
]);
|
||||
|
||||
++$n_ricorrenze;
|
||||
}
|
||||
|
||||
flash()->info(tr('Aggiunte _NUM_ nuove ricorrenze!', [
|
||||
'_NUM_' => $n_ricorrenze,
|
||||
]));
|
||||
}
|
||||
|
||||
if (post('ref') == 'dashboard') {
|
||||
flash()->clearMessage('info');
|
||||
flash()->clearMessage('warning');
|
||||
|
@ -47,7 +47,7 @@ if ($user['gruppo'] == 'Tecnici' && !empty($user['idanagrafica'])) {
|
||||
}
|
||||
|
||||
// Stato di default associato all'attivitò
|
||||
$stato = $dbo->fetchArray("SELECT * FROM in_statiintervento WHERE descrizione = 'In programmazione'");
|
||||
$stato = $dbo->fetchArray("SELECT * FROM in_statiintervento WHERE codice = 'WIP'");
|
||||
$id_stato = $stato['idstatointervento'];
|
||||
|
||||
// Se è indicata un'anagrafica relativa, si carica il tipo di intervento di default impostato
|
||||
@ -314,6 +314,58 @@ echo '
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- RICORRENZA -->
|
||||
<div class="box box-warning collapsable collapsed-box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">'.tr('Ricorrenza').'</h3>
|
||||
<div class="box-tools pull-right">
|
||||
<button type="button" class="btn btn-box-tool" data-widget="collapse">
|
||||
<i class="fa fa-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
{[ "type": "checkbox", "label": "'.tr('Ricorsiva').'", "name": "ricorsiva", "value": "" ]}
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 ricorrenza">
|
||||
{[ "type": "timestamp", "label": "'.tr('Data/ora inizio').'", "name": "data_inizio_ricorrenza", "value": "'.($data_richiesta ?: '-now-').'" ]}
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 ricorrenza">
|
||||
{[ "type": "number", "label": "'.tr('Periodicità').'", "name": "periodicita", "decimals": "0", "icon-after": "choice|period|months", "value": "1" ]}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row ricorrenza">
|
||||
<div class="col-md-4">
|
||||
{[ "type": "select", "label": "'.tr('Metodo fine ricorrenza').'", "name": "metodo_ricorrenza", "values": "list=\"data\":\"Data fine\",\"numero\":\"Numero ricorrenze\"" ]}
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
{[ "type": "timestamp", "label": "'.tr('Data/ora fine').'", "name": "data_fine_ricorrenza" ]}
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
{[ "type": "number", "label": "'.tr('Numero ricorrenze').'", "name": "numero_ricorrenze", "decimals": "0" ]}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row ricorrenza">
|
||||
<div class="col-md-4">
|
||||
{[ "type": "select", "label": "'.tr('Stato ricorrenze').'", "name": "idstatoricorrenze", "values": "query=SELECT idstatointervento AS id, descrizione, colore AS _bgcolor_ FROM in_statiintervento WHERE deleted_at IS NULL AND is_completato=0" ]}
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
{[ "type": "checkbox", "label": "'.tr('Riporta sessioni di lavoro').'", "name": "riporta_sessioni", "value": "" ]}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- DETTAGLI CLIENTE -->
|
||||
<div class="box box-success collapsable collapsed-box">
|
||||
<div class="box-header with-border">
|
||||
@ -407,6 +459,9 @@ echo '
|
||||
location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
// Ricorrenza
|
||||
$(".ricorrenza").addClass("hidden");
|
||||
});
|
||||
|
||||
input("idtecnico").change(function() {
|
||||
@ -597,4 +652,32 @@ if (filter('orario_fine') !== null) {
|
||||
function deassegnaTuttiTecnici() {
|
||||
input("tecnici_assegnati").getElement().selectReset();
|
||||
}
|
||||
|
||||
$("#ricorsiva").on("change", function(){
|
||||
if ($(this).is(":checked")) {
|
||||
$(".ricorrenza").removeClass("hidden");
|
||||
$("#data_inizio_ricorrenza").attr("required", true);
|
||||
$("#metodo_ricorrenza").attr("required", true);
|
||||
$("#idstatoricorrenze").attr("required", true);
|
||||
} else {
|
||||
$(".ricorrenza").addClass("hidden");
|
||||
$("#data_inizio_ricorrenza").attr("required", false);
|
||||
$("#metodo_ricorrenza").attr("required", false);
|
||||
$("#idstatoricorrenze").attr("required", false);
|
||||
}
|
||||
});
|
||||
|
||||
$("#metodo_ricorrenza").on("change", function(){
|
||||
if ($(this).val()=="data") {
|
||||
input("data_fine_ricorrenza").enable();
|
||||
$("#data_fine_ricorrenza").attr("required", true);
|
||||
input("numero_ricorrenze").disable();
|
||||
input("numero_ricorrenze").set("");
|
||||
} else {
|
||||
input("numero_ricorrenze").enable();
|
||||
input("data_fine_ricorrenza").disable();
|
||||
input("data_fine_ricorrenza").set("");
|
||||
$("#data_fine_ricorrenza").attr("required", false);
|
||||
}
|
||||
});
|
||||
</script>';
|
||||
|
@ -33,7 +33,6 @@ if (!isset($_SESSION['module_'.$id_fatture]['id_segment'])) {
|
||||
$_SESSION['module_'.$id_fatture]['id_segment'] = isset($segments[0]['id']) ? $segments[0]['id'] : null;
|
||||
}
|
||||
$id_segment = $_SESSION['module_'.$id_fatture]['id_segment'];
|
||||
|
||||
$idtipodocumento = $dbo->selectOne('co_tipidocumento', ['id'], [
|
||||
'predefined' => 1,
|
||||
'dir' => 'entrata',
|
||||
@ -85,7 +84,6 @@ switch (post('op')) {
|
||||
$dir = 'entrata';
|
||||
$tipo_documento = Tipo::where('id', post('idtipodocumento'))->first();
|
||||
|
||||
$id_iva = setting('Iva predefinita');
|
||||
$id_conto = setting('Conto predefinito fatture di vendita');
|
||||
|
||||
$accodare = post('accodare');
|
||||
@ -96,9 +94,11 @@ switch (post('op')) {
|
||||
// Lettura righe selezionate
|
||||
foreach ($interventi as $intervento) {
|
||||
$id_anagrafica = $intervento['idanagrafica'];
|
||||
|
||||
$id_documento = $id_documento_cliente[$id_anagrafica];
|
||||
|
||||
$anagrafica = Anagrafica::find($id_anagrafica);
|
||||
$id_iva = $anagrafica->idiva_vendite ?: setting('Iva predefinita');
|
||||
|
||||
// Se non c'è già una fattura appena creata per questo cliente, creo una fattura nuova
|
||||
if (empty($id_documento)) {
|
||||
if (!empty($accodare)) {
|
||||
@ -109,7 +109,6 @@ switch (post('op')) {
|
||||
}
|
||||
|
||||
if (empty($id_documento)) {
|
||||
$anagrafica = Anagrafica::find($id_anagrafica);
|
||||
$fattura = Fattura::build($anagrafica, $tipo_documento, $data, $id_segment);
|
||||
|
||||
$id_documento = $fattura->id;
|
||||
|
@ -143,10 +143,6 @@ function aggiungi_intervento_in_fattura($id_intervento, $id_fattura, $descrizion
|
||||
$fattura = Fattura::find($id_fattura);
|
||||
$intervento = Intervento::find($id_intervento);
|
||||
|
||||
if (!empty($fattura->anagrafica->idiva_vendite)) {
|
||||
$id_iva = $fattura->anagrafica->idiva_vendite;
|
||||
}
|
||||
|
||||
$data = $intervento->fine;
|
||||
$codice = $intervento->codice;
|
||||
|
||||
|
@ -24,7 +24,8 @@ use Modules\Emails\Mail;
|
||||
use Modules\Emails\Template;
|
||||
use Modules\ListeNewsletter\Lista;
|
||||
use Modules\Newsletter\Newsletter;
|
||||
use Respect\Validation\Validator as v;
|
||||
use Notifications\EmailNotification;
|
||||
use PHPMailer\PHPMailer\Exception;
|
||||
|
||||
include_once __DIR__.'/../../core.php';
|
||||
|
||||
@ -61,42 +62,19 @@ switch (filter('op')) {
|
||||
break;
|
||||
|
||||
case 'send':
|
||||
$template = $newsletter->template;
|
||||
$uploads = $newsletter->uploads()->pluck('id');
|
||||
$newsletter = Newsletter::find($id_record);
|
||||
|
||||
$destinatari = $newsletter->destinatari();
|
||||
$count = $destinatari->count();
|
||||
for ($i = 0; $i < $count; ++$i) {
|
||||
$destinatario = $destinatari->skip($i)->first();
|
||||
$origine = $destinatario->getOrigine();
|
||||
|
||||
$anagrafica = $origine instanceof Anagrafica ? $origine : $origine->anagrafica;
|
||||
|
||||
$abilita_newsletter = $anagrafica->enable_newsletter;
|
||||
$email = $destinatario->email;
|
||||
if (empty($email) || empty($abilita_newsletter) || !v::email()->validate($email)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Inizializzazione email
|
||||
$mail = Mail::build($user, $template, $anagrafica->id);
|
||||
|
||||
// Completamento informazioni
|
||||
$mail->addReceiver($email);
|
||||
$mail->subject = $newsletter->subject;
|
||||
$mail->content = $newsletter->content;
|
||||
$mail->id_newsletter = $newsletter->id;
|
||||
|
||||
// Registrazione allegati
|
||||
foreach ($uploads as $upload) {
|
||||
$mail->addUpload($upload);
|
||||
}
|
||||
|
||||
$mail->save();
|
||||
$mail = $newsletter->inviaDestinatario($destinatario);
|
||||
|
||||
// Aggiornamento riferimento per la newsletter
|
||||
$destinatario->id_email = $mail->id;
|
||||
$destinatario->save();
|
||||
if (!empty($mail)) {
|
||||
$destinatario->id_email = $mail->id;
|
||||
$destinatario->save();
|
||||
}
|
||||
}
|
||||
|
||||
// Aggiornamento stato newsletter
|
||||
@ -107,6 +85,38 @@ switch (filter('op')) {
|
||||
|
||||
break;
|
||||
|
||||
case 'test':
|
||||
$receiver_id = post('id');
|
||||
$receiver_type = post('type');
|
||||
|
||||
// Individuazione destinatario interessato
|
||||
$newsletter = Newsletter::find($id_record);
|
||||
$destinatario = $newsletter->destinatari()
|
||||
->where('record_type', '=', $receiver_type)
|
||||
->where('record_id', '=', $receiver_id)
|
||||
->first();
|
||||
|
||||
// Generazione email e tentativo di invio
|
||||
$inviata = false;
|
||||
if (!empty($destinatario)) {
|
||||
$mail = $newsletter->inviaDestinatario($destinatario, true);
|
||||
|
||||
try {
|
||||
$email = EmailNotification::build($mail, true);
|
||||
$email->send();
|
||||
|
||||
$inviata = true;
|
||||
} catch (Exception $e) {
|
||||
// $mail->delete();
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'result' => $inviata,
|
||||
]);
|
||||
|
||||
break;
|
||||
|
||||
case 'block':
|
||||
$mails = $newsletter->emails;
|
||||
|
||||
|
@ -114,12 +114,15 @@ foreach ($destinatari_filtrati as $destinatario) {
|
||||
|
||||
$riga = array_merge($riga, [
|
||||
'<div class="text-center">'.
|
||||
(!empty($anagrafica->enable_newsletter) ?
|
||||
(!empty($origine->enable_newsletter) ?
|
||||
'<span class="text-success"><i class="fa fa-check"></i> '.tr('Abilitato').'</span>' :
|
||||
'<span class="text-warning"><i class="fa fa-exclamation-triangle"></i> '.tr('Disabilitato').'</span>'
|
||||
).'
|
||||
</div>',
|
||||
'<div class="text-center">
|
||||
'<div class="text-center">'.(empty($lista) && !empty($origine->email) && !empty($origine->enable_newsletter) ? '
|
||||
<a class="btn btn-warning btn-xs" data-type="'.get_class($origine).'" data-id="'.$origine->id.'" data-email="'.$origine->email.'" onclick="testInvio(this)">
|
||||
<i class="fa fa-paper-plane "></i>
|
||||
</a>' : '').'
|
||||
<a class="btn btn-danger ask btn-xs" data-backto="record-edit" data-op="remove_receiver" data-type="'.get_class($origine).'" data-id="'.$origine->id.'">
|
||||
<i class="fa fa-trash"></i>
|
||||
</a>
|
||||
|
@ -240,4 +240,47 @@ $(document).ready(function() {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function testInvio(button) {
|
||||
const destinatario_id = $(button).data("id");
|
||||
const destinatario_type = $(button).data("type");
|
||||
const email = $(button).data("email");
|
||||
|
||||
swal({
|
||||
title: "'.tr('Invio di test?').'",
|
||||
html: `'.tr("Vuoi effettuare un invio di test all'indirizzo _EMAIL_?", ['_EMAIL_' => '${email}']).' '.tr("L'email non sarà registrata come inviata, e l'invio della newsletter non escluderà questo indirizzo").'.`,
|
||||
type: "warning",
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "'.tr('Invia').'",
|
||||
confirmButtonClass: "btn btn-lg btn-success",
|
||||
}).then(function() {
|
||||
const restore = buttonLoading(button);
|
||||
$.ajax({
|
||||
url: globals.rootdir + "/actions.php",
|
||||
type: "POST",
|
||||
dataType: "JSON",
|
||||
data: {
|
||||
id_module: globals.id_module,
|
||||
id_record: globals.id_record,
|
||||
op: "test",
|
||||
id: destinatario_id,
|
||||
type: destinatario_type,
|
||||
},
|
||||
success: function (response) {
|
||||
buttonRestore(button, restore);
|
||||
|
||||
if (response.result) {
|
||||
swal("'.tr('Invio completato').'", "", "success");
|
||||
} else {
|
||||
swal("'.tr('Invio fallito').'", "", "error");
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
buttonRestore(button, restore);
|
||||
|
||||
swal("'.tr('Errore').'", "'.tr("Errore durante l'invio dell'email").'", "error");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>';
|
||||
|
@ -29,6 +29,7 @@ use Modules\Anagrafiche\Sede;
|
||||
use Modules\Emails\Account;
|
||||
use Modules\Emails\Mail;
|
||||
use Modules\Emails\Template;
|
||||
use Respect\Validation\Validator as v;
|
||||
use Traits\RecordTrait;
|
||||
|
||||
class Newsletter extends Model
|
||||
@ -132,6 +133,45 @@ class Newsletter extends Model
|
||||
->where('record_type', '=', $tipo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Metodo per inviare l'email della newsletter a uno specifico destinatario.
|
||||
*
|
||||
* @return Mail|null
|
||||
*/
|
||||
public function inviaDestinatario(Destinatario $destinatario, $test = false)
|
||||
{
|
||||
$template = $this->template;
|
||||
$uploads = $this->uploads()->pluck('id');
|
||||
|
||||
$origine = $destinatario->getOrigine();
|
||||
|
||||
$anagrafica = $origine instanceof Anagrafica ? $origine : $origine->anagrafica;
|
||||
|
||||
$abilita_newsletter = $origine->enable_newsletter;
|
||||
$email = $destinatario->email;
|
||||
if (empty($email) || empty($abilita_newsletter) || !v::email()->validate($email)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Inizializzazione email
|
||||
$mail = Mail::build(auth()->getUser(), $template, $anagrafica->id);
|
||||
|
||||
// Completamento informazioni
|
||||
$mail->addReceiver($email);
|
||||
$mail->subject = ($test ? '[Test] ' : '').$this->subject;
|
||||
$mail->content = $this->content;
|
||||
$mail->id_newsletter = $this->id;
|
||||
|
||||
// Registrazione allegati
|
||||
foreach ($uploads as $upload) {
|
||||
$mail->addUpload($upload);
|
||||
}
|
||||
|
||||
$mail->save();
|
||||
|
||||
return $mail;
|
||||
}
|
||||
|
||||
// Relazione Eloquent
|
||||
|
||||
public function destinatari()
|
||||
|
@ -35,14 +35,17 @@ if (!isset($_SESSION['module_'.$id_fatture]['id_segment'])) {
|
||||
}
|
||||
$id_segment = $_SESSION['module_'.$id_fatture]['id_segment'];
|
||||
$idconto = setting('Conto predefinito fatture di vendita');
|
||||
$idtipodocumento = $dbo->selectOne('co_tipidocumento', ['id'], [
|
||||
'predefined' => 1,
|
||||
'dir' => 'entrata',
|
||||
])['id'];
|
||||
|
||||
switch (post('op')) {
|
||||
case 'crea_fattura':
|
||||
$documenti = collect();
|
||||
$numero_totale = 0;
|
||||
$descrizione_tipo = 'Fattura immediata di vendita';
|
||||
|
||||
$tipo_documento = Tipo::where('descrizione', $descrizione_tipo)->first();
|
||||
$tipo_documento = Tipo::where('id', post('idtipodocumento'))->first();
|
||||
|
||||
$stato_documenti_accodabili = Stato::where('descrizione', 'Bozza')->first();
|
||||
$accodare = post('accodare');
|
||||
@ -145,7 +148,8 @@ if ($module['name'] == 'Ordini cliente') {
|
||||
'data' => [
|
||||
'title' => tr('Fatturare i _TYPE_ selezionati?', ['_TYPE_' => strtolower($module['name'])]),
|
||||
'msg' => '{[ "type": "checkbox", "label": "<small>'.tr('Aggiungere alle _TYPE_ non ancora emesse?', ['_TYPE_' => strtolower($module_fatture)]).'", "placeholder": "'.tr('Aggiungere alle _TYPE_ nello stato bozza?', ['_TYPE_' => strtolower($module_fatture)]).'</small>", "name": "accodare" ]}
|
||||
<br>{[ "type": "select", "label": "'.tr('Sezionale').'", "name": "id_segment", "required": 1, "values": "query=SELECT id, name AS descrizione FROM zz_segments WHERE id_module=\''.$id_fatture.'\' AND is_fiscale = 1 ORDER BY name", "value": "'.$id_segment.'" ]}',
|
||||
<br>{[ "type": "select", "label": "'.tr('Sezionale').'", "name": "id_segment", "required": 1, "values": "query=SELECT id, name AS descrizione FROM zz_segments WHERE id_module=\''.$id_fatture.'\' AND is_fiscale = 1 ORDER BY name", "value": "'.$id_segment.'" ]}<br>
|
||||
{[ "type": "select", "label": "'.tr('Tipo documento').'", "name": "idtipodocumento", "required": 1, "values": "query=SELECT id, CONCAT(codice_tipo_documento_fe, \' - \', descrizione) AS descrizione FROM co_tipidocumento WHERE enabled = 1 AND dir =\'entrata\' ORDER BY codice_tipo_documento_fe", "value": "'.$idtipodocumento.'" ]}',
|
||||
'button' => tr('Procedi'),
|
||||
'class' => 'btn btn-lg btn-warning',
|
||||
'blank' => false,
|
||||
|
@ -34,6 +34,10 @@ if (!isset($_SESSION['module_'.$id_fatture]['id_segment'])) {
|
||||
$_SESSION['module_'.$id_fatture]['id_segment'] = isset($segments[0]['id']) ? $segments[0]['id'] : null;
|
||||
}
|
||||
$id_segment = $_SESSION['module_'.$id_fatture]['id_segment'];
|
||||
$idtipodocumento = $dbo->selectOne('co_tipidocumento', ['id'], [
|
||||
'predefined' => 1,
|
||||
'dir' => 'entrata',
|
||||
])['id'];
|
||||
|
||||
switch (post('op')) {
|
||||
case 'crea_fattura':
|
||||
@ -41,8 +45,7 @@ switch (post('op')) {
|
||||
$numero_totale = 0;
|
||||
|
||||
// Informazioni della fattura
|
||||
$descrizione_tipo = 'Fattura immediata di vendita';
|
||||
$tipo_documento = Tipo::where('descrizione', $descrizione_tipo)->first();
|
||||
$tipo_documento = Tipo::where('id', post('idtipodocumento'))->first();
|
||||
|
||||
$stato_documenti_accodabili = Stato::where('descrizione', 'Bozza')->first();
|
||||
$accodare = post('accodare');
|
||||
@ -123,7 +126,8 @@ $operations['crea_fattura'] = [
|
||||
'text' => '<span><i class="fa fa-file-code-o"></i> '.tr('Fattura _TYPE_', ['_TYPE_' => strtolower($module['name'])]),
|
||||
'data' => [
|
||||
'title' => tr('Fatturare i _TYPE_ selezionati?', ['_TYPE_' => strtolower($module['name'])]),
|
||||
'msg' => '{[ "type": "checkbox", "label": "<small>'.tr('Aggiungere alle fatture di vendita non ancora emesse?').'</small>", "placeholder": "'.tr('Aggiungere alle fatture di vendita nello stato bozza?').'", "name": "accodare" ]}<br>{[ "type": "select", "label": "'.tr('Sezionale').'", "name": "id_segment", "required": 1, "values": "query=SELECT id, name AS descrizione FROM zz_segments WHERE id_module=\''.$id_fatture.'\' AND is_fiscale = 1 ORDER BY name", "value": "'.$id_segment.'" ]}',
|
||||
'msg' => '{[ "type": "checkbox", "label": "<small>'.tr('Aggiungere alle fatture di vendita non ancora emesse?').'</small>", "placeholder": "'.tr('Aggiungere alle fatture di vendita nello stato bozza?').'", "name": "accodare" ]}<br>{[ "type": "select", "label": "'.tr('Sezionale').'", "name": "id_segment", "required": 1, "values": "query=SELECT id, name AS descrizione FROM zz_segments WHERE id_module=\''.$id_fatture.'\' AND is_fiscale = 1 ORDER BY name", "value": "'.$id_segment.'" ]}<br>
|
||||
{[ "type": "select", "label": "'.tr('Tipo documento').'", "name": "idtipodocumento", "required": 1, "values": "query=SELECT id, CONCAT(codice_tipo_documento_fe, \' - \', descrizione) AS descrizione FROM co_tipidocumento WHERE enabled = 1 AND dir =\'entrata\' ORDER BY codice_tipo_documento_fe", "value": "'.$idtipodocumento.'" ]}',
|
||||
'button' => tr('Procedi'),
|
||||
'class' => 'btn btn-lg btn-warning',
|
||||
'blank' => false,
|
||||
|
@ -43,6 +43,18 @@ class Preventivo extends Document
|
||||
|
||||
protected $table = 'co_preventivi';
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = [
|
||||
'data_bozza',
|
||||
'data_conclusione',
|
||||
'data_accettazione',
|
||||
'data_rifiuto',
|
||||
];
|
||||
|
||||
/**
|
||||
* Crea un nuovo preventivo.
|
||||
*
|
||||
|
@ -17,6 +17,10 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use Models\Module;
|
||||
use Models\OAuth2;
|
||||
use Modules\Emails\Account;
|
||||
|
||||
include_once __DIR__.'/../../core.php';
|
||||
|
||||
switch (filter('op')) {
|
||||
@ -34,6 +38,8 @@ switch (filter('op')) {
|
||||
break;
|
||||
|
||||
case 'update':
|
||||
$account = Account::find($id_record);
|
||||
|
||||
$predefined = post('predefined');
|
||||
if (!empty($predefined)) {
|
||||
$dbo->query('UPDATE em_accounts SET predefined = 0');
|
||||
@ -55,26 +61,38 @@ switch (filter('op')) {
|
||||
'timeout' => post('timeout'),
|
||||
'ssl_no_verify' => post('ssl_no_verify'),
|
||||
'predefined' => $predefined,
|
||||
|
||||
// OAuth2
|
||||
'provider' => post('provider'),
|
||||
'client_id' => post('client_id'),
|
||||
'client_secret' => post('client_secret'),
|
||||
'oauth2_config' => json_encode(post('config')),
|
||||
], ['id' => $id_record]);
|
||||
|
||||
flash()->info(tr('Informazioni salvate correttamente!'));
|
||||
|
||||
// Rimozione informazioni OAuth2 in caso di disabilitazione
|
||||
if (!$abilita_oauth2) {
|
||||
$dbo->update('em_accounts', [
|
||||
'provider' => null,
|
||||
'client_id' => null,
|
||||
'client_secret' => null,
|
||||
'access_token' => null,
|
||||
'refresh_token' => null,
|
||||
'oauth2_config' => null,
|
||||
], ['id' => $id_record]);
|
||||
$oauth2 = $account->oauth2;
|
||||
if (!empty($oauth2)) {
|
||||
$account->oauth2()->dissociate();
|
||||
$account->save();
|
||||
|
||||
$oauth2->delete();
|
||||
}
|
||||
}
|
||||
// Aggiornamento delle informazioni per OAuth2
|
||||
else {
|
||||
$oauth2 = $account->oauth2 ?: OAuth2::build();
|
||||
|
||||
$oauth2->class = post('provider');
|
||||
$oauth2->client_id = post('client_id');
|
||||
$oauth2->client_secret = post('client_secret');
|
||||
$oauth2->config = post('config');
|
||||
|
||||
// Link di redirect dopo la configurazione
|
||||
$modulo_account_email = Module::pool('Account email');
|
||||
$oauth2->after_configuration = base_path().'/editor.php?id_module='.$modulo_account_email->id.'&id_record='.$id_record;
|
||||
|
||||
$oauth2->save();
|
||||
|
||||
// Associazione Account-OAuth2
|
||||
$account->oauth2()->associate($oauth2);
|
||||
$account->save();
|
||||
}
|
||||
|
||||
// Validazione indirizzo email mittente
|
||||
@ -119,7 +137,9 @@ switch (filter('op')) {
|
||||
break;
|
||||
|
||||
case 'oauth2':
|
||||
$redirect = base_path().'/oauth2.php?id_account='.$account->id;
|
||||
$oauth2 = $account->oauth2;
|
||||
|
||||
$redirect = base_path().'/oauth2.php?id='.$oauth2->id;
|
||||
redirect($redirect);
|
||||
|
||||
break;
|
||||
|
@ -17,7 +17,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use Modules\Emails\OAuth2;
|
||||
use Modules\Emails\Account;
|
||||
|
||||
include_once __DIR__.'/../../core.php';
|
||||
|
||||
@ -101,16 +101,18 @@ echo '
|
||||
</div>';
|
||||
|
||||
// Elenco provider disponibili
|
||||
$providers = OAuth2::$providers;
|
||||
$providers = Account::$providers;
|
||||
$elenco_provider = [];
|
||||
foreach ($providers as $key => $provider) {
|
||||
$elenco_provider[] = [
|
||||
'id' => $key,
|
||||
'id' => $provider['class'],
|
||||
'short' => $key,
|
||||
'text' => $provider['name'],
|
||||
'help' => $provider['help'],
|
||||
];
|
||||
}
|
||||
|
||||
$oauth2 = $account->oauth2;
|
||||
echo '
|
||||
<!-- OAuth2 -->
|
||||
<div class="box box-info">
|
||||
@ -122,32 +124,32 @@ echo '
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<span class="label label-warning pull-right hidden" id="guida-configurazione"></span>
|
||||
{[ "type": "select", "label": "'.tr('Provider account').'", "name": "provider", "value": "$provider$", "values": '.json_encode($elenco_provider).', "disabled": "'.intval(empty($account->provider)).'" ]}
|
||||
{[ "type": "select", "label": "'.tr('Provider account').'", "name": "provider", "value": '.json_encode($oauth2->class).', "values": '.json_encode($elenco_provider).', "disabled": "'.intval(empty($oauth2)).'" ]}
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
{[ "type": "checkbox", "label": "'.tr('Abilita OAuth2').'", "name": "abilita_oauth2", "value": "'.intval(!empty($account->provider)).'" ]}
|
||||
{[ "type": "checkbox", "label": "'.tr('Abilita OAuth2').'", "name": "abilita_oauth2", "value": "'.intval(!empty($oauth2)).'" ]}
|
||||
</div>
|
||||
|
||||
<div id="oauth2-config">
|
||||
<div class="col-md-3">
|
||||
<a type="button" class="btn btn-success btn-block '.(empty($account->provider) || empty($account->client_id) || empty($account->client_secret) ? 'disabled' : '').'" style="margin-top: 25px" href="'.base_url().'/editor.php?id_module='.$id_module.'&id_record='.$id_record.'&op=oauth2">
|
||||
<i class="fa fa-refresh"></i> '.(empty($account->access_token) ? tr('Completa configurazione') : tr('Ripeti configurazione')).'
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
{[ "type": "text", "label": "'.tr('Client ID').'", "name": "client_id", "value": "$client_id$", "disabled": "'.intval(empty($account->provider)).'" ]}
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
{[ "type": "text", "label": "'.tr('Client Secret').'", "name": "client_secret", "value": "$client_secret$", "disabled": "'.intval(empty($account->provider)).'" ]}
|
||||
</div>
|
||||
|
||||
<div id="provider-config"></div>
|
||||
<div class="col-md-3 oauth2-config">
|
||||
<a type="button" class="btn btn-success btn-block '.(empty($oauth2->class) || empty($oauth2->client_id) || empty($oauth2->client_secret) ? 'disabled' : '').'" style="margin-top: 25px" href="'.base_url().'/editor.php?id_module='.$id_module.'&id_record='.$id_record.'&op=oauth2">
|
||||
<i class="fa fa-refresh"></i> '.(empty($oauth2->access_token) ? tr('Completa configurazione') : tr('Ripeti configurazione')).'
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row oauth2-config">
|
||||
<div class="col-md-6">
|
||||
{[ "type": "text", "label": "'.tr('Client ID').'", "name": "client_id", "value": "'.$oauth2->client_id.'", "disabled": "'.intval(empty($oauth2)).'" ]}
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
{[ "type": "text", "label": "'.tr('Client Secret').'", "name": "client_secret", "value": "'.$oauth2->client_secret.'", "disabled": "'.intval(empty($oauth2)).'" ]}
|
||||
</div>
|
||||
|
||||
<div id="provider-config"></div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info">
|
||||
<i class="fa fa-info-circle"></i> '.tr('Durante la procedura di configurazione verrà effettuato il logout dal gestionale').'.
|
||||
</div>
|
||||
@ -163,7 +165,7 @@ foreach ($providers as $key => $provider) {
|
||||
$config = $provider['class']::getConfigInputs();
|
||||
foreach ($config as $name => $field) {
|
||||
$field['name'] = 'config['.$name.']';
|
||||
$field['value'] = $account->oauth2_config[$name];
|
||||
$field['value'] = $oauth2 ? $oauth2->config[$name] : null;
|
||||
|
||||
echo '
|
||||
<div class="col-md-6">'.input($field).'</div>';
|
||||
@ -186,7 +188,7 @@ abilita_oauth2.change(function() {
|
||||
const disable = !abilita_oauth2.get();
|
||||
provider.setDisabled(disable);
|
||||
|
||||
const inputs = $("#oauth2-config .openstamanager-input");
|
||||
const inputs = $(".oauth2-config .openstamanager-input");
|
||||
for (i of inputs) {
|
||||
input(i).setDisabled(disable);
|
||||
}
|
||||
@ -204,7 +206,7 @@ provider.change(function() {
|
||||
|
||||
// Impostazione dei dati aggiuntivi da configurare
|
||||
config.html("")
|
||||
aggiungiContenuto(config, "#provider-" + data.id);
|
||||
aggiungiContenuto(config, "#provider-" + data.short);
|
||||
})
|
||||
|
||||
$(document).ready(function() {
|
||||
|
@ -19,8 +19,6 @@
|
||||
|
||||
use API\Services;
|
||||
use Carbon\Carbon;
|
||||
use Models\Cache;
|
||||
use Modules\StatoServizi\ServicesHook;
|
||||
|
||||
include_once __DIR__.'/../../core.php';
|
||||
|
||||
@ -28,12 +26,6 @@ include_once __DIR__.'/../../core.php';
|
||||
echo '
|
||||
<div class="row">';
|
||||
|
||||
/**
|
||||
* Contenuto aggiornato e gestito dall'Hook ServicesHook.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
$response = Cache::pool('Informazioni su Services')->content;
|
||||
$limite_scadenze = (new Carbon())->addDays(60);
|
||||
if (Services::isEnabled()) {
|
||||
echo '
|
||||
@ -48,7 +40,7 @@ if (Services::isEnabled()) {
|
||||
|
||||
<div class="box-body">';
|
||||
|
||||
$servizi = collect($response['servizi'])->flatten(1);
|
||||
$servizi = Services::getServiziAttivi()->flatten(1);
|
||||
if (!$servizi->isEmpty()) {
|
||||
echo '
|
||||
<table class="table table-striped table-hover">
|
||||
@ -99,8 +91,9 @@ if (Services::isEnabled()) {
|
||||
<div class="box-body">';
|
||||
|
||||
// Elaborazione delle risorse API in scadenza
|
||||
if (!empty($response['risorse-api'])) {
|
||||
$risorse_in_scadenza = ServicesHook::getRisorseInScadenza($response['risorse-api'], $limite_scadenze);
|
||||
$risorse_attive = Services::getRisorseAttive();
|
||||
if (!$risorse_attive->isEmpty()) {
|
||||
$risorse_in_scadenza = Services::getRisorseInScadenza($limite_scadenze);
|
||||
if (!$risorse_in_scadenza->isEmpty()) {
|
||||
echo '
|
||||
<p>'.tr('Le seguenti risorse sono in scadenza:').'</p>
|
||||
@ -115,11 +108,12 @@ if (Services::isEnabled()) {
|
||||
|
||||
<tbody>';
|
||||
foreach ($risorse_in_scadenza as $servizio) {
|
||||
$scadenza = Carbon::parse($servizio['data_scadenza']);
|
||||
$scadenza = Carbon::parse($servizio['expiration_at']);
|
||||
|
||||
echo '
|
||||
<tr>
|
||||
<td>'.$servizio['nome'].'</td>
|
||||
<td>'.$servizio['crediti'].'</td>
|
||||
<td>'.$servizio['name'].'</td>
|
||||
<td>'.$servizio['credits'].'</td>
|
||||
<td>'.dateFormat($scadenza).' ('.$scadenza->diffForHumans().')</td>
|
||||
</tr>';
|
||||
}
|
||||
|
@ -21,29 +21,15 @@ namespace Modules\StatoServizi;
|
||||
|
||||
use API\Services;
|
||||
use Carbon\Carbon;
|
||||
use Hooks\CachedManager;
|
||||
use Hooks\Manager;
|
||||
|
||||
class ServicesHook extends CachedManager
|
||||
class ServicesHook extends Manager
|
||||
{
|
||||
public function getCacheName()
|
||||
{
|
||||
return 'Informazioni su Services';
|
||||
}
|
||||
|
||||
public function cacheData()
|
||||
{
|
||||
$response = Services::request('GET', 'info');
|
||||
|
||||
return Services::responseBody($response);
|
||||
}
|
||||
|
||||
public function response()
|
||||
{
|
||||
$servizi = $this->getCache()->content;
|
||||
$limite_scadenze = (new Carbon())->addDays(60);
|
||||
|
||||
// Elaborazione dei servizi in scadenza
|
||||
$risorse_in_scadenza = self::getRisorseInScadenza($servizi['risorse-api'], $limite_scadenze);
|
||||
$limite_scadenze = (new Carbon())->addDays(60);
|
||||
$risorse_in_scadenza = Services::getRisorseInScadenza($limite_scadenze);
|
||||
|
||||
$message = tr('I seguenti servizi sono in scadenza: _LIST_', [
|
||||
'_LIST_' => implode(', ', $risorse_in_scadenza->pluck('nome')->all()),
|
||||
@ -56,26 +42,13 @@ class ServicesHook extends CachedManager
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Restituisce l'elenco delle risorse API in scadenza, causa data oppure crediti.
|
||||
*
|
||||
* @param $servizi
|
||||
*/
|
||||
public static function getRisorseInScadenza($risorse, $limite_scadenze)
|
||||
public function execute()
|
||||
{
|
||||
// Elaborazione dei servizi in scadenza
|
||||
$risorse_in_scadenza = collect($risorse)
|
||||
->filter(function ($item) use ($limite_scadenze) {
|
||||
return (isset($item['expiration_at']) && Carbon::parse($item['expiration_at'])->lessThan($limite_scadenze))
|
||||
|| (isset($item['credits']) && $item['credits'] < 100);
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
return $risorse_in_scadenza->transform(function ($item, $key) {
|
||||
return [
|
||||
'nome' => $item['name'],
|
||||
'data_scadenza' => $item['expiration_at'],
|
||||
'crediti' => $item['credits'],
|
||||
];
|
||||
});
|
||||
public function needsExecution()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
35
oauth2.php
35
oauth2.php
@ -1,8 +1,23 @@
|
||||
<?php
|
||||
/*
|
||||
* OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
|
||||
* Copyright (C) DevCode s.r.l.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use Models\Module;
|
||||
use Modules\Emails\Account;
|
||||
use Modules\Emails\OAuth2;
|
||||
use Models\OAuth2;
|
||||
|
||||
$skip_permissions = true;
|
||||
include_once __DIR__.'/core.php';
|
||||
@ -12,12 +27,12 @@ session_write_close();
|
||||
$state = $_GET['state'];
|
||||
$code = $_GET['code'];
|
||||
|
||||
// Account individuato via oauth2_state
|
||||
// Account individuato via state
|
||||
if (!empty($state)) {
|
||||
$account = Account::where('oauth2_state', '=', $state)
|
||||
$account = OAuth2::where('state', '=', $state)
|
||||
->first();
|
||||
} else {
|
||||
$account = Account::find(get('id_account'));
|
||||
$account = OAuth2::find(get('id'));
|
||||
|
||||
// Impostazione access token a null per reimpostare la configurazione
|
||||
$account->access_token = null;
|
||||
@ -31,16 +46,12 @@ if (empty($account)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Inizializzazione
|
||||
$oauth2 = new OAuth2($account);
|
||||
|
||||
// Redirect all'URL di autorizzazione del servizio esterno
|
||||
$redirect = $oauth2->configure($code, $state);
|
||||
$redirect = $account->configure($code, $state);
|
||||
|
||||
// Redirect automatico al record
|
||||
if (empty($redirect)) {
|
||||
$modulo_account_email = Module::pool('Account email');
|
||||
$redirect = base_path().'/editor.php?id_module='.$modulo_account_email->id.'&id_record='.$account->id;
|
||||
$redirect = $account->after_configuration;
|
||||
}
|
||||
|
||||
if (empty($_GET['error'])) {
|
||||
|
@ -30,6 +30,11 @@ use UnexpectedValueException;
|
||||
*/
|
||||
class Interaction extends Services
|
||||
{
|
||||
public static function isEnabled()
|
||||
{
|
||||
return parent::isEnabled() && self::verificaRisorsaAttiva('Fatturazione Elettronica');
|
||||
}
|
||||
|
||||
public static function sendInvoice($id_record)
|
||||
{
|
||||
try {
|
||||
|
@ -160,6 +160,9 @@ class FatturaOrdinaria extends FatturaElettronica
|
||||
}
|
||||
|
||||
if (!empty($articolo)) {
|
||||
$articolo->idconto_acquisto = $conto[$key];
|
||||
$articolo->save();
|
||||
|
||||
$obj = Articolo::build($fattura, $articolo);
|
||||
|
||||
$obj->movimentazione($movimentazione);
|
||||
|
@ -29,6 +29,11 @@ use Models\Cache;
|
||||
*/
|
||||
class Interaction extends Services
|
||||
{
|
||||
public static function isEnabled()
|
||||
{
|
||||
return parent::isEnabled() && self::verificaRisorsaAttiva('Fatturazione Elettronica');
|
||||
}
|
||||
|
||||
public static function getInvoiceList()
|
||||
{
|
||||
$list = self::getRemoteList();
|
||||
|
@ -29,6 +29,11 @@ use Models\Cache;
|
||||
*/
|
||||
class Interaction extends Services
|
||||
{
|
||||
public static function isEnabled()
|
||||
{
|
||||
return parent::isEnabled() && self::verificaRisorsaAttiva('Fatturazione Elettronica');
|
||||
}
|
||||
|
||||
public static function getReceiptList()
|
||||
{
|
||||
$list = self::getRemoteList();
|
||||
|
@ -46,6 +46,8 @@ switch ($operazione) {
|
||||
break;
|
||||
|
||||
case 'updatereferente':
|
||||
$opt_out_newsletter = post('disable_newsletter');
|
||||
|
||||
$dbo->update('an_referenti', [
|
||||
'idanagrafica' => $id_parent,
|
||||
'nome' => post('nome'),
|
||||
@ -53,6 +55,8 @@ switch ($operazione) {
|
||||
'telefono' => post('telefono'),
|
||||
'email' => post('email'),
|
||||
'idsede' => post('idsede'),
|
||||
|
||||
'enable_newsletter' => empty($opt_out_newsletter),
|
||||
], ['id' => $id_record]);
|
||||
|
||||
flash()->info(tr('Salvataggio completato!'));
|
||||
|
@ -49,9 +49,13 @@ echo '
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="col-md-6">
|
||||
{[ "type": "select", "label": "'.tr('Sede').'", "name": "idsede", "values": "query=SELECT 0 AS id, \'Sede legale\' AS descrizione UNION SELECT id, CONCAT_WS(\' - \', nomesede, citta) AS descrizione FROM an_sedi WHERE idanagrafica='.$id_parent.'", "value": "0", "required": 1 ]}
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
{[ "type": "checkbox", "label": "'.tr('Opt-out per newsletter').'", "name": "disable_newsletter", "id": "disable_newsletter_m", "value": "0" ]}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PULSANTI -->
|
||||
|
@ -48,9 +48,13 @@ echo '
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="col-md-6">
|
||||
{[ "type": "select", "label": "'.tr('Sede').'", "name": "idsede", "values": "query=SELECT 0 AS id, \'Sede legale\' AS descrizione UNION SELECT id, CONCAT_WS(\' - \', nomesede, citta) AS descrizione FROM an_sedi WHERE idanagrafica='.$id_parent.'", "value" : "$idsede$", "required": 1 ]}
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
{[ "type": "checkbox", "label": "'.tr('Opt-out per newsletter').'", "name": "disable_newsletter", "id": "disable_newsletter_m", "value": "'.empty($record['enable_newsletter']).'" ]}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PULSANTI -->
|
||||
|
@ -53,6 +53,8 @@ switch ($operazione) {
|
||||
break;
|
||||
|
||||
case 'updatesede':
|
||||
$opt_out_newsletter = post('disable_newsletter');
|
||||
|
||||
$dbo->update('an_sedi', [
|
||||
'nomesede' => post('nomesede'),
|
||||
'indirizzo' => post('indirizzo'),
|
||||
@ -73,6 +75,8 @@ switch ($operazione) {
|
||||
'gaddress' => post('gaddress'),
|
||||
'lat' => post('lat'),
|
||||
'lng' => post('lng'),
|
||||
|
||||
'enable_newsletter' => empty($opt_out_newsletter),
|
||||
], ['id' => $id_record]);
|
||||
|
||||
flash()->info(tr('Salvataggio completato!'));
|
||||
|
@ -95,10 +95,15 @@ echo '
|
||||
{[ "type": "text", "label": "'.tr('Indirizzo email').'", "name": "email", "value": "$email$" ]}
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-3">
|
||||
{[ "type": "checkbox", "label": "'.tr('Opt-out per newsletter').'", "name": "disable_newsletter", "id": "disable_newsletter_m", "value": "'.empty($record['enable_newsletter']).'" ]}
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
{[ "type": "select", "label": "'.tr('Zona').'", "name": "idzona", "ajax-source": "zone", "value": "$idzona$", "placeholder": "'.tr('Nessuna zona').'", "icon-after": "add|'.Modules::get('Zone')['id'].'" ]}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{[ "type": "textarea", "label": "'.tr('Note').'", "name": "note", "value": "$note$" ]}
|
||||
|
@ -216,6 +216,7 @@ class Interventi extends AppResource
|
||||
$record->richiesta = $data['richiesta'];
|
||||
$record->descrizione = $data['descrizione'];
|
||||
$record->informazioniaggiuntive = $data['informazioni_aggiuntive'];
|
||||
$record->idsede_destinazione = $data['id_sede'] ?: 0;
|
||||
|
||||
// Salvataggio firma eventuale
|
||||
if (empty($record->firma_nome) && !empty($data['firma_nome'])) {
|
||||
|
@ -19,7 +19,9 @@
|
||||
|
||||
namespace API;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use GuzzleHttp\Client;
|
||||
use Models\Cache;
|
||||
|
||||
/**
|
||||
* Classe per l'interazione con API esterne.
|
||||
@ -30,11 +32,98 @@ class Services
|
||||
{
|
||||
protected static $client = null;
|
||||
|
||||
/**
|
||||
* Controlla se il gestionale ha accesso a Services.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isEnabled()
|
||||
{
|
||||
return !empty(setting('OSMCloud Services API Token'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Restituisce le informazioni disponibili su Services.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getInformazioni($force = false)
|
||||
{
|
||||
$cache = Cache::pool('Informazioni su Services');
|
||||
|
||||
// Aggiornamento dei contenuti della cache
|
||||
if (!$cache->isValid() || $force) {
|
||||
$response = self::request('GET', 'info');
|
||||
$content = self::responseBody($response);
|
||||
|
||||
$cache->set($content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
return $cache->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restituisce i servizi attivi attraverso Services.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public static function getServiziAttivi()
|
||||
{
|
||||
return collect(self::getInformazioni()['servizi']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restituisce le risorse attive in Services.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public static function getRisorseAttive()
|
||||
{
|
||||
return collect(self::getInformazioni()['risorse-api']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Controlla se il gestionale ha accesso a una specifica risorsa di Services.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function verificaRisorsaAttiva($servizio)
|
||||
{
|
||||
return self::isEnabled() && self::getRisorseAttive()->search(function ($item) use ($servizio) {
|
||||
return $item['name'] == $servizio;
|
||||
}) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restituisce le risorse in scadenza per assenza di crediti oppure per data di fine prossima.
|
||||
*
|
||||
* @param Carbon $limite_scadenze
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public static function getRisorseInScadenza($limite_scadenze)
|
||||
{
|
||||
return self::getRisorseAttive()
|
||||
->filter(function ($item) use ($limite_scadenze) {
|
||||
return (isset($item['expiration_at']) && Carbon::parse($item['expiration_at'])->lessThan($limite_scadenze))
|
||||
|| (isset($item['credits']) && $item['credits'] < 100);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Effettua una richiesta a Services.
|
||||
*
|
||||
* @param $type
|
||||
* @param $resource
|
||||
* @param array $data
|
||||
* @param array $options
|
||||
*
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public static function request($type, $resource, $data = [], $options = [])
|
||||
{
|
||||
$client = static::getClient();
|
||||
@ -53,6 +142,13 @@ class Services
|
||||
return $client->request($type, '', $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restituisce il corpo JSON della risposta in array.
|
||||
*
|
||||
* @param $response
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function responseBody($response)
|
||||
{
|
||||
$body = $response->getBody();
|
||||
|
212
src/Models/OAuth2.php
Normal file
212
src/Models/OAuth2.php
Normal file
@ -0,0 +1,212 @@
|
||||
<?php
|
||||
/*
|
||||
* OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
|
||||
* Copyright (C) DevCode s.r.l.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Models;
|
||||
|
||||
use Common\SimpleModelTrait;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use InvalidArgumentException;
|
||||
use League\OAuth2\Client\Provider\AbstractProvider;
|
||||
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
|
||||
use League\OAuth2\Client\Token\AccessToken;
|
||||
|
||||
class OAuth2 extends Model
|
||||
{
|
||||
use SimpleModelTrait;
|
||||
|
||||
protected $provider;
|
||||
|
||||
protected $table = 'zz_oauth2';
|
||||
|
||||
protected $casts = [
|
||||
'config' => 'array',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return AbstractProvider
|
||||
*/
|
||||
public function getProvider()
|
||||
{
|
||||
// Inizializza il provider per l'autenticazione OAuth2.
|
||||
if (!isset($this->provider)) {
|
||||
$config = $this->config ?? [];
|
||||
$config = array_merge($config, [
|
||||
'clientId' => $this->client_id,
|
||||
'clientSecret' => $this->client_secret,
|
||||
'redirectUri' => base_url().'/oauth2.php',
|
||||
'accessType' => 'offline',
|
||||
]);
|
||||
|
||||
$class = $this->class;
|
||||
if (!class_exists($class)) {
|
||||
throw new InvalidArgumentException('Classe non esistente');
|
||||
}
|
||||
|
||||
$this->provider = new $class($config);
|
||||
}
|
||||
|
||||
return $this->provider;
|
||||
}
|
||||
|
||||
public function needsConfiguration()
|
||||
{
|
||||
$access_token = $this->getAccessToken();
|
||||
|
||||
return empty($access_token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gestisce le operazioni di configurazione per l'autenticazione OAuth2.
|
||||
* Restituisce l'URL di redirect per le operazioni di aggiornamento dei dati, lancia un eccezione in caso di errori e restituisce null in caso di completamento della configurazione.
|
||||
*
|
||||
* Nota: l'autenticazione OAuth2 richiede una serie di richieste su una singola pagina
|
||||
* - Richiesta di autenticazione al server remoto (code, state vuoti)
|
||||
* - Conferma di autenticazione alla pagina di redirect (code, state impostati)
|
||||
* - Richiesta del token di accesso dalla pagina di redirect al server remoto
|
||||
*
|
||||
* @param string|null $code
|
||||
* @param string|null $state
|
||||
*
|
||||
* @throws IdentityProviderException
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function configure($code, $state)
|
||||
{
|
||||
if (!$this->needsConfiguration()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$provider = $this->getProvider();
|
||||
$options = method_exists($provider, 'getOptions') ? $provider->getOptions() : [];
|
||||
if (empty($code)) {
|
||||
// Fetch the authorization URL from the provider; this returns the
|
||||
// urlAuthorize option and generates and applies any necessary parameters
|
||||
// (e.g. state).
|
||||
$authorization_url = $provider->getAuthorizationUrl($options);
|
||||
|
||||
// Get the state generated for you and store it to the session.
|
||||
$this->state = $provider->getState();
|
||||
$this->save();
|
||||
|
||||
// Redirect the user to the authorization URL.
|
||||
return $authorization_url;
|
||||
} elseif (!empty($this->state) && $this->state !== $state) {
|
||||
$this->state = null;
|
||||
$this->save();
|
||||
|
||||
throw new InvalidArgumentException();
|
||||
} else {
|
||||
$this->state = null;
|
||||
$this->save();
|
||||
|
||||
// Try to get an access token using the authorization code grant
|
||||
$access_token = $provider->getAccessToken('authorization_code', [
|
||||
'code' => $code,
|
||||
]);
|
||||
$refresh_token = $access_token->getRefreshToken();
|
||||
|
||||
$this->updateTokens($access_token, $refresh_token);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getRefreshToken()
|
||||
{
|
||||
$this->checkTokens();
|
||||
|
||||
return $this->attributes['refresh_token'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Restituisce l'access token per l'autenticazione OAuth2.
|
||||
*
|
||||
* @return AccessToken|null
|
||||
*/
|
||||
public function getAccessToken()
|
||||
{
|
||||
$this->checkTokens();
|
||||
|
||||
return unserialize($this->attributes['access_token']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Effettua una richiesta utilizzando il token di accesso prestabilito.
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $url
|
||||
* @param array $options
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function request($method, $url, $options = [])
|
||||
{
|
||||
$provider = $this->getProvider();
|
||||
$accessToken = $this->getAccessToken();
|
||||
|
||||
$request = $provider->getAuthenticatedRequest($method, $url, $accessToken, $options);
|
||||
|
||||
return $provider->getParsedResponse($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Imposta Access Token e Refresh Token per l'autenticazione OAuth2.
|
||||
*
|
||||
* @param AccessToken|null
|
||||
*/
|
||||
protected function updateTokens($access_token, $refresh_token)
|
||||
{
|
||||
$this->access_token = serialize($access_token);
|
||||
|
||||
$previous_refresh_token = $this->refresh_token;
|
||||
$this->refresh_token = $refresh_token ?: $previous_refresh_token;
|
||||
|
||||
$this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Controlla la validità dei token correnti e ne effettua il refresh se necessario.
|
||||
*/
|
||||
protected function checkTokens()
|
||||
{
|
||||
$access_token = unserialize($this->access_token);
|
||||
|
||||
if (!empty($access_token) && $access_token->hasExpired()) {
|
||||
// Tentativo di refresh del token di accesso
|
||||
$refresh_token = $this->refresh_token;
|
||||
if (!empty($refresh_token)) {
|
||||
$access_token = $this->getProvider()->getAccessToken('refresh_token', [
|
||||
'refresh_token' => $this->refresh_token,
|
||||
]);
|
||||
|
||||
$refresh_token = $access_token->getRefreshToken();
|
||||
} else {
|
||||
$access_token = null;
|
||||
$refresh_token = null;
|
||||
}
|
||||
|
||||
$this->updateTokens($access_token, $refresh_token);
|
||||
}
|
||||
}
|
||||
}
|
@ -69,16 +69,15 @@ class EmailNotification extends PHPMailer implements NotificationInterface
|
||||
$this->Username = $account['username'];
|
||||
|
||||
// Configurazione OAuth2
|
||||
if (!empty($account['access_token'])) {
|
||||
$oauth2 = $account->getGestoreOAuth2();
|
||||
|
||||
$oauth2 = $account->oauth2;
|
||||
if (!empty($oauth2)) {
|
||||
$this->AuthType = 'XOAUTH2';
|
||||
$this->setOAuth(
|
||||
new OAuth([
|
||||
'provider' => $oauth2->getProvider(),
|
||||
'refreshToken' => $oauth2->getRefreshToken(),
|
||||
'clientId' => $account->client_id,
|
||||
'clientSecret' => $account->client_secret,
|
||||
'clientId' => $oauth2->client_id,
|
||||
'clientSecret' => $oauth2->client_secret,
|
||||
'userName' => $account->username,
|
||||
])
|
||||
);
|
||||
|
@ -98,7 +98,7 @@ class Validate
|
||||
} */
|
||||
|
||||
// Controllo attraverso apilayer
|
||||
if (Services::isEnabled()) {
|
||||
if (Services::verificaRisorsaAttiva('Verifica Partita IVA')) {
|
||||
$response = Services::request('post', 'check_iva', [
|
||||
'partita_iva' => $vat_number,
|
||||
]);
|
||||
@ -151,7 +151,7 @@ class Validate
|
||||
}
|
||||
|
||||
// Controllo attraverso apilayer
|
||||
if (Services::isEnabled()) {
|
||||
if (Services::verificaRisorsaAttiva('Verifica Email')) {
|
||||
$response = Services::request('post', 'check_email', [
|
||||
'email' => $email,
|
||||
]);
|
||||
|
@ -134,7 +134,7 @@ echo '
|
||||
<tr>
|
||||
<td>'.$liv3_p['numero'].'</td>
|
||||
<td>'.$liv3_p['descrizione'].'</td>
|
||||
<td class="text-right">'.numberFormat(abs($liv3_p['totale'])).'</td>
|
||||
<td class="text-right">'.numberFormat(-$liv3_p['totale']).'</td>
|
||||
</tr>';
|
||||
}
|
||||
}
|
||||
|
@ -18,19 +18,36 @@
|
||||
*/
|
||||
|
||||
use Carbon\CarbonInterval;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Modules\Anagrafiche\Anagrafica;
|
||||
use Modules\Banche\Banca;
|
||||
use Modules\Pagamenti\Pagamento;
|
||||
|
||||
include_once __DIR__.'/../../core.php';
|
||||
|
||||
$anagrafica = Anagrafica::find($documento['idanagrafica']);
|
||||
$pagamento = $dbo->fetchOne('SELECT * FROM co_pagamenti WHERE id = '.prepare($documento['idpagamento']));
|
||||
$anagrafica_azienda = Anagrafica::find(setting('Azienda predefinita'));
|
||||
|
||||
// Verifico se c'è una banca predefinita per il mio cliente
|
||||
if (!empty($anagrafica->idbanca_vendite)) {
|
||||
$banca = $dbo->fetchOne('SELECT co_banche.nome, co_banche.iban, co_banche.bic FROM co_banche WHERE co_banche.id_pianodeiconti3 = '.prepare($pagamento['idconto_vendite']).' AND co_banche.id_anagrafica = '.prepare($anagrafica->id).' AND co_banche.id ='.prepare($anagrafica->idbanca_vendite));
|
||||
} elseif (!empty($pagamento['idconto_vendite'])) {
|
||||
// Altrimenti prendo quella associata la metodo di pagamento selezionato
|
||||
$banca = $dbo->fetchOne('SELECT co_banche.nome, co_banche.iban, co_banche.bic FROM co_banche WHERE co_banche.id_pianodeiconti3 = '.prepare($pagamento['idconto_vendite']).' AND co_banche.id_anagrafica = '.prepare($anagrafica->id).' AND co_banche.deleted_at IS NULL');
|
||||
$pagamento = Pagamento::find($documento['idpagamento']);
|
||||
|
||||
// Banca dell'Azienda corrente impostata come predefinita per il Cliente
|
||||
$banca_azienda = Banca::where('id_anagrafica', '=', $anagrafica_azienda->id)
|
||||
->where('id_pianodeiconti3', '=', $pagamento['idconto_vendite'] ?: 0);
|
||||
try {
|
||||
$banca = (clone $banca_azienda)
|
||||
->findOrFail($anagrafica->idbanca_vendite);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
// Ricerca prima banca dell'Azienda con Conto corrispondente
|
||||
$banca = (clone $banca_azienda)
|
||||
->orderBy('predefined', 'DESC')
|
||||
->first();
|
||||
}
|
||||
|
||||
// Ri.Ba: Banca predefinita *del Cliente* piuttosto che dell'Azienda
|
||||
if ($pagamento->isRiBa()) {
|
||||
$banca = Banca::where('id_anagrafica', $anagrafica->id)
|
||||
->where('predefined', 1)
|
||||
->first();
|
||||
}
|
||||
|
||||
// Righe documento
|
||||
|
12
update/2_4_26.php
Normal file
12
update/2_4_26.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
use Models\Module;
|
||||
|
||||
$modulo_account_email = Module::pool('Account email');
|
||||
$redirect = base_path().'/editor.php?id_module='.$modulo_account_email->id.'&id_record=';
|
||||
|
||||
$database->query("INSERT INTO `zz_oauth2` (`id`, `class`, `client_id`, `client_secret`, `config`, `state`, `access_token`, `refresh_token`, `after_configuration`) SELECT `id`, 'Modules\\\\Emails\\\\OAuth2\\\\Microsoft', `client_id`, `client_secret`, `oauth2_config`, `oauth2_state`, `access_token`, `refresh_token`, CONCAT('".$redirect."', `id`) FROM `em_accounts` WHERE `provider` = 'microsoft' AND `client_id` IS NOT NULL");
|
||||
|
||||
$database->query("INSERT INTO `zz_oauth2` (`id`, `class`, `client_id`, `client_secret`, `config`, `state`, `access_token`, `refresh_token`, `after_configuration`) SELECT `id`, 'Modules\\\\Emails\\\\OAuth2\\\\Google', `client_id`, `client_secret`, `oauth2_config`, `oauth2_state`, `access_token`, `refresh_token`, CONCAT('".$redirect."', `id`) FROM `em_accounts` WHERE `provider` = 'google' AND `client_id` IS NOT NULL");
|
||||
|
||||
$database->query('UPDATE `em_accounts` SET `id_oauth2` = (SELECT `id` FROM `zz_oauth2` WHERE `zz_oauth2`.`id` = `em_accounts`.`id`)');
|
@ -107,3 +107,27 @@ INSERT INTO `em_lists` (`id`, `name`, `description`, `query`, `deleted_at`) VALU
|
||||
|
||||
-- Fix riferimento documento per righe create da Interventi
|
||||
UPDATE `co_righe_documenti` SET `original_document_id` = `idintervento`, `original_document_type` = 'Modules\\Interventi\\Intervento' WHERE `idintervento` IS NOT NULL;
|
||||
|
||||
-- Generalizzazione della configurazione OAuth2
|
||||
CREATE TABLE IF NOT EXISTS `zz_oauth2` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`class` varchar(255) DEFAULT NULL,
|
||||
`client_id` text DEFAULT NULL,
|
||||
`client_secret` text DEFAULT NULL,
|
||||
`config` text DEFAULT NULL,
|
||||
`state` text DEFAULT NULL,
|
||||
`access_token` text DEFAULT NULL,
|
||||
`refresh_token` text DEFAULT NULL,
|
||||
`after_configuration` text DEFAULT NULL,
|
||||
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
ALTER TABLE `em_accounts` ADD `id_oauth2` INT(11) DEFAULT NULL,
|
||||
ADD FOREIGN KEY (`id_oauth2`) REFERENCES `zz_oauth2`(`id`);
|
||||
|
||||
-- Aggiunta opt-out Newsletter per Referenti e Sedi
|
||||
ALTER TABLE `an_referenti` ADD `enable_newsletter` BOOLEAN DEFAULT TRUE;
|
||||
ALTER TABLE `an_sedi` ADD `enable_newsletter` BOOLEAN DEFAULT TRUE;
|
||||
|
||||
|
@ -99,6 +99,7 @@ return [
|
||||
'mg_valori_attributi',
|
||||
'my_impianto_componenti',
|
||||
'my_componenti',
|
||||
'zz_oauth2',
|
||||
'or_ordini',
|
||||
'or_righe_ordini',
|
||||
'or_statiordine',
|
||||
|
Loading…
x
Reference in New Issue
Block a user