Search 1.9 billion lines of Odoo code on GitHub

odoo-academy

Author: MultidadosTI
License: AGPL-3
Branch: 8.0
Repository: multidadosti-erp/odoo-academy
Dependencies: base
Languages: Markdown (226, 50.1%), Python (91, 20.2%), and XML (134, 29.7%)
Other repositories: aldo774/odoo-academy, gustotc/odoo-academy, and rodrigets/odoo-academy

<h1>Odoo Academy</h1> <h4>Criação do Módulo Odoo Academy</h4> <p>A aplicação tera funcionalidades como a criação de cursos, alocação de aulas dentro desses cursos, estas que terão alunos e professores associados,terão data de inicio e término, vagas disponíveis e duração.</p> <h5>Estrutura básica do módulo:</h5> <p><code>bash ├── __init__.py ├── __openerp__.py ├── models │   ├── __init__.py │   ├── courses.py │   ├── partners.py │   └── session.py └── views ├── courses_view.xml ├── partners_view.xml └── session_view.xml </code> <code>__init__.py</code>: Este arquivo permite transformar a pasta em que esta alocado em módulo(estrutura que irá agrupar os arquivos presentes, facilitando na imporatação)</p> <p>```python</p> <h1>Arquivo <strong>init</strong> localizado em models</h1> <p>from . import courses from . import partners from . import session ```</p> <p><code>__openerp__.py</code>: Este arquivo permite funciona como manifesto do módulo, nele estão informações sobre a aplicação e especificações de dependências e views.</p> <p><code>python { &#39;name&#39;: &#39;Nome Módulo&#39; &#39;version&#39;: &#39;Versão Módulo&#39; &#39;summary&#39;: &#39;Sumário Módulo&#39; &#39;description&#39;: &#39;Descrição&#39; &#39;category&#39;: &#39;Categoria&#39; &#39;author&#39;: &#39;Autor da Aplicação&#39; &#39;website&#39;: &#39;Website&#39; &#39;license&#39;: &#39;licença(AGPL-3)&#39; &#39;depends&#39;:[&#39;dependencia.modulo1&#39;, &#39;dependencia.modulo12] &#39;data&#39;:[&#39;views/view1_view1.xml&#39;, &#39;views/view1_view2.xml], } </code></p> <h4>Criação das Models Session, Courses e Partners</h4> <p>-Dentro das models serão especificados os campos a serem exibidos nas views, especificação de dependencias nesses campos, os comportamentos/métodos executados, bem como seus gatilhos.</p> <h5>Modelo básico de uma model:</h5> <p>```python from openerp import fields, models, api</p> <p>Class Model1(models.Model):</p> <pre><code>_name = &#39;modulo.nomeclasse&#39; abool = fields.Boolean() achar = fields.Char() atext = fields.Text() anhtml = fields.Html() anint = fields.Integer() afloat = fields.Float() adate = fields.Date() abin = fields.Binary() aselection = fields.Selection([(&#39;valorASerGuardado1&#39;, &#39;TextoExibido1&#39;),(&#39;valorASerGuardado2&#39;, &#39;TextoExibido2&#39;)]) //Geralmente o campo abaixo fica em outra model, levando em consideração que se queira fazer relação entre models arel_id = fields.Many2one(comodel_name=&#39;res_partner&#39;) //O atributo &#39;rel_id&#39; trata-se do campo Many2one a qual se quer relacionar arel_ids = fields.One2many(comodel_name=&#39;res_partner&#39;, inverse_name = &#39;rel_id&#39;) //O método abaixo é acionado quando há mudanças em achar @api.onchange(achar) def _faz_alguma_coisa(self) ... pass def _faz_outra_coisa(self) ... pass </code></pre> <p>``` Os campos mostrados acima são opções que podem ser implementadas nos formulários que serão montados. dentro desses campos há diversas opções de <strong>atributos</strong>, que podem customizar sua aparência ou relaciona-los a gatilhos(openerp.api). </p> <p><code>python name = fields.Char( string=&quot;Name&quot;, compute=&quot;_compute_name_custom&quot;, store=True, select=True, readonly=True, inverse=&quot;_write_name&quot; required=True, translate=True, help=&#39;blabla&#39;, company_dependent=True, search=&#39;_search_function&#39; ) </code> Abaixo á uma lista dos que podem ser implementados.</p> <p><strong><em>string</em></strong>: string de exibição do campo.<br> <strong><em>compute</em></strong>: transforma o campo em questão em um campo computed, o associando a uma função que determinará seu valor dinamicamente.<br> <strong><em>store</em></strong>: Utilizado juntamente com o atributo <em>compute</em>, tem valor booleano, quando <em>True</em>, salva o campo na tabela da model em questão. <strong><em>select</em></strong>: Força um index no campo.<br> <strong><em>readonly</em></strong>: o campo não poderá ser alterado.<br> <strong><em>inverse</em></strong>: funciona como um gatilho, associa-se esse atributo a uma função, que será chamada sempre que houver atualizações.<br> <strong><em>required</em></strong>: torna o campo obrigatório, caso True.<br> <strong><em>translate</em></strong>: Ativa o Tranlation(tradutor).<br> <strong><em>help</em></strong>: cria um <em>help</em> para o campo, uma espécie de breve descrição.<br> <strong><em>search</em></strong>: atribui uma função de pesquisa customizada, geralmente utilizada em conjunto com o atributo <em>compute</em>.<br> <strong><em>company_dependent</em></strong>: Transforma o campo dependente a compania de registro, usuários cadastrados em diferentes companias, poderão ver valores diferentes para a mesma coluna.<br> <strong><em>default</em></strong>: Define um valor padrão para o campo.<br> <strong><em>related</em></strong>: torna o campo diretamente relacionado a alterações em outra model.<br></p> <h4>Criação das Views de Session, Courses e Partners</h4> <p>-Dentro das views serão alocados os campos criados nas models, e por meio de tags, customizar sua exibição/posicionamento.</p> <h5>Estrutura básica de uma view</h5> <p>```xml <openerp> <data></p> <pre><code> &lt;!--O menu abaixo será exibido na barra superior--&gt; &lt;menuitem id=&quot;id_novomenu&quot; name=&quot;Nome Módulo&quot; sequence=&quot;450&quot;/&gt; &lt;!--O atributo model classifica o tipo --&gt; &lt;!--de record criado, no caso abaixo ir.ui.view,--&gt; &lt;!--utilizado para views que exibirão estruturas--&gt; &lt;!--como form, tree, kanban, graph dentre outros--&gt; &lt;record model=&quot;ir.ui.view&quot; id=&quot;view_nomemodulo_nomemodel_form&quot;&gt; &lt;field name=&quot;name&quot;&gt;Nome Record&lt;/field&gt; &lt;field name=&quot;model&quot;&gt;Nome da Model&lt;/field&gt; &lt;field name=&quot;arch&quot; type=&quot;xml&quot;&gt; &lt;!--Neste espaço colocamos os campos criados--&gt; &lt;!--na model, e escolhemos o tipo de exibição--&gt; &lt;!--(tag de kanban, tree, form e etc), há--&gt; &lt;!--limitações de campos e atributos dependendo--&gt; &lt;!--do tipo de exibição escolhido, neste caso--&gt; &lt;!--exibiremos o tipo form(Exibira Formulario--&gt; &lt;form&gt; &lt;!--A tag &#39;header&#39; agrupa elementos no CABEÇALHO do formulário--&gt; &lt;header&gt; &lt;!--O &#39;widget&#39; statusbar transforma o campo do tipo select em uma status bar(também há um widget que o exibe em formato radio)--&gt; &lt;field name=&quot;aselection&quot; widget=&quot;statusbar&quot;/&gt; &lt;/header&gt; &lt;!--A tag &#39;sheet&#39; agrupa elementos no CORPO do formulário--&gt; &lt;sheet&gt; &lt;!--A tag &#39;group&#39; agrupa os campos--&gt; &lt;group&gt; &lt;field name=&quot;abool&quot;/&gt; &lt;field name=&quot;achar&quot;/&gt; &lt;field name=&quot;atext&quot;/&gt; &lt;field name=&quot;anint&quot;/&gt; &lt;/group&gt; &lt;button string=&quot;Faz Algo&quot; type=&quot;object&quot; name=&quot;_faz_outra_coisa&quot;/&gt; &lt;!--A tag notebook cria exibição em abas, que são identificadas pela tag &#39;page&#39;--&gt; &lt;notebook&gt; &lt;page string=&quot;String Pagina&quot;&gt; &lt;field name=&quot;arel_ids&quot;/&gt; &lt;/page&gt; &lt;/notebook&gt; &lt;/sheet&gt; &lt;/form&gt; &lt;/field&gt; &lt;/record&gt; &lt;record model=&quot;ir.ui.view&quot; id=&quot;view_nomemodulo_nomemodel_tree&quot;&gt; &lt;field name=&quot;name&quot;&gt;Nome Record&lt;/field&gt; &lt;field name=&quot;model&quot;&gt;Nome da Model&lt;/field&gt; &lt;field name=&quot;arch&quot; type=&quot;xml&quot;&gt; &lt;!--O tag tree, especificada abaixo, determina--&gt; &lt;!--que o record em questão, exibira os campos em--&gt; &lt;!--formato de lista--&gt; &lt;tree string=&quot;Session&quot;&gt; &lt;field name=&quot;achar&quot;/&gt; &lt;field name=&quot;aint&quot;/&gt; &lt;/tree&gt; &lt;/field&gt; &lt;/record&gt; &lt;!--Os menus abaixo serão exibidos na barra lateral--&gt; &lt;menuitem id=&quot;id_submenu&quot; name=&quot;Titulo Menu&quot; parent=&quot;id_novomenu&quot; sequence=&quot;1&quot;/&gt; &lt;!--O atributo &#39;action&#39; chama o record com o id especificado--&gt; &lt;menuitem id=&quot;submenu_model1&quot; name=&quot;Model1&quot; parent=&quot;id_submenu&quot; action=&quot;action_modulo_model&quot; sequence=&quot;1&quot;/&gt; &lt;record id=&quot;action_nomemodulo_nomemodel&quot; model=&quot;ir.actions.act_window&quot;&gt; &lt;field name=&quot;name&quot;&gt;Nome Record&lt;/field&gt; &lt;field name=&quot;type&quot;&gt;ir.actions.act_window&lt;/field&gt; &lt;field name=&quot;res_model&quot;&gt;Nome da Model&lt;/field&gt; &lt;field name=&quot;view_mode&quot;&gt;tree,form&lt;/field&gt; &lt;/record&gt; &lt;/data&gt; </code></pre> <p></openerp> ```</p> <h2>Módulo Locadora</h2> <p>Construa as models Categoria, Filme, OperacaoUnit, OperacaoConj e Cliente</p> <ul> <li><strong>Cliente:</strong> <ul> <li>filme_ids - many2many</li> <li>operacaoconj_ids - one2many</li> <li>valor_gasto - float(será um campo <em>compute</em>)</li> </ul></li> <li><strong>Categoria:</strong> <ul> <li>nome - char</li> <li>filme_ids - many2many</li> </ul></li> <li><strong>Filme:</strong> <ul> <li>titulo - char</li> <li>categoria_ids - many2many</li> <li>valor - float</li> <li>descrição - text</li> <li>data - date</li> <li>quantidade - int</li> <li>autor - char</li> </ul></li> <li><strong>OperacaoUnit:</strong> <ul> <li>operacaounit_id - many2one</li> <li>tipo - select [venda, aluguel]</li> <li>preco - float(será um campo <em>compute</em>)</li> <li>filme_ids - many2many</li> <li>status - select <a href="ser%C3%A1%20um%20campo%20*compute*">indisponível, em espera, disponível, atrasado</a></li> <li>dataOperacao - date</li> <li>dataEntrega - date(o campo em questão só fica aberto a escrita quando tipo(OperacaoUnit) é aluguel)</li> </ul></li> <li><strong>OperacaoConj:</strong> <ul> <li>operacaounit_ids - one2many</li> <li>cliente_id - many2one</li> <li>valor - float(será um campo <em>compute</em>)</li> </ul></li> </ul> <h5>Observações sobre alguns campos:</h5> <p>-O campo valor em OperacaoConj deve ser a soma de todos os preços definidos em instancias associadas de OperacaoUnit, será necessário utilizar o módulo api, mais especificamente o decorator api.depends(*mais detalhes sobre os decorator de api na <a href="https://www.odoo.com/documentation/8.0/reference/orm.html#module-openerp.api">documentação</a></p> <p>-O campo valor_gasto em Cliente deve ser a soma de todos os valores definidos em instancias associadas de OperacaoConj</p> <p>-Assim como foi dito acima, o campo preco(OperacaoUnit) é dependente direto de tipo(OperacaoUnit), dataEntrega(OperacaoUnit), e data(Filme), será necessário utilizar o módulo api, mais especificamente o decorator api.depends(<em>mais detalhes sobre os decorator de api na <a href="https://www.odoo.com/documentation/8.0/reference/orm.html#module-openerp.api">documentação</a></em>)</p> <p><em>Para mais detalhes de como manusear campos relacionais (one2many, many2one, many2many, visite a <a href="https://www.odoo.com/documentation/8.0/reference/orm.html#relational-fields">documentação oficial</a>, ou observe um <a href="https://www.odoo.com/documentation/8.0/howtos/backend.html">caso de uso</a> fornecido pelo odoo com exemplos de uso para cada campo relacional).</em></p> <h4>Detalhes do funcionamento do módulo</h4> <ul> <li><p>Ao salvar uma operaçãoUnit com tipo aluguel(alugar um filme), definir o preço como R$4,00 caso for lançamento(com campo data de no maximo 3 meses de diferença da data atual), senão definir preço como R$2,00.</p></li> <li><p>O prazo de entrega do filme é de 2 dias, caso haja atraso, cobrar juros simples de 50% do valor definido em preço(OperacaoUnit) por dia de atraso.</p></li> <li><p>Caso a operação seja do tipo venda, cobrar no filme um valor de 30% a mais do seu valor(Filme), e logicamente decrescer a quantidade do estoque.</p></li> <li><p>Ao criar uma OperacaoUnit o campo dataOperacao recebe a data atual.</p></li> <li><p>Ao alugar filme, este fica temporariamente fora de estoque, até ser devolvido(decrescido do estoque)</p></li> <li><p>Campo status deve ser um workflow com as opções que foram descritas na criação da model, os status a seguir terão os seguintes botões para edição de status.</p> <ul> <li>Alugar - somente em status &#39;Disponível&#39;</li> <li>Vender - somente em status &#39;Disponível&#39;</li> <li>Concluir - somente em status &#39;Em espera&#39; ou &#39;Atrasado&#39;</li> </ul></li> <li><p>A definição do status exibido por OperacaoUnit depende de algumas condições.</p> <ul> <li>Indisponível - quando não há cópias do filme em estoque, ou alugadas.</li> <li>Em espera - quando não há cópias em estoque porém existe cópias alugadas dentro do prazo de entrega, neste caso deve ser exibida a data de entrega da cópia do filme que foi alugada com data de entrega mais proxima da data atual(dentro do campo dataEntrega).</li> <li>Atrasado - quando não há cópias em estoque porém existem cópias alugadas dentro fora do prazo de entrega, neste caso esse status é exclusivo de OperacaoUnit que ainda estão a ser feitas(que ainda não foram criadas).</li> <li>Disponível - quando há cópias em estoque, diponíveis para operações(venda ou aluguel)</li> </ul></li> </ul> <p><em>Na documentação oficial há um exemplo de como criar um workflow completo segue o <a href="https://www.odoo.com/documentation/8.0/howtos/backend.html#workflows">link</a>)</em></p>