Initial commit: Sale packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:49 +02:00
commit 14e3d26998
6469 changed files with 2479670 additions and 0 deletions

View file

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import account_invoice_report
from . import sale_report

View file

@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class AccountInvoiceReport(models.Model):
_inherit = 'account.invoice.report'
team_id = fields.Many2one(comodel_name='crm.team', string="Sales Team")
def _select(self):
return super()._select() + ", move.team_id as team_id"

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_account_invoice_report_search_inherit" model="ir.ui.view">
<field name="name">account.invoice.report.search.inherit</field>
<field name="model">account.invoice.report</field>
<field name="inherit_id" ref="account.view_account_invoice_report_search"/>
<field name="arch" type="xml">
<filter name="user" position="after">
<filter string="Sales Team" name="sales_channel" context="{'group_by':'team_id'}"/>
</filter>
<field name="invoice_user_id" position="after">
<field name="team_id"/>
</field>
</field>
</record>
<record id="account_invoice_report_view_tree" model="ir.ui.view">
<field name="name">account.invoice.report.view.tree.inherit.sale</field>
<field name="model">account.invoice.report</field>
<field name="inherit_id" ref="account.account_invoice_report_view_tree"/>
<field name="arch" type="xml">
<field name="invoice_user_id" position="after">
<field name="team_id" optional="hide"/>
</field>
</field>
</record>
<record id="action_account_invoice_report_salesteam" model="ir.actions.act_window">
<field name="name">Invoices Analysis</field>
<field name="res_model">account.invoice.report</field>
<field name="view_mode">graph</field>
<field name="domain">[('state', 'not in', ['draft', 'cancel'])]</field>
<field name="context">{'search_default_month':1, 'search_default_team_id': [active_id]}</field>
<field name="help">From this report, you can have an overview of the amount invoiced to your customer. The search tool can also be used to personalise your Invoices reports and so, match this analysis to your needs.</field>
</record>
</odoo>

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="action_report_saleorder" model="ir.actions.report">
<field name="name">Quotation / Order</field>
<field name="model">sale.order</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">sale.report_saleorder</field>
<field name="report_file">sale.report_saleorder</field>
<field name="print_report_name">(object.state in ('draft', 'sent') and 'Quotation - %s' % (object.name)) or 'Order - %s' % (object.name)</field>
<field name="binding_model_id" ref="model_sale_order"/>
<field name="binding_type">report</field>
</record>
<record id="action_report_pro_forma_invoice" model="ir.actions.report">
<field name="name">PRO-FORMA Invoice</field>
<field name="model">sale.order</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">sale.report_saleorder_pro_forma</field>
<field name="report_file">sale.report_saleorder_pro_forma</field>
<field name="print_report_name">'PRO-FORMA - %s' % (object.name)</field>
<field name="binding_model_id" ref="model_sale_order"/>
<field name="binding_type">report</field>
<field name="groups_id" eval="[(4, ref('sale.group_proforma_sales'))]"/>
</record>
</odoo>

View file

@ -0,0 +1,204 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="report_saleorder_document">
<t t-call="web.external_layout">
<t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)" />
<t t-set="forced_vat" t-value="doc.fiscal_position_id.foreign_vat"/> <!-- So that it appears in the footer of the report instead of the company VAT if it's set -->
<t t-set="address">
<div t-field="doc.partner_id"
t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}' />
<p t-if="doc.partner_id.vat"><t t-out="doc.company_id.account_fiscal_country_id.vat_label or 'Tax ID'"/>: <span t-field="doc.partner_id.vat"/></p>
</t>
<t t-if="doc.partner_shipping_id == doc.partner_invoice_id
and doc.partner_invoice_id != doc.partner_id
or doc.partner_shipping_id != doc.partner_invoice_id">
<t t-set="information_block">
<strong>
<t t-if="doc.partner_shipping_id == doc.partner_invoice_id">
Invoicing and Shipping Address:
</t>
<t t-else="">
Invoicing Address:
</t>
</strong>
<div t-field="doc.partner_invoice_id"
t-options='{"widget": "contact", "fields": ["address", "name", "phone"], "no_marker": True, "phone_icons": True}'/>
<t t-if="doc.partner_shipping_id != doc.partner_invoice_id">
<strong>Shipping Address:</strong>
<div t-field="doc.partner_shipping_id"
t-options='{"widget": "contact", "fields": ["address", "name", "phone"], "no_marker": True, "phone_icons": True}'/>
</t>
</t>
</t>
<div class="page">
<div class="oe_structure"/>
<h2 class="mt-4">
<span t-if="env.context.get('proforma', False) or is_pro_forma">Pro-Forma Invoice # </span>
<span t-elif="doc.state in ['draft','sent']">Quotation # </span>
<span t-else="">Order # </span>
<span t-field="doc.name"/>
</h2>
<div class="row mt-4 mb-4" id="informations">
<div t-if="doc.client_order_ref" class="col-auto col-3 mw-100 mb-2" name="informations_reference">
<strong>Your Reference:</strong>
<p class="m-0" t-field="doc.client_order_ref"/>
</div>
<div t-if="doc.date_order" class="col-auto col-3 mw-100 mb-2" name="informations_date">
<strong t-if="doc.state in ['draft', 'sent']">Quotation Date:</strong>
<strong t-else="">Order Date:</strong>
<p class="m-0" t-field="doc.date_order" t-options='{"widget": "date"}'/>
</div>
<div t-if="doc.validity_date and doc.state in ['draft', 'sent']"
class="col-auto col-3 mw-100 mb-2"
name="expiration_date">
<strong>Expiration:</strong>
<p class="m-0" t-field="doc.validity_date"/>
</div>
<div t-if="doc.user_id.name" class="col-auto col-3 mw-100 mb-2">
<strong>Salesperson:</strong>
<p class="m-0" t-field="doc.user_id"/>
</div>
</div>
<!-- Is there a discount on at least one line? -->
<t t-set="lines_to_report" t-value="doc._get_order_lines_to_report()"/>
<t t-set="display_discount" t-value="any(l.discount for l in lines_to_report)"/>
<table class="table table-sm o_main_table table-borderless mt-4">
<!-- In case we want to repeat the header, remove "display: table-row-group" -->
<thead style="display: table-row-group">
<tr>
<th name="th_description" class="text-start">Description</th>
<th name="th_quantity" class="text-end">Quantity</th>
<th name="th_priceunit" class="text-end">Unit Price</th>
<th name="th_discount" t-if="display_discount" class="text-end">
<span>Disc.%</span>
</th>
<th name="th_taxes" class="text-end">Taxes</th>
<th name="th_subtotal" class="text-end">
<span groups="account.group_show_line_subtotals_tax_excluded">Amount</span>
<span groups="account.group_show_line_subtotals_tax_included">Total Price</span>
</th>
</tr>
</thead>
<tbody class="sale_tbody">
<t t-set="current_subtotal" t-value="0"/>
<t t-foreach="lines_to_report" t-as="line">
<t t-set="current_subtotal" t-value="current_subtotal + line.price_subtotal" groups="account.group_show_line_subtotals_tax_excluded"/>
<t t-set="current_subtotal" t-value="current_subtotal + line.price_total" groups="account.group_show_line_subtotals_tax_included"/>
<tr t-att-class="'bg-200 fw-bold o_line_section' if line.display_type == 'line_section' else 'fst-italic o_line_note' if line.display_type == 'line_note' else ''">
<t t-if="not line.display_type">
<td name="td_name"><span t-field="line.name"/></td>
<td name="td_quantity" class="text-end">
<span t-field="line.product_uom_qty"/>
<span t-field="line.product_uom"/>
</td>
<td name="td_priceunit" class="text-end">
<span t-field="line.price_unit"/>
</td>
<td t-if="display_discount" class="text-end">
<span t-field="line.discount"/>
</td>
<t t-set="taxes" t-value="', '.join([(tax.description or tax.name) for tax in line.tax_id])"/>
<td name="td_taxes" t-attf-class="text-end {{ 'text-nowrap' if len(taxes) &lt; 10 else '' }}">
<span t-out="taxes">Tax 15%</span>
</td>
<td t-if="not line.is_downpayment" name="td_subtotal" class="text-end o_price_total">
<span t-field="line.price_subtotal" groups="account.group_show_line_subtotals_tax_excluded"/>
<span t-field="line.price_total" groups="account.group_show_line_subtotals_tax_included"/>
</td>
</t>
<t t-elif="line.display_type == 'line_section'">
<td name="td_section_line" colspan="99">
<span t-field="line.name"/>
</td>
<t t-set="current_section" t-value="line"/>
<t t-set="current_subtotal" t-value="0"/>
</t>
<t t-elif="line.display_type == 'line_note'">
<td name="td_note_line" colspan="99">
<span t-field="line.name"/>
</td>
</t>
</tr>
<t t-if="current_section and (line_last or lines_to_report[line_index+1].display_type == 'line_section') and not line.is_downpayment">
<tr class="is-subtotal text-end">
<td name="td_section_subtotal" colspan="99">
<strong class="mr16">Subtotal</strong>
<span
t-out="current_subtotal"
t-options='{"widget": "monetary", "display_currency": doc.pricelist_id.currency_id}'
/>
</td>
</tr>
</t>
</t>
</tbody>
</table>
<div class="clearfix" name="so_total_summary">
<div id="total" class="row" name="total">
<div t-attf-class="#{'col-6' if report_type != 'html' else 'col-sm-7 col-md-6'} ms-auto">
<table class="table table-sm table-borderless">
<!-- Tax totals -->
<t t-set="tax_totals" t-value="doc.tax_totals"/>
<t t-call="account.document_tax_totals"/>
</table>
</div>
</div>
</div>
<div t-if="doc.signature" class="mt-4 ml64 mr4" name="signature">
<div class="offset-8">
<strong>Signature</strong>
</div>
<div class="offset-8">
<img t-att-src="image_data_uri(doc.signature)" style="max-height: 4cm; max-width: 8cm;"/>
</div>
<div class="offset-8 text-center">
<p t-field="doc.signed_by"/>
</div>
</div>
<div>
<p t-field="doc.note" name="order_note"/>
<p t-if="not is_html_empty(doc.payment_term_id.note)">
<span t-field="doc.payment_term_id.note"/>
</p>
<p t-if="doc.fiscal_position_id and not is_html_empty(doc.fiscal_position_id.sudo().note)"
id="fiscal_position_remark">
<strong>Fiscal Position Remark:</strong>
<span t-field="doc.fiscal_position_id.sudo().note"/>
</p>
</div>
</div>
</t>
</template>
<template id="report_saleorder">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="doc">
<t t-call="sale.report_saleorder_document" t-lang="doc.partner_id.lang"/>
</t>
</t>
</template>
<template id="report_saleorder_pro_forma">
<t t-call="web.html_container">
<t t-set="is_pro_forma" t-value="True"/>
<t t-set="docs" t-value="docs.with_context(proforma=True)"/>
<t t-foreach="docs" t-as="doc">
<t t-call="sale.report_saleorder_document" t-lang="doc.partner_id.lang"/>
</t>
</t>
</template>
</odoo>

View file

@ -0,0 +1,201 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class SaleReport(models.Model):
_name = "sale.report"
_description = "Sales Analysis Report"
_auto = False
_rec_name = 'date'
_order = 'date desc'
@api.model
def _get_done_states(self):
return ['sale', 'done']
name = fields.Char('Order Reference', readonly=True)
date = fields.Datetime('Order Date', readonly=True)
product_id = fields.Many2one('product.product', 'Product Variant', readonly=True)
product_uom = fields.Many2one('uom.uom', 'Unit of Measure', readonly=True)
product_uom_qty = fields.Float('Qty Ordered', readonly=True)
qty_to_deliver = fields.Float('Qty To Deliver', readonly=True)
qty_delivered = fields.Float('Qty Delivered', readonly=True)
qty_to_invoice = fields.Float('Qty To Invoice', readonly=True)
qty_invoiced = fields.Float('Qty Invoiced', readonly=True)
partner_id = fields.Many2one('res.partner', 'Customer', readonly=True)
company_id = fields.Many2one('res.company', 'Company', readonly=True)
user_id = fields.Many2one('res.users', 'Salesperson', readonly=True)
price_total = fields.Float('Total', readonly=True)
price_subtotal = fields.Float('Untaxed Total', readonly=True)
untaxed_amount_to_invoice = fields.Float('Untaxed Amount To Invoice', readonly=True)
untaxed_amount_invoiced = fields.Float('Untaxed Amount Invoiced', readonly=True)
product_tmpl_id = fields.Many2one('product.template', 'Product', readonly=True)
categ_id = fields.Many2one('product.category', 'Product Category', readonly=True)
nbr = fields.Integer('# of Lines', readonly=True)
pricelist_id = fields.Many2one('product.pricelist', 'Pricelist', readonly=True)
analytic_account_id = fields.Many2one('account.analytic.account', 'Analytic Account', readonly=True)
team_id = fields.Many2one('crm.team', 'Sales Team', readonly=True)
country_id = fields.Many2one('res.country', 'Customer Country', readonly=True)
industry_id = fields.Many2one('res.partner.industry', 'Customer Industry', readonly=True)
commercial_partner_id = fields.Many2one('res.partner', 'Customer Entity', readonly=True)
state = fields.Selection([
('draft', 'Draft Quotation'),
('sent', 'Quotation Sent'),
('sale', 'Sales Order'),
('done', 'Sales Done'),
('cancel', 'Cancelled'),
], string='Status', readonly=True)
weight = fields.Float('Gross Weight', readonly=True)
volume = fields.Float('Volume', readonly=True)
discount = fields.Float('Discount %', readonly=True, group_operator="avg")
discount_amount = fields.Float('Discount Amount', readonly=True)
campaign_id = fields.Many2one('utm.campaign', 'Campaign', readonly=True)
medium_id = fields.Many2one('utm.medium', 'Medium', readonly=True)
source_id = fields.Many2one('utm.source', 'Source', readonly=True)
order_id = fields.Many2one('sale.order', 'Order #', readonly=True)
def _with_sale(self):
return ""
def _select_sale(self):
select_ = f"""
MIN(l.id) AS id,
l.product_id AS product_id,
t.uom_id AS product_uom,
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.product_uom_qty / u.factor * u2.factor) ELSE 0 END AS product_uom_qty,
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.qty_delivered / u.factor * u2.factor) ELSE 0 END AS qty_delivered,
CASE WHEN l.product_id IS NOT NULL THEN SUM((l.product_uom_qty - l.qty_delivered) / u.factor * u2.factor) ELSE 0 END AS qty_to_deliver,
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.qty_invoiced / u.factor * u2.factor) ELSE 0 END AS qty_invoiced,
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.qty_to_invoice / u.factor * u2.factor) ELSE 0 END AS qty_to_invoice,
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.price_total
/ {self._case_value_or_one('s.currency_rate')}
* {self._case_value_or_one('currency_table.rate')}
) ELSE 0
END AS price_total,
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.price_subtotal
/ {self._case_value_or_one('s.currency_rate')}
* {self._case_value_or_one('currency_table.rate')}
) ELSE 0
END AS price_subtotal,
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.untaxed_amount_to_invoice
/ {self._case_value_or_one('s.currency_rate')}
* {self._case_value_or_one('currency_table.rate')}
) ELSE 0
END AS untaxed_amount_to_invoice,
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.untaxed_amount_invoiced
/ {self._case_value_or_one('s.currency_rate')}
* {self._case_value_or_one('currency_table.rate')}
) ELSE 0
END AS untaxed_amount_invoiced,
COUNT(*) AS nbr,
s.name AS name,
s.date_order AS date,
s.state AS state,
s.partner_id AS partner_id,
s.user_id AS user_id,
s.company_id AS company_id,
s.campaign_id AS campaign_id,
s.medium_id AS medium_id,
s.source_id AS source_id,
t.categ_id AS categ_id,
s.pricelist_id AS pricelist_id,
s.analytic_account_id AS analytic_account_id,
s.team_id AS team_id,
p.product_tmpl_id,
partner.country_id AS country_id,
partner.industry_id AS industry_id,
partner.commercial_partner_id AS commercial_partner_id,
CASE WHEN l.product_id IS NOT NULL THEN SUM(p.weight * l.product_uom_qty / u.factor * u2.factor) ELSE 0 END AS weight,
CASE WHEN l.product_id IS NOT NULL THEN SUM(p.volume * l.product_uom_qty / u.factor * u2.factor) ELSE 0 END AS volume,
l.discount AS discount,
CASE WHEN l.product_id IS NOT NULL THEN SUM(l.price_unit * l.product_uom_qty * l.discount / 100.0
/ {self._case_value_or_one('s.currency_rate')}
* {self._case_value_or_one('currency_table.rate')}
) ELSE 0
END AS discount_amount,
s.id AS order_id"""
additional_fields_info = self._select_additional_fields()
template = """,
%s AS %s"""
for fname, query_info in additional_fields_info.items():
select_ += template % (query_info, fname)
return select_
def _case_value_or_one(self, value):
return f"""CASE COALESCE({value}, 0) WHEN 0 THEN 1.0 ELSE {value} END"""
def _select_additional_fields(self):
"""Hook to return additional fields SQL specification for select part of the table query.
:returns: mapping field -> SQL computation of field, will be converted to '_ AS _field' in the final table definition
:rtype: dict
"""
return {}
def _from_sale(self):
return """
sale_order_line l
LEFT JOIN sale_order s ON s.id=l.order_id
JOIN res_partner partner ON s.partner_id = partner.id
LEFT JOIN product_product p ON l.product_id=p.id
LEFT JOIN product_template t ON p.product_tmpl_id=t.id
LEFT JOIN uom_uom u ON u.id=l.product_uom
LEFT JOIN uom_uom u2 ON u2.id=t.uom_id
JOIN {currency_table} ON currency_table.company_id = s.company_id
""".format(
currency_table=self.env['res.currency']._get_query_currency_table(
{
'multi_company': True,
'date': {'date_to': fields.Date.today()}
}),
)
def _where_sale(self):
return """
l.display_type IS NULL"""
def _group_by_sale(self):
return """
l.product_id,
l.order_id,
t.uom_id,
t.categ_id,
s.name,
s.date_order,
s.partner_id,
s.user_id,
s.state,
s.company_id,
s.campaign_id,
s.medium_id,
s.source_id,
s.pricelist_id,
s.analytic_account_id,
s.team_id,
p.product_tmpl_id,
partner.country_id,
partner.industry_id,
partner.commercial_partner_id,
l.discount,
s.id,
currency_table.rate"""
def _query(self):
with_ = self._with_sale()
return f"""
{"WITH" + with_ + "(" if with_ else ""}
SELECT {self._select_sale()}
FROM {self._from_sale()}
WHERE {self._where_sale()}
GROUP BY {self._group_by_sale()}
{")" if with_ else ""}
"""
@property
def _table_query(self):
return self._query()

View file

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_order_product_pivot" model="ir.ui.view">
<field name="name">sale.report.pivot</field>
<field name="model">sale.report</field>
<field name="arch" type="xml">
<pivot string="Sales Analysis" sample="1">
<field name="team_id" type="col"/>
<field name="date" interval="month" type="row"/>
<field name="price_subtotal" type="measure"/>
</pivot>
</field>
</record>
<record id="view_order_product_graph" model="ir.ui.view">
<field name="name">sale.report.graph</field>
<field name="model">sale.report</field>
<field name="arch" type="xml">
<graph string="Sales Analysis" type="line" sample="1">
<field name="date" interval="day"/>
<field name="price_subtotal" type="measure"/>
</graph>
</field>
</record>
<record id="sale_report_view_tree" model="ir.ui.view">
<field name="name">sale.report.view.tree</field>
<field name="model">sale.report</field>
<field name="arch" type="xml">
<tree string="Sales Analysis">
<field name="date" widget="date"/>
<field name="order_id" optional="show"/>
<field name="partner_id" optional="hide"/>
<field name="user_id" optional="show" widget="many2one_avatar_user"/>
<field name="team_id" optional="show"/>
<field name="company_id" optional="show" groups="base.group_multi_company"/>
<field name="price_subtotal" optional="hide" sum="Sum of Untaxed Total"/>
<field name="price_total" optional="show" sum="Sum of Total"/>
<field name="state" optional="hide"/>
</tree>
</field>
</record>
<record id="view_order_product_search" model="ir.ui.view">
<field name="name">sale.report.search</field>
<field name="model">sale.report</field>
<field name="arch" type="xml">
<search string="Sales Analysis">
<field name="date"/>
<filter string="Date" name="year" invisible="1" date="date" default_period="this_year"/>
<filter string="Quotations" name="Quotations" domain="[('state','in', ('draft', 'sent'))]"/>
<filter string="Sales Orders" name="Sales" domain="[('state','not in',('draft', 'cancel', 'sent'))]"/>
<separator/>
<filter name="filter_date" date="date" default_period="this_month"/>
<filter name="filter_order_date" invisible="1" string="Order Date: Last 365 Days" domain="[('date', '&gt;=', (datetime.datetime.combine(context_today() + relativedelta(days=-365), datetime.time(0,0,0))).strftime('%Y-%m-%d %H:%M:%S'))]"/>
<separator/>
<field name="user_id"/>
<field name="team_id"/>
<field name="product_id"/>
<field name="categ_id"/>
<field name="partner_id"/>
<field name="country_id"/>
<field name="industry_id"/>
<group expand="0" string="Extended Filters">
<field name="categ_id" filter_domain="[('categ_id', 'child_of', self)]"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
<group expand="1" string="Group By">
<filter string="Salesperson" name="User" context="{'group_by':'user_id'}"/>
<filter string="Sales Team" name="sales_channel" context="{'group_by':'team_id'}"/>
<filter string="Customer" name="Customer" context="{'group_by':'partner_id'}"/>
<filter string="Customer Country" name="country_id" context="{'group_by':'country_id'}"/>
<filter string="Customer Industry" name="industry_id" context="{'group_by':'industry_id'}"/>
<filter string="Product" name="Product" context="{'group_by':'product_id'}"/>
<filter string="Product Category" name="Category" context="{'group_by':'categ_id'}"/>
<filter string="Status" name="status" context="{'group_by':'state'}"/>
<filter string="Company" name="company" groups="base.group_multi_company" context="{'group_by':'company_id'}"/>
<separator/>
<filter string="Order Date" name="date" context="{'group_by':'date'}"
invisible="context.get('sale_report_view_hide_date')"/>
<filter string="Order Date" name="group_by_date_day" context="{'group_by':'date:day'}"
invisible="not context.get('sale_report_view_hide_date')"/>
</group>
</search>
</field>
</record>
<record id="action_order_report_all" model="ir.actions.act_window">
<field name="name">Sales Analysis</field>
<field name="res_model">sale.report</field>
<field name="view_mode">graph,pivot,tree</field>
<field name="view_id"></field> <!-- force empty -->
<field name="search_view_id" ref="view_order_product_search"/>
<field name="domain">[('state', '!=', 'cancel')]</field>
<field name="context">{'search_default_Sales':1, 'group_by_no_leaf':1,'group_by':[], 'search_default_filter_order_date': 1}</field>
<field name="help">This report performs analysis on your quotations and sales orders. Analysis check your sales revenues and sort it by different group criteria (salesman, partner, product, etc.) Use this report to perform analysis on sales not having invoiced yet. If you want to analyse your turnover, you should use the Invoice Analysis report in the Accounting application.</field>
</record>
<record id="report_all_channels_sales_action" model="ir.actions.act_window">
<field name="name">Sales Analysis</field>
<field name="res_model">sale.report</field>
<field name="view_mode">pivot,tree,graph</field>
</record>
<record id="action_order_report_quotation_salesteam" model="ir.actions.act_window">
<field name="name">Quotations Analysis</field>
<field name="res_model">sale.report</field>
<field name="view_mode">graph,tree</field>
<field name="domain">[('state','=','draft'),('team_id', '=', active_id)]</field>
<field name="context">{'search_default_order_month':1}</field>
<field name="help">This report performs analysis on your quotations. Analysis check your sales revenues and sort it by different group criteria (salesman, partner, product, etc.) Use this report to perform analysis on sales not having invoiced yet. If you want to analyse your turnover, you should use the Invoice Analysis report in the Accounting application.</field>
</record>
<record id="action_order_report_so_salesteam" model="ir.actions.act_window">
<field name="name">Sales Analysis</field>
<field name="res_model">sale.report</field>
<field name="view_mode">graph,tree</field>
<field name="domain">[('state','not in',('draft','cancel'))]</field>
<field name="context">{
'search_default_Sales': 1,
'search_default_filter_date': 1,
'search_default_team_id': [active_id]}</field>
<field name="help">This report performs analysis on your sales orders. Analysis check your sales revenues and sort it by different group criteria (salesman, partner, product, etc.) Use this report to perform analysis on sales not having invoiced yet. If you want to analyse your turnover, you should use the Invoice Analysis report in the Accounting application.</field>
</record>
</odoo>