P4A 3 Framework: helper per sincronizzare le tabelle sequence in MySQL

P4A 3 LogoChi utilizza l’RDBMS MySQL in P4A avrà certamente notato che il framework produce in certi casi, delle tabelle il cui nome termina in ‘_seq’. Queste tabelle servono ad avere una compatibilità nella gestione di tutti gli RDBMS supportati (MySQL, PostgreSQL, SQLite, Oracle). PostgreSQL e Oracle, non hanno lo stesso tipo di gestione delle chiavi primarie con l’attributo ‘AUTOINCREMENT‘, rispetto a MySQL e SQLite. La soluzione adottata è di costruire, per ogni tabella con chiave primaria di tipo ‘AUTOINCREMENT’, delle tabelle accessorie che hanno un campo ‘id’ di tipo ‘AUTOINCREMENT’ e di riferirsi a quest’ultime per ottenre il ‘LAST INSERT ID‘. In questo modo viene ricalcato il comportamento delle chiavi primarie di tipo ‘SERIAL’ in PostgreSQL, e anche quelle di Oracle (leggermente diverse).

Prima di tutto una precisazione: questo articolo è riferito esclusivamente agli utenti MySQL.
Se si pensa di utilizzare esclusivamente P4A Framework per la gestione dei dati del nostro database, sarebbe bene in fase di progettazione evitare di usare gli AUTOINCREMENT perché, come detto, non necessari. Nel caso in cui il framework venga utilizzato come ‘backoffice’ per la gestione di dati che vengono alimentati da un form di un sito web, oppure si abbia la necessità di utilizzare una struttura dati pre-esistente con tanto di chiavi primarie ‘AUTOINCREMENT’, potremmo prima o poi trovarci di fronte ad un problema di disallineamento dei valori fra la chiave primaria della tabella e l’id’ della tabella ‘_seq’ associata.

Immaginiamo di avere una tabella “test” con questi due campi:

+----+---------+
| id | name    |
+----+---------+

con ‘id’ chiave primaria, P4A creerà automaticamente una tabella “test_id_seq” con una campo ‘id’ chiave primaria e ‘AUTOINCREMENT’, ed userà i valori forniti da quest’ultima sia per l’inserimento di nuovi record nella tabella “test“, che per altre operazioni sulla chiave primaria. Dunque utilizzando un programma esterno al framework per fare degli inserimenti e volendo mantenere allineate le tabelle principali e le tabelle “_seq” sarà necessario, per ogni “INSERT” nella tabella principale, fare altrettanto nella “_seq”!
Anche utilizzando questo metodo, potrebbe verificarsi prima o poi il problema di un disallineamento, in questo caso ho pensato potesse utile scrivere un metodo della classe “P4A_DB_SOURCE” da utilizzare in extremis, per risistemare le cose.

Per maggiori informazioni sull’utilizzo degli ‘helper’ in P4A suggerisco questo link

Ecco il codice dell’helper, in pratica viene prelevato il valore massimo della chiave primaria ‘AUTOINCREMENT’ della tabella che funge da sorgente dati, quindi viene eliminata la tabella ‘_seq’ associata e successivamente ricostruita con il valore corretto.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 function p4a_db_source_resync_seq($source)
 
 { 
	$table = $source->getTable();
	$pKField = $source->getPk();
	$seqTable =  $table."_".$pKField."_seq";
	$lastId = P4A_DB::singleton()->fetchOne("SELECT MAX($pKField) FROM $table");
	$query = "DROP TABLE IF EXISTS `$seqTable`";
	$resQ1 = P4A_DB::singleton()->query($query);
	$query = "CREATE TABLE `$seqTable` (
	`id` int(11) NOT NULL auto_increment,
	PRIMARY KEY  (`id`)
	) TYPE=MyISAM AUTO_INCREMENT=$lastId";
 
	$resQ2 = P4A_DB::singleton()->query($query);
	$query = "INSERT INTO `$seqTable` VALUES ($lastId)";
	$resQ3 = P4A_DB::singleton()->query($query);
  return ($resQ1 && $resQ2 && $resQ3); 
 
 }

Questo codice deve essere inserito in un file con il nome: “p4a_db_source_resync_seq.php” che deve essere posizionato nella directory “libraries” della nostra applicazione P4A.

Ecco infine un po’ di codice di esempio da aggiungere alla nostra ipotetica maschera di manutenzione del db:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class test extends P4A_Base_Mask
{
	public function __construct()
 
	{
		parent::__construct();
 
		// DB Source
		$this->build("p4a_db_source", "source")
			->setTable("test")
			->setPk("id")
			->load();
		$this->setSource($this->source);
 
		// ....
 
	    $this->build("p4a_button", "btn_resync")
			->setLabel("resync")
			->implement("onclick", $this, "resync_seq_table");
 
		// ....
	}
 
	public function resync_seq_table()
	{
		$res = $this->source->resync_seq();	
	}
 
	// ....
}

Conclusioni

Questo metodo dovrebbe essere usato con una certa cautela, e solo come procedura di emergenza. Non consiglio l’utilizzo se c’è la possibilità di accesso in scrittura alla tabella coinvolta da parte di altri utenti.

Riferimenti ed approfondimenti:

OpenOffice Calc: come creare una funzione che genera password random

Logo della OpenOffice Calc

Vi è mai capitato di dover generare una lunga serie di password random da inserire in un database? Esistono diversi generatori, anche piuttosto sofisticati e flessibili nelle regole, ma normalmente generano una password alla volta. Ne ho trovati alcuni, che nelle versioni freeware, generano un massimo di 100 password. Ma se abbiamo la necessità di generarne 10000 o più?

Ho pensato di creare una formula per OpenOffice Calc, che possa generare una stringa alfanumerica rispettando certi requisiti di casualità, lunghezza e robustezza.

Il codice che genera la password è tratto da questo articolo, e tradotto in linguaggio Basic per OO.

E’ possibile stabilire la lunghezza della password e la robustezza. Quest’ultima viene definita da un valore minimo di 0 fin ad un massimo di 8

  • Robustezza = 0, solo consonanti e vocali minuscole
  • Robustezza = 1, consonanti minuscole e maiuscole e vocali minuscole
  • Robustezza = 2, consonanti minuscole e maiuscole e vocali minuscole e maiuscole
  • Robustezza = 4, consonanti minuscole e maiuscole, numeri e vocali minuscole e maiuscole
  • Robustezza = 8, consonanti minuscole e maiuscole, numeri, caratteri speciali e vocali minuscole e maiuscole

Per la compilazione e l’esecuzione della macro in OpenOffice Calc, ho seguito scrupolosamente le indicazioni di questo post sul sito Wiki di OpenOffice.
In pratica si tratta di creare una nuova macro associata ad un foglio di calcolo “Calc”, utilizzando:

Strumenti > Macro > Organizza Macro > OpenOffice.org Basic

Qunidi cliccando sul bottone “Gestisci” e sul tab “Libreria”, è possibile creare una nuova libreria associata al foglio di calcolo, nel nostro caso in calcTestMacros.ods creo (con poca fantasia…) la libreria: AuthorsCalcMacros.

Utilizzando il bottone “Modifica” si apre un IDE per poter scrivere, con l’aiuto del Syntax highlighting, il codice della macro in linguaggio Basic.
La macro in realtà corrisponde all’implementazione, ma non è la funzione che richiameremo all’interno delle celle del foglio di lavoro. Il motivo è da imputarsi al fatto che, a parte la libreria di default denominata “Standard”, tutte le altre non vengono automaticamente caricate all’avvio, dunque si rende necessario creare una funzione che potremmo chiamare “prototipo” nella libreria “Standard”, che a sua volta richiama l’implementazione vera e propria.

Questo è il codice della implementazione inserito nella libreria “AuthorsCalcMacros”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Function Passwdgen_implementation(ByVal length AS Integer, ByVal strength As Integer)
	Dim vowels As string
	Dim consonants As string
	Dim password As string
	Dim alt As Integer
	Dim i As Integer
 
	vowels = "aeuy"
	consonants = "bdghjmnpqrstvz"
	If (strength >= 1) Then
		consonants = consonants + "BDGHJLMNPQRSTVWXZ"
	End If
	If (strength >= 2) Then
		vowels = vowels + "AEUY"
	End If	
	If (strength >= 4) Then
		consonants = consonants + "23456789"
	End If	
	If (strength >= 8) Then
		consonants = consonants + "@#$%"
	End If	
	password = ""
	Randomize()
	alt = Int((2 * Rnd) + 1)
	For i = 0 To length-1
		If (alt = 2) Then
			password = password + Mid(consonants, Int((Len(consonants) * Rnd) + 1), 1)	
			alt = 1
		Else 
			password = password + Mid(vowels, Int((Len(vowels) * Rnd) + 1), 1)		
			alt = 2						
		End If
	Next i
	Passwdgen_implementation = password
End Function

Questo è il codice del “prototipo” inserito nella libreria “Standard”:

1
2
3
4
5
6
Function Passwdgen(ByVal l as Integer, ByVal s as Integer)
  If NOT BasicLibraries.isLibraryLoaded("AuthorsCalcMacros") Then
    BasicLibraries.LoadLibrary("AuthorsCalcMacros")
  End If
  Passwdgen = Passwdgen_Implementation(l, s)
End Function

Ed ecco infine il risultato della funzione nel foglio di calcolo:

screenshot del foglio di calcolo: calcTestMacros.ods

Per permettere l’esecuzione delle macro, è necessario impostare il livello di sicurezza su “Medio”
Questo parametro si imposta da:

Strumenti > Opzioni

Selezionare: “Sicurezza, quindi premere il bottone “Sicurezza delle macro…”

Aprendo il documento, ovviamente è necessario abilitare le macro, come mostrato nella figura qui sotto:

screenshot della finestra di dialogo abilita macro

Download:

Il documento ods che contiene la macro è disponibile qui

Riferimenti e Links:

Il famoso problema di Einstein

albert einstein 1951, foto di Arthur Sasse, nital.it
albert einstein 1951, foto di Arthur Sasse, nital.it

Albert Einstein, probabilmente il più grande fisico del XX secolo, è anche riconosciuto come l’icona dell’intelligenza. Non si direbbe dall’espressione che assume nella famosa foto del 1951 scattata dal fotografo Arthur Sasse!

In questo mini post, vi propongo il famoso problema di Einstein: si tratta di un enigma da risolvere mediante la logica, rispettando le 15 condizioni imposte.

Dimenticavo, un’ultima cosa: Einstein disse che il 98% della popolazione non sarebbe riuscita a risolverlo, la sfida è lanciata…

Il famoso problema di Einstein

La premessa:

In una strada ci sono 5 case pitturate con 5 colori diversi. In ogni casa vive una persona di una diversa nazionalità. I 5 proprietari bevono bevande differenti, fumano una diversa marca di sigarette e possiedono ognuno un animale diverso.

Le condizioni:

  1. L’inglese vive in una casa rossa
  2. Lo svedese possiede un cane
  3. Il danese beve te
  4. La casa verde è a sinistra di quella bianca
  5. Il proprietario della casa verde beve caffè
  6. La persona che fuma Pall Mall possiede un uccello
  7. Il proprietario della casa gialla fuma Dunhill
  8. L’uomo che vive nella casa in centro beve latte
  9. Il norvegese vive nella prima casa
  10. L’uomo che fuma Blends vive vicino a quello che ha un gatto
  11. L’uomo che possiede un cavallo vive vicino a quello che fuma Dunhill
  12. L’uomo che fuma Blu Master beve birra
  13. Il tedesco fuma Prince
  14. Il norvegese vive vicino a una casa blu
  15. L’uomo che fuma Blends ha un vicino che beve acqua

Chi possiede il pesce?

 

Referenza immagine

Fotografo: Arthur Sasse, Bettmann/CORBIS, Fonte: nital.it

 

 

 

Soluzione e links:

ANSI C: Test di numeri primi con la Wheel Factorization

Crivello di eratostene: animazioneCosa sono i numeri primi e perché tanto interesse intorno a loro? Un numero n > 0 si definisce primo se è divisibile solo per 1 e per sé stesso con resto 0. L’interesse è dovuto a due motivi, principalmente:

1) I numeri primi sono le basi di tutta l’aritmetica come si può evincere dal Teorema Fondamentale della matematica che recita:“Ogni intero si fattorizza in modo unico come prodotto di numeri primi” e questo li rende indubbiamente affascinanti.
2) I numeri primi molto grandi (ordine di 21024), sono alla base del più utilizzato sistema di crittografia: l’RSA questo invece, attira molto gli esperti in sicurezza informatica…!

Come si trovano i numeri primi?

Fu Eratostene di Cirene (276 – 194 a.c.), il primo a proporre un metodo per “setacciare” i numeri primi, detto appunto: crivello di Eratostene. Esistono diversi algoritmi che risolvono il crivello di Eratostene, questo che propongo mi sembra il più efficiente. Supponiamo dunque di voler trovare tutti i numeri primi da 1 a n, l’algoritmo in pseudocodice è il seguente:


for i := 2 to n-1 do
 a[i] := 1
for i := 2 to n-1 do
 if a[i]
  for j := i to (j*i)<n do
   a[i*j] := 0
for i := 2 to n-1 do
 if a[i]
  print i

In pratica si procede da i=2 a n, eliminando tutti i multipli di i
(nella immagine in alto a sinistra è possibile vedere un’animazione del processo). Va detto che ancora oggi, pur non essendo l’algoritmo più efficiente in assoluto, è molto utilizzato quando si lavora su numeri relativamente piccoli, per la sua estrema semplicità.

Il metodo della ruota di fattorizzazione (Wheel Factorization)

Già il crivello di Eratostene permette un notevole incremento di prestazioni rispetto ad un processo di “forza bruta” specialmente se l’algoritmo è opportunamente ottimizzato. Il metodo della ruota risulta ancora più efficiente, e vediamo il perché:
Si scelgono inizialmente come numeri primi di partenza: 2, 3, 5 per ottenere una ruota di lunghezza 30. La lunghezza della ruota è determinta dal prodotto dei numeri primi che decidiamo di utilizzare. Nel nostro caso 2 * 3 * 5 = 30. A questo punto troviamo tutti gli interi che non sono multipli di 2, 3 e 5, il vettore risultate sarà: s[] = {1, 7, 11, 13, 17, 19, 23, 29 }. Abbiamo ottenuto un insieme di numeri che, non sono multipli di 2, 3, 5 e anche se sommati alla lunghezza della ruota o ai suoi multipli (30, 60, 90, ecc), non daranno mai multipli di 2, 3, 5.
Il concetto è più chiaro osservando la figura sotto, le colonne gialle della tabella contengono i soli numeri che andremo a testare, i rimanenenti non sono sicuramente primi, esclusi i numeri di partenza (2, 3, 5). Se provassimo a visualizzare ciascuna riga della tabella come una circonferenza, potremmo immaginare la tabella come una ruota in cui le colonne gialle rappresentano i raggi dove cercare i numeri primi.

Tabella di fattorizzazione
Tabella di fattorizzazione

Il codice è tratto dall’articolo: “Prime Number Determination Using Wheel Factorization” di rickoshay originariamente scritto in C#, e da me convertito in ANSI C


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <stdio .h>
#include <stdlib .h>
 
unsigned long FirstDivisor(unsigned long candidatePrime);
int isPrime(unsigned long primeSuspect);
 
unsigned long FirstDivisor(unsigned long candidatePrime)
{
 const int wheelFactor = 30;
 int aSieve30[] = {7, 11, 13, 17, 19, 23, 29, 31};
 int firstPrimes[] = {2, 3, 5}, i;
 unsigned long sqrtmax, pass;
 
 if (candidatePrime == 1)
 {  
    return 0;
 }
 for (i=0;i<sizeof (firstPrimes)/sizeof(int);i++) {
     if (candidatePrime % firstPrimes[i] == 0) {
        return firstPrimes[i];
     }
 }
 
 sqrtmax  = (unsigned long) sqrt(candidatePrime);
 for (pass=0; pass<sqrtmax; pass+=wheelFactor) {
  for (i=0;i<sizeof(aSieve30)/sizeof(int);i++) {
      if (candidatePrime % (pass + aSieve30[i]) == 0) {
         return pass + aSieve30[i];
      }
  }   
 }
 return candidatePrime; 
}
 
int isPrime(unsigned long primeSuspect)
{
   if (primeSuspect == 0) {
      return 0;
   }
   if (FirstDivisor(primeSuspect) == primeSuspect) {
      return 1;
   }
   else {
      return 0;
   }
}
 
int main(int argc, char *argv[])
{
  unsigned long x, i;
 
  if (argc == 2) {
     x = strtoul(argv[1],NULL,10);
     if (isPrime(x)) {
        printf("%u e' un numero primo\n",x);
     }
     else {
        printf("%u non e' un numero primo\n",x);        
     }     
  }
  else {
   printf ("\nUsage: %s n \nWhere n is an integer number to check for primality\n",argv[0]);
  }
  system("PAUSE");	
  return 0;
}

Download

Il download dell’applicazione (compilata per Win32) è disponibile qui, in formato compresso zip. Sono compresi i sorgenti e i files di progetto per il compilatore DevC++ (ver.: 4.9.9.2). Per l’utilizzo è sufficiente lanciare il programma da una console DOS e passare come parametro il numero da testare.

Conclusioni:

Adottare il metodo della Wheel Factorization per testare la primalità di un numero, consente un incremento di performance pari a (1 – 8 /30) * 100 = 73% con una ruota di dimensioni 30. Le prestazioni possono crescere aumentando le dimensioni della ruota, specialmente quando si ragiona con numeri abbastanza grandi. Il codice proposto utilizza al massimo numeri di 4 byte (unsigned long int = 4,294,967,295) e le performance rimangono accettabili ricompilando per numeri di 8 byte (unsigned long long = 18,446,744,073,709,551,615). In questo caso però sarebbe consigliabile utilizzare una ruota prodotta dai primi 8 numeri primi, come suggerito nell’articolo da cui ho tratto lo spunto per il codice.

Riferimenti ed approfondimenti:

PHP: Quando Tartaglia e Fibonacci si davano la mano

Tartaglia e FibonacciDi certo, in vita i due non si sarebbero mai potuti dare la mano, essendo vissuti in epoche distanti ben tre secoli. Fibonacci, al secolo Leonardo Pisano, visse infatti a cavallo del 1200 ed era di famiglia benestante essendo il padre (Bonaccio, da qui il nome FiBonacci) il segretario della Repubblica di Pisa e responsabile del commercio con l’Africa. Fu proprio in Africa che ebbe modo di studiare le avanzate tecniche matematiche, al tempo in possesso del mondo arabo.
Tartaglia, al secolo Niccolò Fontana visse a cavallo del 1500 fra Brescia e Verona. Era di famiglia tutt’altro che ricca, e rimase orfano di padre quando era ancora molto giovane. Ebbe anche la disgrazia di rimanere sfregiato durante il sacco di Brescia del 1512 ad opera dell’esercito francese. A leggere il suo stesso racconto c’è da stupirsi di come sia riuscito a sopravvivere a ferite così gravi. Rimase diversi giorni senza poter parlare e mangiare cibi solidi proprio a causa dei colpi di spada inferti sulla sua testa, e quando guarì non riuscì più a parlare senza balbettare, da questo il suo soprannome Tartaglia con il quale divenne famoso.

Il triangolo di Tartaglia

Tutti noi ricordiamo, dai tempi delle superiori, la piramide di numeri che compongono il famoso triangolo di Tartaglia, e lo ricordiamo soprattutto in relazione allo studio delle potenze di un binomio.

Triangolo di Tartaglia

Ogni riga, riporta i coefficienti dell’espansione del binomio con esponente uguale al numero di riga – 1 (iniziando a contare dal vertice della piramide) Così ad esempio, per esponente 3 avremo:
(a + b)3 = 1a3 + 3a2b + 3ab2 + 1b3

La successione di Fibonacci

La successione dei numeri di Fibonacci è nota soprattutto per la particolarità che il rapporto tra un numero e quello precedente, man mano che si procede nella successione, tende alla sezione aurea La successione fu trovata da Fibonacci, rispondendo al quesito: “Supponiamo di avere una coppia di conigli, che dopo un mese è in grado di generare una seconda coppia di conigli, quante coppie avremo in un anno?” (Ammesso che ogni coppia generi sempre e solo una coppia al mese e nessuno muoia…). Il procedimento è molto semplice: ogni numero, ad eccezione dei primi due (1, 1), è la somma dei due che lo precedono. Quindi:
F(12) = 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144

Dove si incontrano Tartaglia e Fibonacci?

Per capire il punto di contatto fra i due, è necessario modificare la forma del triangolo di Tartaglia, disponendo i numeri nelle celle che costituiscono un triangolo rettangolo piuttosto che isoscele, in questo modo:

Triangolo di Tartaglia

I numeri che costituiscono le diagonali ascendenti di questa matrice triangolare, sommati fra loro, generano la successione di Fibonacci.

Ecco dunque una classe PHP che calcola i valori del triangolo di Tartaglia e poi estrae dalle diagonali ascendenti i numeri della successione di Fibonacci.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class tartfibo
{
  var $tartaglia;
  var $fibonacci;
  var $max;
 
  function tartfibo($max=10)
  {
    $this->max = $max;
    $this->tartaglia = array();
    $this->fibonacci = array();    
    $this->makeTartaglia();
    $this->makeFibonacci();
  }
 
  function makeTartaglia ()
  {
    $this->tartaglia[1][1] = 1;
    $this->tartaglia[2][1] = 1;
    $this->tartaglia[2][2] = 1;
    for($row=3; $row< =$this->max; ++$row) {
      $this->tartaglia[$row][1] = 1;
      for ($col=2; $col< $row; ++$col) {
        $this->tartaglia[$row][$col] = $this->tartaglia[$row-1][$col-1]
                                + $this->tartaglia[$row-1][$col];
      }
      $this->tartaglia[$row][$row] = 1;
    }    
  }
 
  function makeFibonacci ()
  {
    for ($d=1; $d< =$this->max; ++$d) {
      $t = 0;
      for($el=1; $el< =($d+1)/2; ++$el) {
        $t += $this->tartaglia[$d+1-$el][$el];
      }
      $this->fibonacci[$d] = $t;
    }
  }  
}

Demo:

In questa pagina è visibile una demo della classe per n=15.

Download

Il download della classe è disponibile qui.

Conclusioni:

Il triangolo di Tartaglia racchiude nei suoi numeri, diversi piccoli segreti e non è solo un metodo per calcolare i coefficienti binomiali. Provate, per esempio a sommare i numeri di ciascuna riga, partendo dall’alto, danno le potenze di 2. Esistono persino dei frattali! Infine, due grandi matematici, Newton e Pascal hanno rielaborato il suo triangolo per lo studio del calcolo combinatorio. Anche i numeri di Fibonacci, oltre alla relazione con la sezione aurea, hanno implicazioni interessanti, sia con la disposizione geometrica di molte strutture naturali (piante soprattutto) che con l’informatica, per esempio: Fibonacci heap

Riferimenti ed approfondimenti:

Gestione fatture: un’applicazione completa in P4A

Screenshot di Gestione fatture
Screenshot di Gestione fatture

Questa applicazione web si basa sul framework PHP: P4A 3. Si tratta di una versione migliorata e corretta del codice già presentato in questo post. E’ un’applicazione completa per la gestione delle fatture, pensata soprattutto per chi eroga prestazioni, più che prodotti, in quanto non contempla una gestione del magazzino. Può essere utile per chi, come me, fa consulenze informatiche e realizza software, oppure per piccole aziende di autotrasporto che lavorano principalmente conto terzi o per artigiani e professionisti che non utilizzano un magazzino.
Non può essere utilizzata però da coloro i quali sono iscritti ad un albo professionale, in quanto, da informazioni ricevute da un commercialista, mi risulta che il calcolo della ritenuta d’acconto e delle trattenute INPS sia leggermente differente.

Maschere:

  • Gestione azienda: in questa maschera è possibile definire la ragione sociale, i dati anagrafici e il logo dell’azienda, definire l’utente e la password e impostare il tipo di fatturazione: IVA fissa, IVA variabile, ritenuta d’acconto, contributo INPS (queste ultime due opzioni sono possibili solo con IVA fissa).
  • Gestione clienti: in questa maschera vengono immessi i dati anagrafici dei clienti.
  • Fatture: è la maschera principale per creare e modificare le fatture. E’ divisa in due parti selezionabili attraverso delle ‘linguette’ come per gli schedari. La sezione ‘fatture’ permette di inserire una nuova fattura vuota, indicando la data, il numero, il cliente e la tipologia di pagamento. E’ anche possibile indicare se la fattura è stata pagata attraverso un flag ed inserire eventuali note. Il numero viene suggerito automaticamente seguendo la progressione dell’anno in corso, è però possibile immetterlo manualmente, in questo caso esiste un controllo per evitare duplicati.
    La sezione ‘Dettaglio fattura’ serve per inserire la lista di prestazioni o prodotti da fatturare. E’ possibile raggruppare una lista attraverso il campo ‘sezione’. Gli altri campi da riempire sono la descrizione, la quantità il prezzo e l’IVA (se non si è scelta la modalità IVA fissa). In fondo alla maschera vengono riportati i valori del totale imponibile, totale IVA e totale fattura. (totale ritenuta d’acconto e contributo INPS, solo se lo si è attivato nella Gestione azienda).
    Attraverso il pulsante di stampa, viene generato un documento pdf stampabile con la fattura impaginata in una o più pagine (in questo caso numerate) e la dicitura del destinatario allineata con l’apertura delle buste a ‘finestra’ standard.
  • Lista fatture: attraverso questo report è possibile filtrare le fatture di un certo periodo, visualizzare e stampare su pdf l’elenco e i totali dell’imponibile, delle fatture e i totali di quelle pagate e quelle no.
  • Tipo pagamenti: E’ possibile inserire le varie modalità di pagamento (assegno, bonifico, riba ecc.)
  • Unità di misura: E’ possibile inserire le unità di misura (ore, pezzi, kg, ecc.)

Alcune note sull’utilizzo:
Per aggiungere un nuovo record, è sempre necessario utilizzare il pulsante ‘Inserisci un nuovo elemento’, e una volta compilati i campi, premere il pulsante ‘Conferma e salva’. Nel caso di inserimento di una nuova fattura, dopo aver salvato e prima di inserire la lista delle prestazioni, è necessario selezionare con il puntatore (triangolino nero) la fattura appena creata. Per creare dei blocchi di prestazioni, inserire una dicitura nel campo ‘sezione’, in questo modo, i nuovi record creati con la stessa dicitura nel campo sezione, saranno raggruppati e ordinati alfabeticamente in fattura.

Installazione

Deve innazitutto essere installato il framework P4A versione 3.2.x (dettagli per il download e l’installazione). Poi è sufficiente scompattare l’archivio compresso nella direcory ‘applications’ che si trova sotto la directory ‘P4A’, caricare il dump .sql del database che si trova nella directory ‘_private’ in un server ‘MySQL’ e impostare i parametri per la connessione nel file ‘index.php’ (Nella maggioranza dei casi questo potrebbe non essere necessario). Chi utilizza linux, deve ricordarsi di dare i permessi di scrittura alla directory ‘uploads’ e alle sue subdirectories. Se il server web è installato localmente, per accedere all’applicazione digitare la url ‘http://localhost/p4a/applications/gestionefatture/’
Infine, volendo personalizzare l’aspetto grafico dell’applicazione, suggerisco questo articolo.

Il nome utente e la password per l’accesso iniziale sono: user = ‘utente’ e password = ‘utente’

Demo:

La demo non è disponibile.

Download

  • gestione fatture in formato compresso zip
  • gestione fatture in formato compresso tar bz2

Licenza

La licenza applicata è la LGPLv3

Conclusioni:

Considerando che l’applicazione viene fornita gratuitamente, non garantisco nessun supporto ufficiale e non mi assumo alcuna responsabilità per eventuali anomalie di funzionamento. Sono comunque disponibile a correggere gli errori che mi segnalerete e a valutare eventuali upgrade, compatibilmente con il tempo richiesto.

Riferimenti ed approfondimenti: