Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix typo #3

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@

Codice della documentazione prodotta per il [workshop introduttivo allo sviluppo moduli Odoo](https://metadonors.github.io/odoo.workshop/).

## Utilizzo
## Utilizzo

La documentazione è stata prodotta utilizzanto il generatore di siti statici [Hugo](https://gohugo.io/).

[Documentazione Hugo](https://gohugo.io/documentation/)

Dopo aver installato Hugo sul proprio computer, è possibile modificare i file contenuti nella cartella _content_ e avviare la compilazione del sito statico lanciando il comando
Dopo aver installato Hugo sul proprio computer, è possibile modificare i file contenuti nella cartella _content_ e avviare la compilazione del sito statico lanciando il comando

```
$ hugo
```
oppure editarlo avvalendosi dell'aggiornamento real time lanciando il comando

```
$ hugo server
```

nella root di questo repository.

10 changes: 5 additions & 5 deletions content/api/panoramica.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ weight: 1

---

Il server di Odoo fornisce un API esterna che può essere utilizzata da applicazioni terze per integrarsi. L'API sono le stesse che utilizza il client web ufficiale di Odoo per funzionare. Quindi qualsiasi funzionalità utlizzata nel client web può essere utilizzita direttamente tramite API.
Il server di Odoo fornisce un API esterna che può essere utilizzata da applicazioni terze per integrarsi. L'API sono le stesse che utilizza il client web ufficiale di Odoo per funzionare. Quindi qualsiasi funzionalità utlizzata nel client web può essere utilizzata direttamente tramite API.

Le API di Odoo supportano i protocolli XML-RPC e JSON-RPC, è quindi possibili scrivere integrazioni in qualsiasi linguaggio che supporti questi due protocolli. Per esempio nella [documentazione ufficiale](https://www.odoo.com/documentation/11.0/webservices/odoo.html) ci sono esempi per: Python, PHP, Ruby e Java.

Per questioni di chiarezza continueremo con i nostri esempi in Python. Inoltre faremo ricorso a una libreria python specifica che crea un'astrazione sopra le API base per ricreare un'interfaccia quanto più possibile a quella utilizzata direttamente all'interno del framework.

La libreria a cui faremo ricorso è [OdooRPC](https://pypi.org/project/OdooRPC/)

Solitamente potete installarla nel vostro ambiente python con il comando
Solitamente potete installarla nel vostro ambiente python con il comando

```bash
$ pip install OdooRPC
```

Per semplificare però gli esempi di questo corso, abbiamo aggiungo un comando specifico alla nostra immagine docker che ci permette di avviare una shell interattiva _ipython_ con la libreria già installata. Per farlo apriamo un altro terminale e digitiamo:
Per semplificare però gli esempi di questo corso, abbiamo aggiunto un comando specifico alla nostra immagine docker che ci permette di avviare una shell interattiva _ipython_ con la libreria già installata. Per farlo apriamo un altro terminale e digitiamo:

```bash
$ cd odoo.dockerenv/
Expand All @@ -33,7 +33,7 @@ Ci comparirà quindi il seguente output:
odoo.dockerenv (completed) $ docker compose run odoo ipython

Starting odoodockerenv_postgres_1 ... done
Python 3.5.3 (default, Jan 19 2017, 14:11:04)
Python 3.5.3 (default, Jan 19 2017, 14:11:04)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.

Expand All @@ -45,4 +45,4 @@ Out[2]: <module 'odoorpc' from '/usr/local/lib/python3.5/dist-packages/odoorpc/_

### Continua

A questo punto siamo in grado di effettuare le nostre chiamate, vediamo nel dettaglio [come procedere](/odoo.workshop/api/operazioni/)
A questo punto siamo in grado di effettuare le nostre chiamate, vediamo nel dettaglio [come procedere](/odoo.workshop/api/operazioni/)
18 changes: 9 additions & 9 deletions content/application_logic/usare_orm.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Fino a questo punto abbiamo utilizzato l'ORM di Odoo senza scendere nel dettagli

### Decoratori

Abbiamo notato che a molti metodi dei modelli viene applicato un decoratore come [email protected]_. Questi decorati hanno lo scopo di istruire il backend su come gestire i metodi rispetto alle API esposte.
Abbiamo notato che a molti metodi dei modelli viene applicato un decoratore come [email protected]_. Questi decorati hanno lo scopo di istruire il backend su come gestire i metodi rispetto alle API esposte.

Il decoratore **@api.model** invece si utilizza per decorare metodi statici in cui il _self_ non fa rifermento a nessuna entità in particolare. Per coerenza _self_ farà sempre riferimento a un oggetto di tipo recordset ma il suo contenuto diventa irrilevante. Questo tipo di metodi non possono essere richiamati dalle API e quindi non possono essere usati sui bottoni nell'interfaccia utente.

Expand Down Expand Up @@ -44,7 +44,7 @@ I metodi principali utilizzabili nei modelli sono quelli disponibili sulla [docu

### Interrogare i modelli

Attraverso la variabile _self_ possiamo accedere solamente ai metodi del modello che stiamo attualmente utilizzando. Ma ogni modello ha un variabile _env_, accesssibile tramite _self.env_ che ci permette di avere un riferimento a qualsiasi modello installato sul sistema. Per esempio _self.env['res.parner']_ restituisce un riferimento al modello dei Partner permettendoci quindi di utilizzare metodi come _search_ o _browse_ su quel determinato set di dati.
Attraverso la variabile _self_ possiamo accedere solamente ai metodi del modello che stiamo attualmente utilizzando. Ma ogni modello ha un variabile _env_, accessibile tramite _self.env_ che ci permette di avere un riferimento a qualsiasi modello installato sul sistema. Per esempio _self.env['res.parner']_ restituisce un riferimento al modello dei Partner permettendoci quindi di utilizzare metodi come _search_ o _browse_ su quel determinato set di dati.

Il metodo _search()_ accetta come paramentro un _domain_ e restituisce un recordset contenente le righe che rispettano le condizioni del dominio. Passando un _domain_ vuoto ([]) si ottengono tutte le righe presenti. Gli altri paramentri accettati da _search()_ sono:

Expand All @@ -70,7 +70,7 @@ Out[5]: 'Administrator'

### Operazioni sui recordset

I Recordset supportano diverse operazioni. Possiamo per esempio controllare se un elemento è contenuto in un recordset oppure no.
I Recordset supportano diverse operazioni. Possiamo per esempio controllare se un elemento è contenuto in un recordset oppure no.

Considerando _x_ un singleton e _test\_recordset_ un insieme di elementi possiamo scrivere

Expand All @@ -87,7 +87,7 @@ Sono inoltre dissponibili le seguenti proprietà:

### Manipolazione dei recordset

Per aggiungere, togliere o sostituire elementi dai recorset ci sono una serie di operatori che ci possono aiutare. I recordset di per sè sono immutabili ma attraverso questi operatori è possibile generare nuovi recordset modificati partendo da quelli esistenti
Per aggiungere, togliere o sostituire elementi dai recordset ci sono una serie di operatori che ci possono aiutare. I recordset di per sè sono immutabili ma attraverso questi operatori è possibile generare nuovi recordset modificati partendo da quelli esistenti

Gli operatori di manipolazione sono:

Expand All @@ -98,20 +98,20 @@ Gli operatori di manipolazione sono:

È inoltre possibile accedere agli elementi dei recordset attverso gli operatori di list Python, queste sono quindi espressioni valide:

- _rs[0]_ il primo elemento del recordset
- _rs[-1]_ l'ultimo elemento del recordset
- _rs[0]_ il primo elemento del recordset
- _rs[-1]_ l'ultimo elemento del recordset
- _rs[1:]_ restituisce una copia del recordset senza il primo elemento

Altri operatori:

- _rs\_ids |= element\_id_ aggiunge _element\_id_ al recordset _rs\_ids_ se non presente
- _rs\_ids -= element\_id_ rimuove _element\_id_ al recordset _rs\_ids_ se presente

### Query SQL
### Query SQL

E' sempre possibile accedere al databse direttametne eseguendo query SQL personalizzate. Nella varibile _self.env.cr_ è disponibile un cursore legato all'attuale connessione al db che possiamo utilizzare proprio a questo scopo.

Per effetturare una query utilizziamo il metodo _execute_ successitamente dobbiamo invocare un'altra funzione per ottenerne gli eventuali risultati:
Per effetturare una query utilizziamo il metodo _execute_ successivamente dobbiamo invocare un'altra funzione per ottenerne gli eventuali risultati:
- **fetchall()** restituisce una lista di tuple rappresentanti le righe
- **dictfetchall()** restituisce una lista di dizionari rappresentanti le righe con il nome della colonna utilizzato come chiave

Expand Down Expand Up @@ -150,7 +150,7 @@ Quando dobbiamo scrivere un campo *Many2one* dobbiamo ricordarci di passare solo
In [17]: self.write({'user_id': self.env.user.id})
```

ma darebbe invece errore
ma darebbe invece errore

```python
# SBAGLIATO
Expand Down
36 changes: 18 additions & 18 deletions content/application_logic/wizard.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ todo_plus/
__manifest__.py
```

All'interno del file _task\_plus/\_\_init.py\_\__ aggiungiamo
All'interno del file _task\_plus/\_\_init.py\_\__ aggiungiamo

```python
from . import wizards
```

All'interno del file _task\_plus/wizards/\_\_init.py\_\__ aggiungiamo
All'interno del file _task\_plus/wizards/\_\_init.py\_\__ aggiungiamo

```python
from . import todo_wizard
```

All'interno del file _task\_plus/\_\_manifest.py\_\__ aggiungiamo
All'interno del file _task\_plus/\_\_manifest.py\_\__ aggiungiamo

```python
{
Expand Down Expand Up @@ -82,7 +82,7 @@ class TodoWizard(models.TransientModel):
Le viste dei wizard sono uguali alle viste classiche, con due differenze:

- Può essere inserita una sezione \<footer\> per contenere i pulsanti del wizard
- Può essere inserito un pulsante con _special="cancel"_ che si ooccupa di chiudere il wizard
- Può essere inserito un pulsante con _special="cancel"_ che si occupa di chiudere il wizard

Quindi apriamo il file _task\_plus/wizards/task\_wizard.xml_ e scriviamo

Expand All @@ -108,8 +108,8 @@ Quindi apriamo il file _task\_plus/wizards/task\_wizard.xml_ e scriviamo
</field>

<group>
<group> <field name="new_user_id"/></group>
<group> <field name="new_deadline_date"/></group>
<group> <field name="new_user_id"/></group>
<group> <field name="new_deadline_date"/></group>
</group>

<footer>
Expand All @@ -121,13 +121,13 @@ Quindi apriamo il file _task\_plus/wizards/task\_wizard.xml_ e scriviamo
</field>
</record>

<act_window
id="todo_app.action_todo_wizard"
name="Todo Wizard"
src_model="todo.task"
res_model="todo.wizard"
view_mode="form"
target="new"
<act_window
id="todo_app.action_todo_wizard"
name="Todo Wizard"
src_model="todo.task"
res_model="todo.wizard"
view_mode="form"
target="new"
multi="True"/>
</odoo>

Expand Down Expand Up @@ -158,7 +158,7 @@ import logging
log = logging.getLogger(__name__)
```

nel corpo della classe invece aggiungiamo
nel corpo della classe invece aggiungiamo

```python
@api.multi
Expand All @@ -167,18 +167,18 @@ def do_mass_update(self):

if not self.new_user_id:
raise exceptions.ValidationError("E' necessario specificare un utente")

log.debug("Mass update on todos %s" % self.todo_ids.ids)

vals = {}

if self.new_deadline_date:
vals['deadline_date'] = self.new_deadline_date

vals['user_id'] = self.new_user_id.id

self.todo_ids.write(vals)

```

Questo metodo solleva un errore se l'utente cerca di inviare il form senza specificare un responsabile da assegnare ai todo selezionati.
Expand All @@ -192,7 +192,7 @@ def do_count_todos(self):
raise exceptions.Warning("Ci sono %d todo ancora aperti" % count)
```

per l'ultimo metodo (Seleziona tutti) invece c'è un piccolo problema: ogni volta che premiamo un bottone in un wizard e la chiamata non ritorna un eccezione, Oddo chiude automaticamente la finestra popup. La soluzione a questo è qquella di restituire un'azione che dice ad odoo di riaprire il wizard, vediamo come:
per l'ultimo metodo (Seleziona tutti) invece c'è un piccolo problema: ogni volta che premiamo un bottone in un wizard e la chiamata non ritorna un eccezione, Odoo chiude automaticamente la finestra popup. La soluzione a questo è qquella di restituire un'azione che dice ad odoo di riaprire il wizard, vediamo come:

```python

Expand Down
2 changes: 1 addition & 1 deletion content/basics/installazione.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Inizializziamo il database di Odoo
$ docker compose run odoo upgrade base
```

Compose comincerà a scaricare tutte le nostre dipendenze, ,a procedura può durare diversi minuti in base alla connessione a internet disponibile.
Compose comincerà a scaricare tutte le nostre dipendenze, la procedura può durare diversi minuti in base alla connessione a internet disponibile.

Infine diciamo a compose di tirare su l'ambiente:

Expand Down
10 changes: 4 additions & 6 deletions content/basics/precorso.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Anche per questi strumenti l'installazione varia in base al sistema operativo us

### Linux

#### Docker
#### Docker


Per Ubuntu:
Expand Down Expand Up @@ -134,12 +134,10 @@ Per maggiori informazioni qui trovate la [pagina di documentazione specifica](ht

#### Docker e Docker Compose

Come per Mac è sufficiente scaricare [l'applicazione ufficiale dall'Docker Store]
(https://store.docker.com/editions/community/docker-ce-desktop-windows)
Come per Mac è sufficiente scaricare [l'applicazione ufficiale dall'Docker Store](https://store.docker.com/editions/community/docker-ce-desktop-windows)

Per maggiori informazioni qui trovate la [pagina di documentazione specifica]
(https://docs.docker.com/docker-for-windows/install/#where-to-go-next)
Per maggiori informazioni qui trovate la [pagina di documentazione specifica](https://docs.docker.com/docker-for-windows/install/#where-to-go-next)

## Continua...

Una volta terminata questa procedura siete pronti ad iniziare il corso [installando l'ambiete di sviluppo Odoo](/odoo.workshop/basics/installazione/)
Una volta terminata questa procedura siete pronti ad iniziare il corso [installando l'ambiente di sviluppo Odoo](/odoo.workshop/basics/installazione/)
6 changes: 3 additions & 3 deletions content/inheritance/aggiungere_funzionalita.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Apriamo il nostro file di manfiesto e modifichiamolo come segue:

Per aggiungere la classe al modello procediamo nella stessa maniera con cui abbiamo ereditato il modello esteso dal modello base. Andiamo ad aggiungere all'attributo _\_inherit_ il modello _mail.thread_

Apriamo il nostro file _models/task\_task.py_
Apriamo il nostro file _models/task\_task.py_

```python
class TodoTask(models.Model):
Expand All @@ -52,7 +52,7 @@ class TodoTask(models.Model):
Con questa semplice modifica il nostro modello thread acquisterà tutta la logica che gli serve per far funzionare la messaggistica. C'è anche da notare che mettendo due dipendenze siamo obbligati anche a specificare quale deve essere il nome del modello principale da cui ereditiamo, per questo aggiungiamo ancche l'attributo _\_name_.

{{% notice note %}}
Il modello _mail.thread_ è un **Abstract Class**, che significa che non ha una tabella sua di riferimento. Può essere ssolo utiilizzato in altri modelli e va a estendere le loro funzionalità. Quindi, nella pratica, aggiungendolo andrà a modificare direttamente la tabella originale e aggiungerà al modello i metodi necessari alle sue funzionalità. Per maggiori infomazioni consultate la [documentazione ufficiale di Odoo](https://www.odoo.com/documentation/11.0/reference/orm.html#model-reference).
Il modello _mail.thread_ è un **Abstract Class**, che significa che non ha una tabella sua di riferimento. Può essere solo utilizzato in altri modelli e va a estendere le loro funzionalità. Quindi, nella pratica, aggiungendolo andrà a modificare direttamente la tabella originale e aggiungerà al modello i metodi necessari alle sue funzionalità. Per maggiori infomazioni consultate la [documentazione ufficiale di Odoo](https://www.odoo.com/documentation/11.0/reference/orm.html#model-reference).
{{% /notice%}}


Expand Down Expand Up @@ -83,4 +83,4 @@ ricaricare la pagina e cominciare ad aggiungere commenti

### Continua

Il nostro upgrade del modulo base è finito, a questo punto possiamo andare a guardare più nel dettaglio cosa ci offre il framework Odoo. Cominciamo ad [analizzare i Modelli](/odoo.workshop/models/)
Il nostro upgrade del modulo base è finito, a questo punto possiamo andare a guardare più nel dettaglio cosa ci offre il framework Odoo. Cominciamo ad [analizzare i Modelli](/odoo.workshop/models/)
10 changes: 5 additions & 5 deletions content/inheritance/estendere_modelli.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ Per prima cosa andiamo a creare la cartella _models/_ con il file _\_\_init\_\_.
__manifest__.py
```

Inseriamo gli import necessari per far funzionare il codice Python mettendo all'interno del file _todo\_user/\_\_init\_\_.py_
Inseriamo gli import necessari per far funzionare il codice Python mettendo all'interno del file _todo\_user/\_\_init\_\_.py_

```python
from . import models
```

e all'interno del file _todo\_user/models/\_\_init\_\_.py_
e all'interno del file _todo\_user/models/\_\_init\_\_.py_

```python
from . import task
Expand All @@ -54,7 +54,7 @@ Come vedete non c'è nessun meccanismo python di eredità e anche il nome della

### Modificare campi esistenti

Aggiungere campi è piuttosto semplice, ma è anche possibile apportare modifiche a campi esitenti. Per farlo è sufficiente ridichiara il campo e passare solo gli attributi che si vogliono andare a modificare.
Aggiungere campi è piuttosto semplice, ma è anche possibile apportare modifiche a campi esitenti. Per farlo è sufficiente ridichiara il campo e passare solo gli attributi che si vogliono andare a modificare.

Per esempio per modificare il tooltip del campo name possiamo aggiungere il campo

Expand All @@ -68,15 +68,15 @@ Per vedere se le modifiche che abbiamo apportato sono corrette dobbiamo effettua

### Modificare i metodi del modello

Con l'eredità dei modelli, oltre ai campi, è posssibile anche i metodi associati. Aggiungere un nuovo metodo è semplice: è sufficiente dichiarare una nuova funzione. Se invece si vuole modificare il comportamento di un metodo esistente, si può procedere sovrascrivendo il metodo stesso ed è possibile, se necessario, invocare comunque il metodo padre con la funzione _super()_ di Python.
Con l'eredità dei modelli, oltre ai campi, è possibile anche i metodi associati. Aggiungere un nuovo metodo è semplice: è sufficiente dichiarare una nuova funzione. Se invece si vuole modificare il comportamento di un metodo esistente, si può procedere sovrascrivendo il metodo stesso ed è possibile, se necessario, invocare comunque il metodo padre con la funzione _super()_ di Python.

{{% notice warning %}}
Cambiare gli argomenti dei metodi esistenti può essere pericoloso perchè non potete sapere chi li sta già invocando. In caso sia necessario è opportuno inizializare gli argomenti con un valore predefinito.
{{% /notice%}}

Nel nostro caso vogliamo che quando un utente invoca il metodo _do\_clear\_done_ non vengano chiusi tutti i task completati ma solo quelli assegnati all'utente stesso oppure quelli non assegnati.

Per farlo aggiungiamo il seguente metodo all'oggetto _TodoTask_ nel file _models/task.py_
Per farlo aggiungiamo il seguente metodo all'oggetto _TodoTask_ nel file _models/task.py_

```python
def do_clear_done(self):
Expand Down
Loading