[IMP] analytic, project, *: Improve views
Improve the views of analytic.account and project.project. Add category to analytic.line. Task-2469742 PR #68708
This commit is contained in:
@@ -7,6 +7,9 @@ from odoo.exceptions import UserError
|
||||
class AccountAnalyticAccount(models.Model):
|
||||
_inherit = 'account.analytic.account'
|
||||
|
||||
invoice_count = fields.Integer("Invoice Count", compute='_compute_invoice_count')
|
||||
vendor_bill_count = fields.Integer("Vendor Bill Count", compute='_compute_vendor_bill_count')
|
||||
|
||||
@api.constrains('company_id')
|
||||
def _check_company_consistency(self):
|
||||
analytic_accounts = self.filtered('company_id')
|
||||
@@ -26,6 +29,55 @@ class AccountAnalyticAccount(models.Model):
|
||||
if self._cr.fetchone():
|
||||
raise UserError(_("You can't set a different company on your analytic account since there are some journal items linked to it."))
|
||||
|
||||
@api.depends('line_ids')
|
||||
def _compute_invoice_count(self):
|
||||
sale_types = self.env['account.move'].get_sale_types()
|
||||
domain = [
|
||||
('move_id.state', '=', 'posted'),
|
||||
('move_id.move_type', 'in', sale_types),
|
||||
('analytic_account_id', 'in', self.ids)
|
||||
]
|
||||
groups = self.env['account.move.line'].read_group(domain, ['move_id:count_distinct'], ['analytic_account_id'])
|
||||
moves_count_mapping = dict((g['analytic_account_id'][0], g['analytic_account_id_count']) for g in groups)
|
||||
for account in self:
|
||||
account.invoice_count = moves_count_mapping.get(account.id, 0)
|
||||
|
||||
@api.depends('line_ids')
|
||||
def _compute_vendor_bill_count(self):
|
||||
purchase_types = self.env['account.move'].get_purchase_types()
|
||||
domain = [
|
||||
('move_id.state', '=', 'posted'),
|
||||
('move_id.move_type', 'in', purchase_types),
|
||||
('analytic_account_id', 'in', self.ids)
|
||||
]
|
||||
groups = self.env['account.move.line'].read_group(domain, ['move_id:count_distinct'], ['analytic_account_id'])
|
||||
moves_count_mapping = dict((g['analytic_account_id'][0], g['analytic_account_id_count']) for g in groups)
|
||||
for account in self:
|
||||
account.vendor_bill_count = moves_count_mapping.get(account.id, 0)
|
||||
|
||||
def action_view_invoice(self):
|
||||
self.ensure_one()
|
||||
result = {
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "account.move",
|
||||
"domain": [('id', 'in', self.line_ids.move_id.move_id.ids), ('move_type', 'in', self.env['account.move'].get_sale_types())],
|
||||
"context": {"create": False},
|
||||
"name": "Customer Invoices",
|
||||
'view_mode': 'tree,form',
|
||||
}
|
||||
return result
|
||||
|
||||
def action_view_vendor_bill(self):
|
||||
self.ensure_one()
|
||||
result = {
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "account.move",
|
||||
"domain": [('id', 'in', self.line_ids.move_id.move_id.ids), ('move_type', 'in', self.env['account.move'].get_purchase_types())],
|
||||
"context": {"create": False},
|
||||
"name": "Vendor Bills",
|
||||
'view_mode': 'tree,form',
|
||||
}
|
||||
return result
|
||||
|
||||
class AccountAnalyticTag(models.Model):
|
||||
_inherit = 'account.analytic.tag'
|
||||
@@ -62,6 +114,7 @@ class AccountAnalyticLine(models.Model):
|
||||
move_id = fields.Many2one('account.move.line', string='Journal Item', ondelete='cascade', index=True, check_company=True)
|
||||
code = fields.Char(size=8)
|
||||
ref = fields.Char(string='Ref.')
|
||||
category = fields.Selection(selection_add=[('invoice', 'Customer Invoice'), ('vendor_bill', 'Vendor Bill')])
|
||||
|
||||
@api.onchange('product_id', 'product_uom_id', 'unit_amount', 'currency_id')
|
||||
def on_change_unit_amount(self):
|
||||
|
||||
@@ -5007,6 +5007,11 @@ class AccountMoveLine(models.Model):
|
||||
for move_line in self:
|
||||
amount = (move_line.credit or 0.0) - (move_line.debit or 0.0)
|
||||
default_name = move_line.name or (move_line.ref or '/' + ' -- ' + (move_line.partner_id and move_line.partner_id.name or '/'))
|
||||
category = 'other'
|
||||
if move_line.move_id.is_sale_document():
|
||||
category = 'invoice'
|
||||
elif move_line.move_id.is_purchase_document():
|
||||
category = 'vendor_bill'
|
||||
result.append({
|
||||
'name': default_name,
|
||||
'date': move_line.date,
|
||||
@@ -5023,6 +5028,7 @@ class AccountMoveLine(models.Model):
|
||||
'user_id': move_line.move_id.invoice_user_id.id or self._uid,
|
||||
'partner_id': move_line.partner_id.id,
|
||||
'company_id': move_line.analytic_account_id.company_id.id or move_line.move_id.company_id.id,
|
||||
'category': category,
|
||||
})
|
||||
return result
|
||||
|
||||
|
||||
@@ -69,5 +69,25 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_analytic_account_view_form_inherit" model="ir.ui.view">
|
||||
<field name="name">account.analytic.account.form.inherit</field>
|
||||
<field name="model">account.analytic.account</field>
|
||||
<field name="inherit_id" ref="analytic.view_account_analytic_account_form"/>
|
||||
<field eval="9" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="button_box" position="inside">
|
||||
<button class="oe_stat_button" type="object" name="action_view_invoice"
|
||||
icon="fa-pencil-square-o" attrs="{'invisible': [('invoice_count', '=', 0)]}">
|
||||
<field string="Customer Invoices" name="invoice_count" widget="statinfo"/>
|
||||
</button>
|
||||
<button class="oe_stat_button" type="object" name="action_view_vendor_bill"
|
||||
icon="fa-file-text-o" attrs="{'invisible': [('vendor_bill_count', '=', 0)]}">
|
||||
<field string="Vendor Bills" name="vendor_bill_count" widget="statinfo"/>
|
||||
</button>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -184,7 +184,7 @@ class AccountAnalyticLine(models.Model):
|
||||
amount = fields.Monetary('Amount', required=True, default=0.0)
|
||||
unit_amount = fields.Float('Quantity', default=0.0)
|
||||
product_uom_id = fields.Many2one('uom.uom', string='Unit of Measure', domain="[('category_id', '=', product_uom_category_id)]")
|
||||
product_uom_category_id = fields.Many2one(related='product_uom_id.category_id', readonly=True)
|
||||
product_uom_category_id = fields.Many2one(related='product_uom_id.category_id', string='UoM Category', readonly=True)
|
||||
account_id = fields.Many2one('account.analytic.account', 'Analytic Account', required=True, ondelete='restrict', index=True, check_company=True)
|
||||
partner_id = fields.Many2one('res.partner', string='Partner', check_company=True)
|
||||
user_id = fields.Many2one('res.users', string='User', default=_default_user)
|
||||
@@ -192,6 +192,7 @@ class AccountAnalyticLine(models.Model):
|
||||
company_id = fields.Many2one('res.company', string='Company', required=True, readonly=True, default=lambda self: self.env.company)
|
||||
currency_id = fields.Many2one(related="company_id.currency_id", string="Currency", readonly=True, store=True, compute_sudo=True)
|
||||
group_id = fields.Many2one('account.analytic.group', related='account_id.group_id', store=True, readonly=True, compute_sudo=True)
|
||||
category = fields.Selection([('other', 'Other')], default='other')
|
||||
|
||||
@api.constrains('company_id', 'account_id')
|
||||
def _check_company_id(self):
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
<record model="ir.actions.act_window" id="account_analytic_line_action">
|
||||
<field name="context">{'search_default_group_date': 1, 'default_account_id': active_id}</field>
|
||||
<field name="domain">[('account_id','=', active_id)]</field>
|
||||
<field name="name">Costs & Revenues</field>
|
||||
<field name="name">Gross Margin</field>
|
||||
<field name="res_model">account.analytic.line</field>
|
||||
<field name="view_mode">tree,form,graph,pivot</field>
|
||||
<field name="view_id" ref="view_account_analytic_line_tree"/>
|
||||
@@ -157,8 +157,14 @@
|
||||
<form string="Analytic Account">
|
||||
<sheet string="Analytic Account">
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button class="oe_stat_button" type="action" name="%(account_analytic_line_action)d"
|
||||
icon="fa-usd" string="Cost/Revenue" widget="statinfo"/>
|
||||
<button class="oe_stat_button" type="action" name="%(account_analytic_line_action)d" icon="fa-usd">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<span class="o_stat_text">Gross Margin</span>
|
||||
<span class="o_stat_value">
|
||||
<field name="balance" widget='monetary'/>
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
|
||||
<div class="oe_title">
|
||||
@@ -171,8 +177,8 @@
|
||||
<group name="main">
|
||||
<group>
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="code"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="code"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="group_id"/>
|
||||
@@ -321,6 +327,7 @@
|
||||
<group string="Group By..." expand="0" name="groupby">
|
||||
<filter string="Analytic Account" name="account_id" context="{'group_by': 'account_id'}"/>
|
||||
<filter string="Date" name="group_date" context="{'group_by': 'date'}"/>
|
||||
<filter string="Category" name='category' context="{'group_by': 'category'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
|
||||
@@ -24,6 +24,7 @@ If the automated inventory valuation is active, the necessary accounting entries
|
||||
"views/product_views.xml",
|
||||
"views/mrp_bom_views.xml",
|
||||
"views/mrp_production_views.xml",
|
||||
"views/analytic_account_views.xml",
|
||||
],
|
||||
'demo': [
|
||||
'data/mrp_account_demo.xml',
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import analytic_account
|
||||
from . import mrp_bom
|
||||
from . import mrp_workcenter
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class AccountAnalyticAccount(models.Model):
|
||||
_inherit = 'account.analytic.account'
|
||||
_description = 'Analytic Account'
|
||||
|
||||
production_ids = fields.One2many('mrp.production', 'analytic_account_id', string='Manufacturing Orders')
|
||||
production_count = fields.Integer("Manufacturing Orders Count", compute='_compute_production_count')
|
||||
bom_ids = fields.One2many('mrp.bom', 'analytic_account_id', string='Bills of Materials')
|
||||
bom_count = fields.Integer("BoM Count", compute='_compute_bom_count')
|
||||
workcenter_ids = fields.One2many('mrp.workcenter', 'costs_hour_account_id', string='Workcenters')
|
||||
workorder_count = fields.Integer("Work Order Count", compute='_compute_workorder_count')
|
||||
|
||||
@api.depends('production_ids')
|
||||
def _compute_production_count(self):
|
||||
for account in self:
|
||||
account.production_count = len(account.production_ids)
|
||||
|
||||
@api.depends('bom_ids')
|
||||
def _compute_bom_count(self):
|
||||
for account in self:
|
||||
account.bom_count = len(account.bom_ids)
|
||||
|
||||
@api.depends('workcenter_ids.order_ids', 'production_ids.workorder_ids')
|
||||
def _compute_workorder_count(self):
|
||||
for account in self:
|
||||
account.workorder_count = len(account.workcenter_ids.order_ids | account.production_ids.workorder_ids)
|
||||
|
||||
def action_view_mrp_production(self):
|
||||
self.ensure_one()
|
||||
result = {
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "mrp.production",
|
||||
"domain": [['id', 'in', self.production_ids.ids]],
|
||||
"name": "Manufacturing Orders",
|
||||
'view_mode': 'tree,form',
|
||||
"context": {'default_analytic_account_id': self.id},
|
||||
}
|
||||
if len(self.production_ids) == 1:
|
||||
result['view_mode'] = 'form'
|
||||
result['res_id'] = self.production_ids.id
|
||||
return result
|
||||
|
||||
def action_view_mrp_bom(self):
|
||||
self.ensure_one()
|
||||
result = {
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "mrp.bom",
|
||||
"domain": [['id', 'in', self.bom_ids.ids]],
|
||||
"name": "Bills of Materials",
|
||||
'view_mode': 'tree,form',
|
||||
"context": {'default_analytic_account_id': self.id},
|
||||
}
|
||||
if self.bom_count == 1:
|
||||
result['view_mode'] = 'form'
|
||||
result['res_id'] = self.bom_ids.id
|
||||
return result
|
||||
|
||||
def action_view_workorder(self):
|
||||
self.ensure_one()
|
||||
result = {
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "mrp.workorder",
|
||||
"domain": [['id', 'in', (self.workcenter_ids.order_ids | self.production_ids.workorder_ids).ids]],
|
||||
"context": {"create": False},
|
||||
"name": "Work Orders",
|
||||
'view_mode': 'tree',
|
||||
}
|
||||
return result
|
||||
|
||||
|
||||
class AccountAnalyticLine(models.Model):
|
||||
_inherit = 'account.analytic.line'
|
||||
|
||||
category = fields.Selection(selection_add=[('manufacturing_order', 'Manufacturing Order')])
|
||||
@@ -36,6 +36,7 @@ class MrpWorkorder(models.Model):
|
||||
'product_uom_id': self.product_id.uom_id.id,
|
||||
'company_id': self.company_id.id,
|
||||
'ref': self.production_id.name,
|
||||
'category': 'manufacturing_order',
|
||||
}
|
||||
|
||||
def _create_or_update_analytic_entry(self):
|
||||
|
||||
@@ -62,12 +62,13 @@ class TestAnalyticAccount(TransactionCase):
|
||||
self.assertEqual(mo.state, 'progress')
|
||||
self.assertEqual(mo.move_raw_ids.analytic_account_line_id.amount, -50.0)
|
||||
|
||||
# decrease qty_producing to 10.0
|
||||
# increase qty_producing to 10.0
|
||||
mo_form = Form(mo)
|
||||
mo_form.qty_producing = 10.0
|
||||
mo_form.save()
|
||||
# Hack to bypass test doing strange things
|
||||
mo._set_qty_producing()
|
||||
mo.workorder_ids.button_finish()
|
||||
self.assertEqual(mo.state, 'to_close')
|
||||
self.assertEqual(mo.move_raw_ids.analytic_account_line_id.amount, -100.0)
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="account_analytic_account_view_form_mrp" model="ir.ui.view">
|
||||
<field name="name">account.analytic.account.form.mrp</field>
|
||||
<field name="model">account.analytic.account</field>
|
||||
<field name="inherit_id" ref="analytic.view_account_analytic_account_form"/>
|
||||
<field eval="14" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="button_box" position="inside">
|
||||
<button class="oe_stat_button" type="object" name="action_view_mrp_production"
|
||||
icon="fa-wrench" attrs="{'invisible': [('production_count', '=', 0)]}">
|
||||
<field string="Manufacturing Orders" name="production_count" widget="statinfo"/>
|
||||
</button>
|
||||
<button class="oe_stat_button" type="object" name="action_view_mrp_bom"
|
||||
icon="fa-flask" attrs="{'invisible': [('bom_count', '=', 0)]}">
|
||||
<field string="Bills of Materials" name="bom_count" widget="statinfo"/>
|
||||
</button>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -140,7 +140,7 @@ class ProjectTaskType(models.Model):
|
||||
class Project(models.Model):
|
||||
_name = "project.project"
|
||||
_description = "Project"
|
||||
_inherit = ['portal.mixin', 'mail.alias.mixin', 'mail.thread', 'rating.parent.mixin']
|
||||
_inherit = ['portal.mixin', 'mail.alias.mixin', 'mail.thread', 'mail.activity.mixin', 'rating.parent.mixin']
|
||||
_order = "sequence, name, id"
|
||||
_rating_satisfaction_days = False # takes all existing ratings
|
||||
_check_company_auto = True
|
||||
@@ -234,6 +234,7 @@ class Project(models.Model):
|
||||
domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]", check_company=True,
|
||||
help="Analytic account to which this project is linked for financial management. "
|
||||
"Use an analytic account to record cost and revenue on your project.")
|
||||
analytic_account_balance = fields.Monetary(related="analytic_account_id.balance")
|
||||
|
||||
favorite_user_ids = fields.Many2many(
|
||||
'res.users', 'project_favorite_user_rel', 'project_id', 'user_id',
|
||||
@@ -604,6 +605,33 @@ class Project(models.Model):
|
||||
'project.open_view_project_all_group_stage')
|
||||
return action
|
||||
|
||||
def action_view_analytic_account_entries(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
'res_model': 'account.analytic.line',
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': _("Gross Margin"),
|
||||
'domain': [('account_id', '=', self.analytic_account_id.id)],
|
||||
'views': [(self.env.ref('analytic.view_account_analytic_line_tree').id, 'list'),
|
||||
(self.env.ref('analytic.view_account_analytic_line_form').id, 'form'),
|
||||
(self.env.ref('analytic.view_account_analytic_line_graph').id, 'graph'),
|
||||
(self.env.ref('analytic.view_account_analytic_line_pivot').id, 'pivot')],
|
||||
'view_mode': 'tree,form,graph,pivot',
|
||||
'context': {'search_default_group_date': 1, 'default_account_id': self.analytic_account_id.id}
|
||||
}
|
||||
|
||||
def action_view_kanban_project(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
'res_model': 'project.project',
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': _("Project"),
|
||||
'res_id': self.id,
|
||||
'views': [(self.env.ref('project.edit_project').id, 'form')],
|
||||
'view_mode': 'form',
|
||||
'context': {'form_view_initial_mode': 'readonly'}
|
||||
}
|
||||
|
||||
# ---------------------------------------------
|
||||
# PROJECT UPDATES
|
||||
# ---------------------------------------------
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
<field name="name">account.analytic.account.form.inherit</field>
|
||||
<field name="model">account.analytic.account</field>
|
||||
<field name="inherit_id" ref="analytic.view_account_analytic_account_form"/>
|
||||
<field eval="18" name="priority"/>
|
||||
<field eval="40" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="button_box" position="inside">
|
||||
<xpath expr="//button[@name='%(analytic.account_analytic_line_action)d']" position="before">
|
||||
<button class="oe_stat_button" type="object" name="action_view_projects"
|
||||
icon="fa-puzzle-piece" attrs="{'invisible': [('project_count', '=', 0)]}">
|
||||
<field string="Projects" name="project_count" widget="statinfo"/>
|
||||
</button>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -272,6 +272,15 @@
|
||||
</header>
|
||||
<sheet string="Project">
|
||||
<div class="oe_button_box" name="button_box" groups="base.group_user">
|
||||
<field name="currency_id" invisible="1"/>
|
||||
<button class="oe_stat_button" type="object" name="action_view_analytic_account_entries" icon="fa-usd" attrs="{'invisible': [('analytic_account_id', '=', False)]}" groups="analytic.group_analytic_accounting">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<span class="o_stat_text">Gross Margin</span>
|
||||
<span class="o_stat_value">
|
||||
<field name="analytic_account_balance" widget='monetary'/>
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<button class="oe_stat_button" type="action"
|
||||
name="%(act_project_project_2_project_task_all)d" icon="fa-tasks">
|
||||
<field string="Tasks In Progress" name="task_count" widget="statinfo" options="{'label_field': 'label_tasks'}"/>
|
||||
@@ -335,18 +344,32 @@
|
||||
<group>
|
||||
<field name="label_tasks" string="Name of the tasks"/>
|
||||
<field name="partner_id" widget="res_partner_many2one"/>
|
||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}"/>
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="user_id" string="Project Manager" widget="many2one_avatar_user" attrs="{'readonly':[('active','=',False)]}" domain="[('share', '=', False)]"/>
|
||||
<label for="date_start" string="Dates"/>
|
||||
<div name="dates" class="o_row">
|
||||
<field name="date_start" widget="daterange" options='{"related_end_date": "date"}'/>
|
||||
<i class="fa fa-long-arrow-right mx-2 oe_edit_only" aria-label="Arrow icon" title="Arrow"/>
|
||||
<i class="fa fa-long-arrow-right mx-2 oe_read_only" aria-label="Arrow icon" title="Arrow" attrs="{'invisible': [('date_start', '=', False), ('date', '=', False)]}"/>
|
||||
<field name="date" widget="daterange" options='{"related_start_date": "date_start"}'/>
|
||||
</div>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page name="description" string="Description">
|
||||
<field name="description"/>
|
||||
</page>
|
||||
<page name="settings" string="Settings">
|
||||
<group>
|
||||
<group>
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="user_id" string="Project Manager" widget="many2one_avatar_user" attrs="{'readonly':[('active','=',False)]}" domain="[('share', '=', False)]"/>
|
||||
<field name="date" string="Deadline"/>
|
||||
<field name="analytic_account_id" domain="['|', ('company_id', '=', company_id), ('company_id', '=', False)]" context="{'default_partner_id': partner_id}" groups="analytic.group_analytic_accounting"/>
|
||||
<field name="privacy_visibility" widget="radio"/>
|
||||
</group>
|
||||
<group>
|
||||
<div name="alias_def" colspan="2" attrs="{'invisible': [('alias_domain', '=', False)]}">
|
||||
<!-- Always display the whole alias in edit mode. It depends in read only -->
|
||||
<field name="alias_enabled" invisible="1"/>
|
||||
@@ -363,11 +386,6 @@
|
||||
<field name="alias_contact" class="oe_inline" string="Accept Emails From"
|
||||
attrs="{'invisible': ['|', ('alias_name', '=', ''), ('alias_name', '=', False)]}"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="analytic_account_id" domain="['|', ('company_id', '=', company_id), ('company_id', '=', False)]" context="{'default_partner_id': partner_id}" groups="analytic.group_analytic_accounting"/>
|
||||
<field name="privacy_visibility" widget="radio"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<group name="extra_settings">
|
||||
</group>
|
||||
</group>
|
||||
@@ -434,6 +452,7 @@
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" options="{'post_refresh':True}" help="Follow this project to automatically track the events associated to tasks and issues of this project." groups="base.group_user"/>
|
||||
<field name="activity_ids"/>
|
||||
<field name="message_ids"/>
|
||||
</div>
|
||||
</form>
|
||||
@@ -482,7 +501,8 @@
|
||||
<field name="privacy_visibility" optional="hide"/>
|
||||
<field name="company_id" optional="show" groups="base.group_multi_company" options="{'no_create': True, 'no_create_edit': True}"/>
|
||||
<field name="analytic_account_id" optional="hide" groups="analytic.group_analytic_accounting"/>
|
||||
<field name="date" optional="hide" string="Deadline" widget="remaining_days"/>
|
||||
<field name="date_start" string="Start Date" widget="daterange" options="{'related_end_date': 'date'}"/>
|
||||
<field name="date" string="End Date" widget="daterange" options="{'related_start_date': 'date_start'}"/>
|
||||
<field name="user_id" optional="show" string="Project Manager" widget="many2one_avatar_user" options="{'no_open':True, 'no_create': True, 'no_create_edit': True}"/>
|
||||
<field name="last_update_color" invisible="1"/>
|
||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}" optional="hide"/>
|
||||
@@ -605,8 +625,10 @@
|
||||
<span class="o_text_overflow text-muted" t-if="record.partner_id.value">
|
||||
<span class="fa fa-user mr-2" aria-label="Partner" title="Partner"></span><t t-esc="record.partner_id.value"/>
|
||||
</span>
|
||||
<div t-if="record.date.raw_value" class="text-muted">
|
||||
<span class="fa fa-clock-o mr-2" aria-label="Remaining days" title="Remaining days"></span><field name="date" widget="remaining_days"/>
|
||||
<div t-if="record.date.raw_value or record.date_start.raw_value" class="text-muted o_row">
|
||||
<span class="fa fa-clock-o mr-2" title="Dates"></span><field name="date_start"/>
|
||||
<i t-if="record.date.raw_value and record.date_start.raw_value" class="fa fa-long-arrow-right mx-2 oe_read_only" aria-label="Arrow icon" title="Arrow"/>
|
||||
<field name="date"/>
|
||||
</div>
|
||||
<div t-if="record.alias_name.value and record.alias_domain.value" class="text-muted">
|
||||
<span class="fa fa-envelope-o mr-2" aria-label="Domain Alias" title="Domain Alias"></span><t t-esc="record.alias_id.value"/>
|
||||
@@ -653,7 +675,7 @@
|
||||
</div>
|
||||
<div role="menuitem" class="col-4">
|
||||
<a t-if="record.privacy_visibility.raw_value == 'portal'" class="dropdown-item" role="menuitem" name="%(project.project_share_wizard_action)d" type="action">Share</a>
|
||||
<a class="dropdown-item" role="menuitem" type="edit">Edit</a>
|
||||
<a class="dropdown-item" role="menuitem" type="object" name="action_view_kanban_project">See More</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -674,9 +696,11 @@
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<field name="activity_ids" widget="kanban_activity"/>
|
||||
</div>
|
||||
<div class="oe_kanban_bottom_right">
|
||||
<span t-att-class="'o_status_bubble mx-0 o_color_bubble_' + record.last_update_color.value" t-att-title="record.last_update_status.value"></span>
|
||||
<field name="user_id" widget="many2one_avatar_user"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
'report/purchase_order_templates.xml',
|
||||
'report/purchase_quotation_templates.xml',
|
||||
'views/product_packaging_views.xml',
|
||||
'views/analytic_account_views.xml',
|
||||
],
|
||||
'demo': [
|
||||
'data/purchase_demo.xml',
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import account_invoice
|
||||
from . import analytic_account
|
||||
from . import purchase
|
||||
from . import product
|
||||
from . import res_company
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class AccountAnalyticAccount(models.Model):
|
||||
_inherit = 'account.analytic.account'
|
||||
|
||||
purchase_order_count = fields.Integer("Purchase Order Count", compute='_compute_purchase_order_count')
|
||||
|
||||
@api.depends('line_ids')
|
||||
def _compute_purchase_order_count(self):
|
||||
for account in self:
|
||||
account.purchase_order_count = len(account.line_ids.move_id.purchase_order_id)
|
||||
|
||||
def action_view_purchase_orders(self):
|
||||
self.ensure_one()
|
||||
purchase_orders = self.line_ids.move_id.purchase_order_id
|
||||
result = {
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "purchase.order",
|
||||
"domain": [['id', 'in', purchase_orders.ids]],
|
||||
"name": "Purchase Orders",
|
||||
'view_mode': 'tree,form',
|
||||
}
|
||||
if len(purchase_orders) == 1:
|
||||
result['view_mode'] = 'form'
|
||||
result['res_id'] = purchase_orders.id
|
||||
return result
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="account_analytic_account_view_form_purchase" model="ir.ui.view">
|
||||
<field name="name">account.analytic.account.form.purchase</field>
|
||||
<field name="model">account.analytic.account</field>
|
||||
<field name="inherit_id" ref="analytic.view_account_analytic_account_form"/>
|
||||
<field eval="10" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<div name="button_box" position="inside">
|
||||
<button class="oe_stat_button" type="object" name="action_view_purchase_orders"
|
||||
icon="fa-shopping-cart" attrs="{'invisible': [('purchase_order_count', '=', 0)]}">
|
||||
<field string="Purchase Orders" name="purchase_order_count" widget="statinfo"/>
|
||||
</button>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user