Add reporting
issue10397 review342321002
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
* Add reporting
|
||||
|
||||
Version 6.0.0 - 2021-05-03
|
||||
* Bug fixes (see mercurial logs for details)
|
||||
* Use the invoice date or payment date for commission date
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
from trytond.pool import Pool
|
||||
from . import account
|
||||
from . import commission
|
||||
from . import commission_reporting
|
||||
from . import invoice
|
||||
from . import sale
|
||||
from . import product
|
||||
@@ -19,6 +20,9 @@ def register():
|
||||
commission.AgentSelection,
|
||||
commission.Commission,
|
||||
commission.CreateInvoiceAsk,
|
||||
commission_reporting.Agent,
|
||||
commission_reporting.AgentTimeseries,
|
||||
commission_reporting.Context,
|
||||
invoice.Invoice,
|
||||
invoice.InvoiceLine,
|
||||
invoice.CreditInvoiceStart,
|
||||
|
||||
@@ -344,11 +344,17 @@ class Commission(ModelSQL, ModelView):
|
||||
product = fields.Many2One('product.product', 'Product', required=True,
|
||||
states=_readonly_states, depends=_readonly_depends,
|
||||
help="The product that is used on the invoice line.")
|
||||
base_amount = fields.Numeric(
|
||||
"Base Amount", digits=(16, Eval('currency_digits', 2)),
|
||||
states=_readonly_states,
|
||||
depends=_readonly_depends + ['currency_digits'])
|
||||
amount = fields.Numeric('Amount', required=True, digits=price_digits,
|
||||
domain=[('amount', '!=', 0)],
|
||||
states=_readonly_states, depends=_readonly_depends)
|
||||
currency = fields.Function(fields.Many2One('currency.currency',
|
||||
'Currency'), 'on_change_with_currency')
|
||||
currency_digits = fields.Function(fields.Integer(
|
||||
"Currency Digits"), 'on_change_with_currency_digits')
|
||||
type_ = fields.Function(fields.Selection([
|
||||
('in', 'Incoming'),
|
||||
('out', 'Outgoing'),
|
||||
@@ -394,6 +400,11 @@ class Commission(ModelSQL, ModelView):
|
||||
if self.agent:
|
||||
return self.agent.currency.id
|
||||
|
||||
@fields.depends('agent')
|
||||
def on_change_with_currency_digits(self, name=None):
|
||||
if self.agent:
|
||||
return self.agent.currency.digits
|
||||
|
||||
@fields.depends('agent')
|
||||
def on_change_with_type_(self, name=None):
|
||||
if self.agent:
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from itertools import tee, zip_longest
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
try:
|
||||
import pygal
|
||||
except ImportError:
|
||||
pygal = None
|
||||
from sql import Literal, Null
|
||||
from sql.aggregate import Min, Sum, Count
|
||||
from sql.functions import CurrentTimestamp, DateTrunc
|
||||
|
||||
from trytond.model import ModelSQL, ModelView, fields
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval, If
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
from trytond.modules.product import price_digits
|
||||
|
||||
|
||||
def pairwise(iterable):
|
||||
a, b = tee(iterable)
|
||||
next(b)
|
||||
return zip_longest(a, b)
|
||||
|
||||
|
||||
class Agent(ModelView, ModelSQL):
|
||||
"Commission Reporting per Agent"
|
||||
__name__ = 'commission.reporting.agent'
|
||||
|
||||
agent = fields.Many2One('commission.agent', 'Agent')
|
||||
number = fields.Integer("Number")
|
||||
|
||||
base_amount = fields.Numeric(
|
||||
"Base Amount", digits=(16, Eval('currency_digits', 2)),
|
||||
depends=['currency_digits'])
|
||||
base_amount_trend = fields.Function(
|
||||
fields.Char("Base Amount Trend"), 'get_trend')
|
||||
amount = fields.Numeric("Amount", digits=price_digits)
|
||||
|
||||
time_series = fields.One2Many(
|
||||
'commission.reporting.agent.time_series', 'agent', "Time Series")
|
||||
|
||||
currency = fields.Function(fields.Many2One(
|
||||
'currency.currency', "Currency"), 'get_currency')
|
||||
currency_digits = fields.Function(fields.Integer(
|
||||
"Currency Digits"), 'get_currency_digits')
|
||||
|
||||
@classmethod
|
||||
def table_query(cls):
|
||||
from_item, tables, withs = cls._joins()
|
||||
return from_item.select(
|
||||
*cls._columns(tables, withs),
|
||||
where=cls._where(tables, withs),
|
||||
group_by=cls._group_by(tables, withs),
|
||||
with_=withs.values())
|
||||
|
||||
@classmethod
|
||||
def _joins(cls):
|
||||
pool = Pool()
|
||||
Commission = pool.get('commission')
|
||||
Agent = pool.get('commission.agent')
|
||||
|
||||
tables = {}
|
||||
tables['commission'] = commission = Commission.__table__()
|
||||
tables['commission.agent'] = agent = Agent.__table__()
|
||||
withs = {}
|
||||
|
||||
from_item = (commission
|
||||
.join(agent, condition=commission.agent == agent.id))
|
||||
return from_item, tables, withs
|
||||
|
||||
@classmethod
|
||||
def _columns(cls, tables, withs):
|
||||
commission = tables['commission']
|
||||
return [
|
||||
cls._column_id(tables, withs).as_('id'),
|
||||
Literal(0).as_('create_uid'),
|
||||
CurrentTimestamp().as_('create_date'),
|
||||
cls.write_uid.sql_cast(Literal(Null)).as_('write_uid'),
|
||||
cls.write_date.sql_cast(Literal(Null)).as_('write_date'),
|
||||
commission.agent.as_('agent'),
|
||||
Count(commission.id, distinct=True).as_('number'),
|
||||
Sum(commission.base_amount).as_('base_amount'),
|
||||
Sum(commission.amount).as_('amount'),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def _column_id(cls, tables, withs):
|
||||
commission = tables['commission']
|
||||
return commission.agent
|
||||
|
||||
@classmethod
|
||||
def _group_by(cls, tables, withs):
|
||||
commission = tables['commission']
|
||||
return [commission.agent]
|
||||
|
||||
@classmethod
|
||||
def _where(cls, tables, withs):
|
||||
context = Transaction().context
|
||||
commission = tables['commission']
|
||||
agent = tables['commission.agent']
|
||||
where = agent.type_ == cls._get_agent_type(context.get('type', 'out'))
|
||||
from_date = context.get('from_date')
|
||||
if from_date:
|
||||
where &= commission.date >= from_date
|
||||
to_date = context.get('to_date')
|
||||
if to_date:
|
||||
where &= commission.date <= to_date
|
||||
if context.get('invoiced'):
|
||||
where &= commission.invoice_line != Null
|
||||
return where
|
||||
|
||||
@classmethod
|
||||
def _get_agent_type(cls, type):
|
||||
return {
|
||||
'out': 'agent',
|
||||
'in': 'principal',
|
||||
}.get(type)
|
||||
|
||||
@property
|
||||
def time_series_all(self):
|
||||
delta = self._period_delta()
|
||||
for ts, next_ts in pairwise(self.time_series or []):
|
||||
yield ts
|
||||
if delta and next_ts:
|
||||
date = ts.date + delta
|
||||
while date < next_ts.date:
|
||||
yield None
|
||||
date += delta
|
||||
|
||||
@classmethod
|
||||
def _period_delta(cls):
|
||||
context = Transaction().context
|
||||
return {
|
||||
'year': relativedelta(years=1),
|
||||
'month': relativedelta(months=1),
|
||||
'day': relativedelta(days=1),
|
||||
}.get(context.get('period'))
|
||||
|
||||
def get_trend(self, name):
|
||||
name = name[:-len('_trend')]
|
||||
if pygal:
|
||||
chart = pygal.Line()
|
||||
chart.add('', [
|
||||
getattr(ts, name, 0) or 0
|
||||
for ts in self.time_series_all])
|
||||
return chart.render_sparktext()
|
||||
|
||||
def get_currency(self, name):
|
||||
return self.agent.currency.id
|
||||
|
||||
def get_currency_digits(self, name):
|
||||
return self.agent.currency.digits
|
||||
|
||||
|
||||
class AgentTimeseries(Agent):
|
||||
"Commission Reporting per Agent"
|
||||
__name__ = 'commission.reporting.agent.time_series'
|
||||
|
||||
date = fields.Date("Date")
|
||||
time_series = None
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls._order = [('date', 'ASC')]
|
||||
|
||||
@classmethod
|
||||
def _columns(cls, tables, withs):
|
||||
return super()._columns(tables, withs) + [
|
||||
cls._column_date(tables, withs).as_('date')]
|
||||
|
||||
@classmethod
|
||||
def _column_id(cls, tables, withs):
|
||||
commission = tables['commission']
|
||||
return Min(commission.id)
|
||||
|
||||
@classmethod
|
||||
def _column_date(cls, tables, withs):
|
||||
context = Transaction().context
|
||||
commission = tables['commission']
|
||||
date = DateTrunc(context.get('period'), commission.date)
|
||||
date = cls.date.sql_cast(date)
|
||||
return date
|
||||
|
||||
@classmethod
|
||||
def _group_by(cls, tables, withs):
|
||||
return super()._group_by(tables, withs) + [
|
||||
cls._column_date(tables, withs)]
|
||||
|
||||
|
||||
class Context(ModelView):
|
||||
"Commission Reporting Context"
|
||||
__name__ = 'commission.reporting.context'
|
||||
|
||||
type = fields.Selection([
|
||||
('in', "Incoming"),
|
||||
('out', "Outgoing"),
|
||||
], "Type", required=True)
|
||||
from_date = fields.Date("From Date",
|
||||
domain=[
|
||||
If(Eval('to_date') & Eval('from_date'),
|
||||
('from_date', '<=', Eval('to_date')),
|
||||
()),
|
||||
],
|
||||
depends=['to_date'])
|
||||
to_date = fields.Date("To Date",
|
||||
domain=[
|
||||
If(Eval('from_date') & Eval('to_date'),
|
||||
('to_date', '>=', Eval('from_date')),
|
||||
()),
|
||||
],
|
||||
depends=['from_date'])
|
||||
period = fields.Selection([
|
||||
('year', "Year"),
|
||||
('month', "Month"),
|
||||
('day', "Day"),
|
||||
], "Period", required=True)
|
||||
invoiced = fields.Boolean(
|
||||
"Invoiced",
|
||||
help="Only included invoiced commissions.")
|
||||
|
||||
@classmethod
|
||||
def default_type(cls):
|
||||
return Transaction().context.get('type', 'out')
|
||||
|
||||
@classmethod
|
||||
def default_from_date(cls):
|
||||
pool = Pool()
|
||||
Date = pool.get('ir.date')
|
||||
context = Transaction().context
|
||||
if 'from_date' in context:
|
||||
return context['from_date']
|
||||
return Date.today() - relativedelta(years=1)
|
||||
|
||||
@classmethod
|
||||
def default_to_date(cls):
|
||||
pool = Pool()
|
||||
Date = pool.get('ir.date')
|
||||
context = Transaction().context
|
||||
if 'to_date' in context:
|
||||
return context['to_date']
|
||||
return Date.today()
|
||||
|
||||
@classmethod
|
||||
def default_period(cls):
|
||||
return Transaction().context.get('period', 'month')
|
||||
@@ -0,0 +1,176 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<menuitem
|
||||
name="Reporting"
|
||||
parent="menu_commission"
|
||||
sequence="100"
|
||||
id="menu_reporting"/>
|
||||
|
||||
<menuitem
|
||||
name="Commissions"
|
||||
parent="menu_reporting"
|
||||
sequence="10"
|
||||
id="menu_reporting_commission"
|
||||
icon="tryton-graph"/>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_context_view_form">
|
||||
<field name="model">commission.reporting.context</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">reporting_context_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_agent_view_list">
|
||||
<field name="model">commission.reporting.agent</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">reporting_agent_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_agent_view_graph_amount">
|
||||
<field name="model">commission.reporting.agent</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_agent_graph_amount</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_agent_view_graph_number">
|
||||
<field name="model">commission.reporting.agent</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_agent_graph_number</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_agent">
|
||||
<field name="name">Commissions per Agent</field>
|
||||
<field name="res_model">commission.reporting.agent</field>
|
||||
<field name="context_model">commission.reporting.context</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_agent_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_agent_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_agent"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_agent_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="reporting_agent_view_graph_amount"/>
|
||||
<field name="act_window" ref="act_reporting_agent"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_agent_view3">
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="view" ref="reporting_agent_view_graph_number"/>
|
||||
<field name="act_window" ref="act_reporting_agent"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_agent_keyword1">
|
||||
<field name="keyword">tree_open</field>
|
||||
<field name="model" eval="'ir.ui.menu,%s' % ref('menu_reporting_commission')"/>
|
||||
<field name="action" ref="act_reporting_agent"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_reporting_agent_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model"
|
||||
search="[('model', '=', 'commission.reporting.agent')]"/>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_reporting_agent_companies">
|
||||
<field name="domain"
|
||||
eval="[('agent.company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_agent_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_reporting_agent">
|
||||
<field name="model" search="[('model', '=', 'commission.reporting.agent')]"/>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_reporting_agent_commission">
|
||||
<field name="model" search="[('model', '=', 'commission.reporting.agent')]"/>
|
||||
<field name="group" ref="group_commission"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_agent_time_series_view_list">
|
||||
<field name="model">commission.reporting.agent.time_series</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">reporting_agent_time_series_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_agent_time_series_view_graph_amount">
|
||||
<field name="model">commission.reporting.agent.time_series</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_agent_time_series_graph_amount</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="reporting_agent_time_series_view_graph_number">
|
||||
<field name="model">commission.reporting.agent.time_series</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="name">reporting_agent_time_series_graph_number</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_reporting_agent_time_series">
|
||||
<field name="name">Commissions per Agent</field>
|
||||
<field name="res_model">commission.reporting.agent.time_series</field>
|
||||
<field name="context_model">commission.reporting.context</field>
|
||||
<field
|
||||
name="domain"
|
||||
eval="[('agent', '=', Eval('active_id', -1))]"
|
||||
pyson="1"/>
|
||||
<field name="order" eval="[('date', 'DESC')]" pyson="1"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_agent_time_series_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="reporting_agent_time_series_view_list"/>
|
||||
<field name="act_window" ref="act_reporting_agent_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_agent_time_series_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="reporting_agent_time_series_view_graph_amount"/>
|
||||
<field name="act_window" ref="act_reporting_agent_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_reporting_agent_time_series_view3">
|
||||
<field name="sequence" eval="30"/>
|
||||
<field name="view" ref="reporting_agent_time_series_view_graph_number"/>
|
||||
<field name="act_window" ref="act_reporting_agent_time_series"/>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_reporting_agent_time_series_keyword1">
|
||||
<field name="keyword">tree_open</field>
|
||||
<field name="model">commission.reporting.agent,-1</field>
|
||||
<field name="action" ref="act_reporting_agent_time_series"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.rule.group" id="rule_group_reporting_agent_time_series_companies">
|
||||
<field name="name">User in companies</field>
|
||||
<field name="model"
|
||||
search="[('model', '=', 'commission.reporting.agent.time_series')]"/>
|
||||
<field name="global_p" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.rule" id="rule_reporting_agent_time_series_companies">
|
||||
<field name="domain"
|
||||
eval="[('agent.company', 'in', Eval('companies', []))]"
|
||||
pyson="1"/>
|
||||
<field name="rule_group" ref="rule_group_reporting_agent_time_series_companies"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_reporting_agent_time_series">
|
||||
<field name="model" search="[('model', '=', 'commission.reporting.agent.time_series')]"/>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_reporting_agent_time_series_commission">
|
||||
<field name="model" search="[('model', '=', 'commission.reporting.agent.time_series')]"/>
|
||||
<field name="group" ref="group_commission"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
+3
-2
@@ -162,9 +162,9 @@ class InvoiceLine(metaclass=PoolMeta):
|
||||
if not plan:
|
||||
continue
|
||||
with Transaction().set_context(date=self.invoice.currency_date):
|
||||
amount = Currency.compute(self.invoice.currency,
|
||||
base_amount = Currency.compute(self.invoice.currency,
|
||||
self.amount, agent.currency, round=False)
|
||||
amount = self._get_commission_amount(amount, plan)
|
||||
amount = self._get_commission_amount(base_amount, plan)
|
||||
if amount:
|
||||
amount = round_price(amount)
|
||||
if not amount:
|
||||
@@ -179,6 +179,7 @@ class InvoiceLine(metaclass=PoolMeta):
|
||||
commission.date = self.invoice.reconciled or today
|
||||
commission.agent = agent
|
||||
commission.product = plan.commission_product
|
||||
commission.base_amount = base_amount
|
||||
commission.amount = amount
|
||||
commissions.append(commission)
|
||||
return commissions
|
||||
|
||||
@@ -57,7 +57,7 @@ else:
|
||||
if local_version:
|
||||
version += '+' + '.'.join(local_version)
|
||||
|
||||
requires = ['simpleeval', 'python-sql']
|
||||
requires = ['simpleeval', 'python-sql', 'python-dateutil']
|
||||
for dep in info.get('depends', []):
|
||||
if not re.match(r'(ir|res)(\W|$)', dep):
|
||||
requires.append(get_require_version('trytond_%s' % dep))
|
||||
@@ -139,6 +139,9 @@ setup(name=name,
|
||||
license='GPL-3',
|
||||
python_requires='>=3.6',
|
||||
install_requires=requires,
|
||||
extras_require={
|
||||
'sparklines': ['pygal'],
|
||||
},
|
||||
dependency_links=dependency_links,
|
||||
zip_safe=False,
|
||||
entry_points="""
|
||||
|
||||
@@ -22,6 +22,9 @@ Activate modules::
|
||||
|
||||
>>> config = activate_modules('commission')
|
||||
|
||||
>>> ReportingAgent = Model.get('commission.reporting.agent')
|
||||
>>> ReportingAgentTimeseries = Model.get('commission.reporting.agent.time_series')
|
||||
|
||||
Create company::
|
||||
|
||||
>>> _ = create_company()
|
||||
@@ -151,6 +154,8 @@ Post invoice::
|
||||
>>> line, = invoice.lines
|
||||
>>> len(line.commissions)
|
||||
2
|
||||
>>> [c.base_amount for c in line.commissions]
|
||||
[Decimal('100.00'), Decimal('100.00')]
|
||||
>>> [c.amount for c in line.commissions]
|
||||
[Decimal('10.0000'), Decimal('10.0000')]
|
||||
>>> [c.invoice_state for c in line.commissions]
|
||||
@@ -222,3 +227,25 @@ Credit invoice::
|
||||
>>> credit_note, = credit.actions[0]
|
||||
>>> credit_note.agent == agent
|
||||
True
|
||||
|
||||
Check commission reporting per agent::
|
||||
|
||||
>>> with config.set_context(type='out'):
|
||||
... reporting_agent, = ReportingAgent.find([])
|
||||
... reporting_agent_timeseries, = ReportingAgentTimeseries.find([])
|
||||
|
||||
>>> reporting_agent.base_amount == Decimal('100.00')
|
||||
True
|
||||
>>> reporting_agent.amount == Decimal('10.0000')
|
||||
True
|
||||
>>> reporting_agent.number
|
||||
1
|
||||
|
||||
>>> reporting_agent_timeseries.date == tomorrow
|
||||
True
|
||||
>>> reporting_agent_timeseries.base_amount == Decimal('100.00')
|
||||
True
|
||||
>>> reporting_agent_timeseries.amount == Decimal('10.00')
|
||||
True
|
||||
>>> reporting_agent_timeseries.number
|
||||
1
|
||||
|
||||
@@ -12,6 +12,7 @@ extras_depend:
|
||||
sale
|
||||
xml:
|
||||
commission.xml
|
||||
commission_reporting.xml
|
||||
invoice.xml
|
||||
sale.xml
|
||||
account.xml
|
||||
|
||||
@@ -10,10 +10,12 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="type_"/>
|
||||
<label name="product"/>
|
||||
<field name="product"/>
|
||||
|
||||
<label name="base_amount"/>
|
||||
<field name="base_amount" symbol="currency"/>
|
||||
<label name="amount"/>
|
||||
<field name="amount"/>
|
||||
<label name="currency"/>
|
||||
<field name="currency"/>
|
||||
<field name="amount" symbol="currency"/>
|
||||
|
||||
<label name="origin"/>
|
||||
<field name="origin"/>
|
||||
<newline/>
|
||||
|
||||
@@ -5,8 +5,8 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="type_"/>
|
||||
<field name="agent" expand="1"/>
|
||||
<field name="date"/>
|
||||
<field name="amount"/>
|
||||
<field name="currency"/>
|
||||
<field name="base_amount" symbol="currency"/>
|
||||
<field name="amount" symbol="currency"/>
|
||||
<field name="invoice_state"/>
|
||||
<button name="invoice" tree_invisible="1"/>
|
||||
</tree>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<graph>
|
||||
<x>
|
||||
<field name="agent"/>
|
||||
</x>
|
||||
<y>
|
||||
<field name="base_amount"/>
|
||||
<field name="amount"/>
|
||||
</y>
|
||||
</graph>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<graph>
|
||||
<x>
|
||||
<field name="agent"/>
|
||||
</x>
|
||||
<y>
|
||||
<field name="number"/>
|
||||
</y>
|
||||
</graph>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tree keyword_open="1">
|
||||
<field name="agent" expand="1"/>
|
||||
<field name="number"/>
|
||||
<field name="base_amount" symbol="currency"/>
|
||||
<field name="base_amount_trend" expand="1"/>
|
||||
<field name="amount" symbol="currency"/>
|
||||
</tree>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<graph>
|
||||
<x>
|
||||
<field name="date"/>
|
||||
</x>
|
||||
<y>
|
||||
<field name="base_amount"/>
|
||||
<field name="amount"/>
|
||||
</y>
|
||||
</graph>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<graph>
|
||||
<x>
|
||||
<field name="date"/>
|
||||
</x>
|
||||
<y>
|
||||
<field name="number"/>
|
||||
</y>
|
||||
</graph>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tree>
|
||||
<field name="date"/>
|
||||
<field name="number"/>
|
||||
<field name="base_amount" symbol="currency"/>
|
||||
<field name="amount" symbol="currency"/>
|
||||
</tree>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<form>
|
||||
<group id="dates" colspan="2" col="4">
|
||||
<label name="from_date"/>
|
||||
<field name="from_date"/>
|
||||
<label name="to_date"/>
|
||||
<field name="to_date"/>
|
||||
</group>
|
||||
<label name="period"/>
|
||||
<field name="period"/>
|
||||
|
||||
<label name="type"/>
|
||||
<field name="type"/>
|
||||
<label name="invoiced"/>
|
||||
<field name="invoiced"/>
|
||||
</form>
|
||||
Reference in New Issue
Block a user