Search 1.9 billion lines of Odoo code on GitHub

demo_multi_company

Author: My Company
License: no license
Branch: master
Repository: twtrubiks/odoo-demo-addons-tutorial
Dependencies: account
Languages: Markdown (103, 52.0%), Python (37, 18.7%), and XML (58, 29.3%)

<h1>odoo 觀念 - multi company</h1> <p>建議觀看影片, 會更清楚:smile:</p> <p><a href="https://youtu.be/u8u0eRzY8kg">Youtube Tutorial - odoo 手把手教學 - multi company - part1</a></p> <p>建議在閱讀這篇文章之前, 請先確保了解看過以下的文章 (因為都有連貫的關係)</p> <p><a href="https://github.com/twtrubiks/odoo-demo-addons-tutorial/tree/master/demo_odoo_tutorial">odoo 手把手建立第一個 addons</a></p> <p>本篇文章主要介紹 odoo 中的 multi company 的一小部份:smile:</p> <p>因為 multi company 的方法有很多種.</p> <h2>說明</h2> <p>首先, odoo 在 Multi-company 的設計上是有很多想法以及方法的,</p> <p>可參考官方文件 <a href="https://www.odoo.com/documentation/14.0/developer/howtos/company.html">Multi-company Guidelines</a> 觀看.</p> <p>(補充一下, 從 odoo13 開始, Multi-company 的概念有改動, 但不影響本篇的教學:relaxed:)</p> <p>今天主要是要介紹 fields 中的一個參數 <code>company_dependent=True</code>,</p> <p>這個參數主要是為了 Multi-company 設計的.</p> <p>寫法很簡單, 就是在 model 中加入參數即可</p> <p><a href="https://github.com/twtrubiks/odoo-demo-addons-tutorial/blob/master/demo_multi_company/models/model.py">models/model.py</a></p> <p>```python ......</p> <p>class DemoCompany(models.Model): _name = &#39;demo.company&#39; _description = &#39;Demo Company&#39;</p> <pre><code>name = fields.Char(&#39;Description&#39;, required=True) property_account_receivable_id = fields.Many2one(&#39;account.account&#39;, company_dependent=True, string=&quot;Account Receivable&quot;, domain=&quot;[(&#39;internal_type&#39;, &#39;=&#39;, &#39;receivable&#39;), (&#39;deprecated&#39;, &#39;=&#39;, False)]&quot;, required=True) company_id = fields.Many2one(&#39;res.company&#39;, string=&#39;Company&#39;, required=True, readonly=True, default=lambda self: self.env.user.company_id) </code></pre> <p>...... ```</p> <p>主要就是 <code>property_account_receivable_id</code> 中的 <code>company_dependent=True</code>.</p> <p>在 view 的介面底下是可以看到這個欄位</p> <p><img src="https://i.imgur.com/fRZ4ioI.png" alt="alt tag"></p> <p>如果你有多公司, 切換到其他的公司, 你會發現這個欄位有可能會變空的.</p> <p>(切換公司時, 內容也會不一樣, 注意這邊是相同的 record)</p> <p><img src="https://i.imgur.com/HCFwDd3.png" alt="alt tag"></p> <p>但你在 db 中的 <code>demo_company</code> 不會有 <code>property_account_receivable_id</code> 的欄位</p> <p><img src="https://i.imgur.com/fz0aK8h.png" alt="alt tag"></p> <p>這邊你可能會覺得很奇怪, 但這就是他特別的地方:smile:</p> <p>那他會存在哪裡呢:question:</p> <p>他會存在 <code>ir_property</code> 中</p> <p><img src="https://i.imgur.com/I9T8uVx.png" alt="alt tag"></p> <p>在後台的部份, 也可以看到 <code>ir_property</code> 的東西</p> <p>路徑在 <code>Technical -&gt; Parameters -&gt; Company Properties</code></p> <p><img src="https://i.imgur.com/Xf55Oip.png" alt="alt tag"></p> <p>裡面的值, 紀錄著 model 和 id</p> <p><img src="https://i.imgur.com/k3VIApY.png" alt="alt tag"></p> <p>然後請把 Resource(res_id) 手動清空,</p> <p><img src="https://i.imgur.com/AZir7v0.png" alt="alt tag"></p> <p>等下要示範使用以下的 code 來取值</p> <p><code>python self.env[&#39;ir.property&#39;].with_context(force_company=self.company_id.id).get(&#39;property_account_receivable_id&#39;, &#39;demo.company&#39;) </code></p> <p>要清空的原因是因為其他的 Company Properties 很多是使用 code 的方式產生的</p> <p>原始碼中的 <code>odoo/addons/account/models/chart_template.py</code></p> <p><code>python @api.multi def generate_properties(self, acc_template_ref, company): ...... PropertyObj = self.env[&#39;ir.property&#39;] todo_list = [ (&#39;property_account_receivable_id&#39;, &#39;res.partner&#39;, &#39;account.account&#39;), (&#39;property_account_payable_id&#39;, &#39;res.partner&#39;, &#39;account.account&#39;), (&#39;property_account_expense_categ_id&#39;, &#39;product.category&#39;, &#39;account.account&#39;), (&#39;property_account_income_categ_id&#39;, &#39;product.category&#39;, &#39;account.account&#39;), (&#39;property_account_expense_id&#39;, &#39;product.template&#39;, &#39;account.account&#39;), (&#39;property_account_income_id&#39;, &#39;product.template&#39;, &#39;account.account&#39;), ] </code></p> <p><code>property_account_receivable_id</code> <code>property_account_payable_id</code> ... 都是 code 產生的.</p> <p>(這些透過 code 產生的值 res_id 都是 False)</p> <p>而 Resource(res<em>id) 清空的原因則是因為原始碼中的 `odoo/addons/base/models/ir</em>property.py`</p> <p>```python ......</p> <p>def <em>get</em>property(self, name, model, res<em>id): domain = self.</em>get<em>domain(name, model) if domain is not None: domain = [(&#39;res</em>id&#39;, &#39;=&#39;, res<em>id)] + domain #make the search with company</em>id asc to make sure that properties specific to a company are given first return self.search(domain, limit=1, order=&#39;company_id&#39;) return self.browse(())</p> <p>...... ```</p> <p>通常 domain 這邊的 res_id 會是 False. (如果有值就會被過濾掉)</p> <p>```python class DemoCompany(models.Model): _name = &#39;demo.company&#39; _description = &#39;Demo Company&#39;</p> <pre><code>...... def action_get_default_account(self): default_account = self.env[&#39;ir.property&#39;].with_context(force_company=self.company_id.id).get(&#39;property_account_receivable_id&#39;, &#39;demo.company&#39;) _logger.warning(default_account) _logger.warning(self.property_account_receivable_id) _logger.warning(&#39;============= HELLO ==================&#39;) </code></pre> <p>```</p> <p>點選這個按鈕可以觸發這個 function</p> <p><img src="https://i.imgur.com/X5xPuZ5.png" alt="alt tag"></p> <p>你會發現輸出一樣的資訊</p> <p>一個是透過 company<em>id 找出當下對應的 model 中的 `property</em>account<em>receivable</em>id`,</p> <p>另一個則是直接呼叫 model 中的 <code>property_account_receivable_id</code>.</p> <p><img src="https://i.imgur.com/k5KTLXH.png" alt="alt tag"></p> <p>當你嘗試著新增 record, 你會發現 <code>property_account_receivable_id</code> 預設都會有值</p> <p>(這也是為甚麼我和大家說要清空 res_id 的原因, 因為 odoo 的 code 中是這樣設定的, 前面有說明)</p> <p><img src="https://i.imgur.com/e4vLm0A.png" alt="alt tag"></p>