[IMP] purchase: purchase report improvement
Modify purchase report in order to make it consistent with sales report. For the RFQ it will show the Order Date and for the Purchase order menu it will display the Confirmation Date. Also rewrite a bit the SQL view in order to compute every purchase order in the company currency. Technicaly rewrite the SQL alias in order to have a report more readable in the future. Task ID : 1857130. closes odoo/odoo#28248 Signed-off-by: Arnold Moyaux <amoyaux@users.noreply.github.com>
This commit is contained in:
committed by
Arnold Moyaux
parent
2d4b026625
commit
b5cea7e2b6
@@ -19,21 +19,21 @@
|
||||
'price_unit': 79.80,
|
||||
'product_qty': 15.0,
|
||||
'product_uom': ref('uom.product_uom_unit'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')}),
|
||||
'date_planned': DateTime.today() + relativedelta(days=3)}),
|
||||
(0, 0, {
|
||||
'product_id': ref('product.product_product_25'),
|
||||
'name': obj().env.ref('product.product_product_25').partner_ref,
|
||||
'price_unit': 2868.70,
|
||||
'product_qty': 5.0,
|
||||
'product_uom': ref('uom.product_uom_unit'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')}),
|
||||
'date_planned': DateTime.today() + relativedelta(days=3)}),
|
||||
(0, 0, {
|
||||
'product_id': ref('product.product_product_27'),
|
||||
'name': obj().env.ref('product.product_product_27').partner_ref,
|
||||
'price_unit': 3297.20,
|
||||
'product_qty': 4.0,
|
||||
'product_uom': ref('uom.product_uom_unit'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')})
|
||||
'date_planned': DateTime.today() + relativedelta(days=3)})
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
@@ -48,14 +48,14 @@
|
||||
'price_unit': 132.50,
|
||||
'product_qty': 20.0,
|
||||
'product_uom': ref('uom.product_uom_unit'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')}),
|
||||
'date_planned': DateTime.today() + relativedelta(days=1)}),
|
||||
(0, 0, {
|
||||
'product_id': ref('product.product_delivery_01'),
|
||||
'name': obj().env.ref('product.product_delivery_01').partner_ref,
|
||||
'price_unit': 89.0,
|
||||
'product_qty': 5.0,
|
||||
'product_uom': ref('uom.product_uom_unit'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')}),
|
||||
'date_planned': DateTime.today() + relativedelta(days=1)}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
'price_unit': 25.50,
|
||||
'product_qty': 10.0,
|
||||
'product_uom': ref('uom.product_uom_hour'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')}),
|
||||
'date_planned': DateTime.today() + relativedelta(days=1)}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
@@ -85,21 +85,21 @@
|
||||
'price_unit': 85.50,
|
||||
'product_qty': 6.0,
|
||||
'product_uom': ref('uom.product_uom_unit'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')}),
|
||||
'date_planned': DateTime.today() + relativedelta(days=5)}),
|
||||
(0, 0, {
|
||||
'product_id': ref('product.product_product_20'),
|
||||
'name': obj().env.ref('product.product_product_20').partner_ref,
|
||||
'price_unit': 1690.0,
|
||||
'product_qty': 5.0,
|
||||
'product_uom': ref('uom.product_uom_unit'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')}),
|
||||
'date_planned': DateTime.today() + relativedelta(days=5)}),
|
||||
(0, 0, {
|
||||
'product_id': ref('product.product_product_6'),
|
||||
'name': obj().env.ref('product.product_product_6').partner_ref,
|
||||
'price_unit': 800.0,
|
||||
'product_qty': 7.0,
|
||||
'product_uom': ref('uom.product_uom_unit'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')})
|
||||
'date_planned': DateTime.today() + relativedelta(days=5)})
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
@@ -114,14 +114,14 @@
|
||||
'price_unit': 2010.0,
|
||||
'product_qty': 3.0,
|
||||
'product_uom': ref('uom.product_uom_unit'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')}),
|
||||
'date_planned': DateTime.today()}),
|
||||
(0, 0, {
|
||||
'product_id': ref('product.product_product_24'),
|
||||
'name': obj().env.ref('product.product_product_24').partner_ref,
|
||||
'price_unit': 876.0,
|
||||
'product_qty': 3.0,
|
||||
'product_uom': ref('uom.product_uom_unit'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')}),
|
||||
'date_planned': DateTime.today()}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
@@ -136,21 +136,21 @@
|
||||
'price_unit': 58.0,
|
||||
'product_qty': 9.0,
|
||||
'product_uom': ref('uom.product_uom_unit'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')}),
|
||||
'date_planned': DateTime.today()}),
|
||||
(0, 0, {
|
||||
'product_id': ref('product.product_delivery_01'),
|
||||
'name': obj().env.ref('product.product_delivery_01').partner_ref,
|
||||
'price_unit': 65.0,
|
||||
'product_qty': 3.0,
|
||||
'product_uom': ref('uom.product_uom_unit'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')}),
|
||||
'date_planned': DateTime.today()}),
|
||||
(0, 0, {
|
||||
'product_id': ref('product.consu_delivery_01'),
|
||||
'name': obj().env.ref('product.consu_delivery_01').partner_ref,
|
||||
'price_unit': 154.5,
|
||||
'product_qty': 4.0,
|
||||
'product_uom': ref('uom.product_uom_unit'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')}),
|
||||
'date_planned': DateTime.today()}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
@@ -165,14 +165,14 @@
|
||||
'price_unit': 13.5,
|
||||
'product_qty': 5.0,
|
||||
'product_uom': ref('uom.product_uom_unit'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')}),
|
||||
'date_planned': DateTime.today()}),
|
||||
(0, 0, {
|
||||
'product_id': ref('product.product_delivery_02'),
|
||||
'name': obj().env.ref('product.product_delivery_02').partner_ref,
|
||||
'price_unit': 38.0,
|
||||
'product_qty': 15.0,
|
||||
'product_uom': ref('uom.product_uom_unit'),
|
||||
'date_planned': time.strftime('%Y-%m-%d')}),
|
||||
'date_planned': DateTime.today()}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ class PurchaseOrder(models.Model):
|
||||
"delivery order sent by your vendor.")
|
||||
date_order = fields.Datetime('Order Date', required=True, states=READONLY_STATES, index=True, copy=False, default=fields.Datetime.now,\
|
||||
help="Depicts the date where the Quotation should be validated and converted into a purchase order.")
|
||||
date_approve = fields.Date('Confirmation Date', readonly=1, index=True, copy=False)
|
||||
date_approve = fields.Datetime('Confirmation Date', readonly=1, index=True, copy=False)
|
||||
partner_id = fields.Many2one('res.partner', string='Vendor', required=True, states=READONLY_STATES, change_default=True, tracking=True, help="You can find a vendor by its Name, TIN, Email or Internal Reference.")
|
||||
dest_address_id = fields.Many2one('res.partner', string='Drop Ship Address', states=READONLY_STATES,
|
||||
help="Put an address if you want to deliver directly from the vendor to the customer. "
|
||||
@@ -125,6 +125,7 @@ class PurchaseOrder(models.Model):
|
||||
product_id = fields.Many2one('product.product', related='order_line.product_id', string='Product', readonly=False)
|
||||
user_id = fields.Many2one('res.users', string='Purchase Representative', index=True, tracking=True, default=lambda self: self.env.user)
|
||||
company_id = fields.Many2one('res.company', 'Company', required=True, index=True, states=READONLY_STATES, default=lambda self: self.env.company.id)
|
||||
currency_rate = fields.Float("Currency Rate", compute='_compute_currency_rate', compute_sudo=True, store=True, readonly=True, help='Ratio between the purchase order currency and the company currency')
|
||||
|
||||
def _compute_access_url(self):
|
||||
super(PurchaseOrder, self)._compute_access_url()
|
||||
@@ -140,6 +141,11 @@ class PurchaseOrder(models.Model):
|
||||
purchase_order_ids = self._search(expression.AND([domain, args]), limit=limit, access_rights_uid=name_get_uid)
|
||||
return self.browse(purchase_order_ids).name_get()
|
||||
|
||||
@api.depends('date_order', 'currency_id', 'company_id', 'company_id.currency_id')
|
||||
def _compute_currency_rate(self):
|
||||
for order in self:
|
||||
order.currency_rate = self.env['res.currency']._get_conversion_rate(order.company_id.currency_id, order.currency_id, order.company_id, order.date_order)
|
||||
|
||||
@api.multi
|
||||
@api.depends('name', 'partner_ref')
|
||||
def name_get(self):
|
||||
|
||||
@@ -25,18 +25,15 @@ class PurchaseReport(models.Model):
|
||||
], 'Order Status', readonly=True)
|
||||
product_id = fields.Many2one('product.product', 'Product', readonly=True)
|
||||
partner_id = fields.Many2one('res.partner', 'Vendor', readonly=True)
|
||||
date_approve = fields.Date('Date Approved', readonly=True)
|
||||
date_approve = fields.Datetime('Confirmation Date', readonly=True)
|
||||
product_uom = fields.Many2one('uom.uom', 'Reference Unit of Measure', required=True)
|
||||
company_id = fields.Many2one('res.company', 'Company', readonly=True)
|
||||
currency_id = fields.Many2one('res.currency', 'Currency', readonly=True)
|
||||
user_id = fields.Many2one('res.users', 'Purchase Representative', readonly=True)
|
||||
delay = fields.Float('Days to Validate', digits=(16, 2), readonly=True)
|
||||
delay_pass = fields.Float('Days to Deliver', digits=(16, 2), readonly=True)
|
||||
unit_quantity = fields.Float('Product Quantity', readonly=True, oldname='quantity')
|
||||
price_total = fields.Float('Total Price', readonly=True)
|
||||
price_average = fields.Float('Average Price', readonly=True, group_operator="avg")
|
||||
negociation = fields.Float('Purchase-Standard Price', readonly=True, group_operator="avg")
|
||||
price_standard = fields.Float('Products Value', readonly=True, group_operator="sum")
|
||||
delay = fields.Float('Days to Confirm', digits=(16, 2), readonly=True)
|
||||
delay_pass = fields.Float('Days to Receive', digits=(16, 2), readonly=True)
|
||||
price_total = fields.Float('Total', readonly=True)
|
||||
price_average = fields.Float('Average Cost', readonly=True, group_operator="avg")
|
||||
nbr_lines = fields.Integer('# of Lines', readonly=True, oldname='nbr')
|
||||
category_id = fields.Many2one('product.category', 'Product Category', readonly=True)
|
||||
product_tmpl_id = fields.Many2one('product.template', 'Product Template', readonly=True)
|
||||
@@ -46,6 +43,12 @@ class PurchaseReport(models.Model):
|
||||
commercial_partner_id = fields.Many2one('res.partner', 'Commercial Entity', readonly=True)
|
||||
weight = fields.Float('Gross Weight', readonly=True)
|
||||
volume = fields.Float('Volume', readonly=True)
|
||||
order_id = fields.Many2one('purchase.order', 'Order', readonly=True)
|
||||
untaxed_total = fields.Float('Untaxed Total', readonly=True)
|
||||
qty_ordered = fields.Float('Qty Ordered', readonly=True)
|
||||
qty_received = fields.Float('Qty Received', readonly=True)
|
||||
qty_billed = fields.Float('Qty Billed', readonly=True)
|
||||
qty_to_be_billed = fields.Float('Qty to be Billed', readonly=True)
|
||||
|
||||
@api.model_cr
|
||||
def init(self):
|
||||
@@ -61,80 +64,83 @@ class PurchaseReport(models.Model):
|
||||
select_str = """
|
||||
WITH currency_rate as (%s)
|
||||
SELECT
|
||||
po.id as order_id,
|
||||
min(l.id) as id,
|
||||
s.date_order as date_order,
|
||||
s.state,
|
||||
s.date_approve,
|
||||
s.dest_address_id,
|
||||
s.partner_id as partner_id,
|
||||
s.user_id as user_id,
|
||||
s.company_id as company_id,
|
||||
s.fiscal_position_id as fiscal_position_id,
|
||||
po.date_order as date_order,
|
||||
po.state,
|
||||
po.date_approve,
|
||||
po.dest_address_id,
|
||||
po.partner_id as partner_id,
|
||||
po.user_id as user_id,
|
||||
po.company_id as company_id,
|
||||
po.fiscal_position_id as fiscal_position_id,
|
||||
l.product_id,
|
||||
p.product_tmpl_id,
|
||||
t.categ_id as category_id,
|
||||
s.currency_id,
|
||||
po.currency_id,
|
||||
t.uom_id as product_uom,
|
||||
sum(l.product_qty/u.factor*u2.factor) as unit_quantity,
|
||||
extract(epoch from age(s.date_approve,s.date_order))/(24*60*60)::decimal(16,2) as delay,
|
||||
extract(epoch from age(l.date_planned,s.date_order))/(24*60*60)::decimal(16,2) as delay_pass,
|
||||
extract(epoch from age(po.date_approve,po.date_order))/(24*60*60)::decimal(16,2) as delay,
|
||||
extract(epoch from age(l.date_planned,po.date_order))/(24*60*60)::decimal(16,2) as delay_pass,
|
||||
count(*) as nbr_lines,
|
||||
sum(l.price_unit / COALESCE(NULLIF(cr.rate, 0), 1.0) * l.product_qty)::decimal(16,2) as price_total,
|
||||
avg(100.0 * (l.price_unit / COALESCE(NULLIF(cr.rate, 0),1.0) * l.product_qty) / NULLIF(ip.value_float*l.product_qty/u.factor*u2.factor, 0.0))::decimal(16,2) as negociation,
|
||||
sum(ip.value_float*l.product_qty/u.factor*u2.factor)::decimal(16,2) as price_standard,
|
||||
(sum(l.product_qty * l.price_unit / COALESCE(NULLIF(cr.rate, 0), 1.0))/NULLIF(sum(l.product_qty/u.factor*u2.factor),0.0))::decimal(16,2) as price_average,
|
||||
sum(l.price_total / COALESCE(po.currency_rate, 1.0))::decimal(16,2) as price_total,
|
||||
(sum(l.product_qty * l.price_unit / COALESCE(po.currency_rate, 1.0))/NULLIF(sum(l.product_qty/line_uom.factor*product_uom.factor),0.0))::decimal(16,2) as price_average,
|
||||
partner.country_id as country_id,
|
||||
partner.commercial_partner_id as commercial_partner_id,
|
||||
analytic_account.id as account_analytic_id,
|
||||
sum(p.weight * l.product_qty/u.factor*u2.factor) as weight,
|
||||
sum(p.volume * l.product_qty/u.factor*u2.factor) as volume
|
||||
sum(p.weight * l.product_qty/line_uom.factor*product_uom.factor) as weight,
|
||||
sum(p.volume * l.product_qty/line_uom.factor*product_uom.factor) as volume,
|
||||
sum(l.price_subtotal / COALESCE(po.currency_rate, 1.0))::decimal(16,2) as untaxed_total,
|
||||
sum(l.product_qty / line_uom.factor * product_uom.factor) as qty_ordered,
|
||||
sum(l.qty_received / line_uom.factor * product_uom.factor) as qty_received,
|
||||
sum(l.qty_invoiced / line_uom.factor * product_uom.factor) as qty_billed,
|
||||
sum(l.product_qty / line_uom.factor * product_uom.factor) - sum(l.qty_received / line_uom.factor * product_uom.factor) as qty_to_be_billed
|
||||
""" % self.env['res.currency']._select_companies_rates()
|
||||
return select_str
|
||||
|
||||
def _from(self):
|
||||
from_str = """
|
||||
purchase_order_line l
|
||||
join purchase_order s on (l.order_id=s.id)
|
||||
join res_partner partner on s.partner_id = partner.id
|
||||
join purchase_order po on (l.order_id=po.id)
|
||||
join res_partner partner on po.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 ir_property ip ON (ip.name='standard_price' AND ip.res_id=CONCAT('product.product,',p.id) AND ip.company_id=s.company_id)
|
||||
left join uom_uom u on (u.id=l.product_uom)
|
||||
left join uom_uom u2 on (u2.id=t.uom_id)
|
||||
left join uom_uom line_uom on (line_uom.id=l.product_uom)
|
||||
left join uom_uom product_uom on (product_uom.id=t.uom_id)
|
||||
left join account_analytic_account analytic_account on (l.account_analytic_id = analytic_account.id)
|
||||
left join currency_rate cr on (cr.currency_id = s.currency_id and
|
||||
cr.company_id = s.company_id and
|
||||
cr.date_start <= coalesce(s.date_order, now()) and
|
||||
(cr.date_end is null or cr.date_end > coalesce(s.date_order, now())))
|
||||
left join currency_rate cr on (cr.currency_id = po.currency_id and
|
||||
cr.company_id = po.company_id and
|
||||
cr.date_start <= coalesce(po.date_order, now()) and
|
||||
(cr.date_end is null or cr.date_end > coalesce(po.date_order, now())))
|
||||
"""
|
||||
return from_str
|
||||
|
||||
def _group_by(self):
|
||||
group_by_str = """
|
||||
GROUP BY
|
||||
s.company_id,
|
||||
s.user_id,
|
||||
s.partner_id,
|
||||
u.factor,
|
||||
s.currency_id,
|
||||
po.company_id,
|
||||
po.user_id,
|
||||
po.partner_id,
|
||||
line_uom.factor,
|
||||
po.currency_id,
|
||||
l.price_unit,
|
||||
s.date_approve,
|
||||
po.date_approve,
|
||||
l.date_planned,
|
||||
l.product_uom,
|
||||
s.dest_address_id,
|
||||
s.fiscal_position_id,
|
||||
po.dest_address_id,
|
||||
po.fiscal_position_id,
|
||||
l.product_id,
|
||||
p.product_tmpl_id,
|
||||
t.categ_id,
|
||||
s.date_order,
|
||||
s.state,
|
||||
u.uom_type,
|
||||
u.category_id,
|
||||
po.date_order,
|
||||
po.state,
|
||||
line_uom.uom_type,
|
||||
line_uom.category_id,
|
||||
t.uom_id,
|
||||
u.id,
|
||||
u2.factor,
|
||||
line_uom.id,
|
||||
product_uom.factor,
|
||||
partner.country_id,
|
||||
partner.commercial_partner_id,
|
||||
analytic_account.id
|
||||
analytic_account.id,
|
||||
po.id
|
||||
"""
|
||||
return group_by_str
|
||||
|
||||
@@ -4,12 +4,11 @@
|
||||
<field name="name">product.month.pivot</field>
|
||||
<field name="model">purchase.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Purchase Orders Statistics" disable_linking="True">
|
||||
<field name="partner_id" type="row"/>
|
||||
<field name="date_order" interval="month" type="col"/>
|
||||
<pivot string="Purchase Analysis" disable_linking="True" display_quantity="true">
|
||||
<field name="category_id" type="row"/>
|
||||
<field name="order_id" type="measure"/>
|
||||
<field name="untaxed_total" type="measure"/>
|
||||
<field name="price_total" type="measure"/>
|
||||
<field name="unit_quantity" type="measure"/>
|
||||
<field name="price_average" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
@@ -17,10 +16,9 @@
|
||||
<field name="name">product.month.graph</field>
|
||||
<field name="model">purchase.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Purchase Orders Statistics">
|
||||
<field name="partner_id" type="row"/>
|
||||
<field name="date_order" interval="month" type="col"/>
|
||||
<field name="price_average" type="measure"/>
|
||||
<graph string="Purchase Orders Statistics" type="line">
|
||||
<field name="date_approve" interval="day" type="col"/>
|
||||
<field name="untaxed_total" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
@@ -31,7 +29,6 @@
|
||||
<field name="model_id">purchase.report</field>
|
||||
<field name="domain">[('state','!=','cancel')]</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="context">{'group_by': ['category_id'], 'col_group_by': ['date_order:month'], 'measures': ['unit_quantity']}</field>
|
||||
</record>
|
||||
<record id="filter_purchase_order_price_per_supplier" model="ir.filters">
|
||||
<field name="name">Price Per Vendor</field>
|
||||
@@ -54,8 +51,8 @@
|
||||
<field name="model">purchase.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Purchase Orders">
|
||||
<filter string="Quotations" name="quotes" domain="[('state','=','draft')]"/>
|
||||
<filter string="Orders" name="orders" domain="[('state','!=','draft'),('state','!=','cancel')]"/>
|
||||
<filter string="Requests for Quotation" name="quotes" domain="[('state','=','draft')]"/>
|
||||
<filter string="Purchase Orders" name="orders" domain="[('state','!=','draft'),('state','!=','cancel')]"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="product_id"/>
|
||||
<group expand="0" string="Extended Filters">
|
||||
@@ -69,12 +66,13 @@
|
||||
<filter string="Vendor" name="group_partner_id" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Vendor Country" name="country_id" context="{'group_by':'country_id'}"/>
|
||||
<filter string="Purchase Representative" name="user_id" context="{'group_by':'user_id'}"/>
|
||||
<filter string="Product" name="group_product_id" context="{'group_by':'product_id'}"/>
|
||||
<filter string="Product Category" name="group_category_id" context="{'group_by':'category_id'}"/>
|
||||
<filter string="Fiscal Position" name="fiscal_position" context="{'group_by':'fiscal_position_id'}" help="Purchase Order Fiscal Position"/>
|
||||
<filter string="Status" name="status" context="{'group_by':'state'}"/>
|
||||
<filter string="Company" name="company" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<separator/>
|
||||
<filter string="Order Date" name="order_month" context="{'group_by': 'date_order:month'}"/>
|
||||
<filter string="Confirmation Date" name="group_date_approve_month" context="{'group_by': 'date_approve:month'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
@@ -90,7 +88,8 @@
|
||||
<field name="target">current</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="purchase_report" name="Reporting" parent="purchase.menu_purchase_root" sequence="99"
|
||||
groups="purchase.group_purchase_manager" action="action_purchase_order_report_all"/>
|
||||
<menuitem id="purchase_report" name="Reporting" parent="purchase.menu_purchase_root" sequence="99"/>
|
||||
|
||||
<menuitem id="menu_report_purchase" name="Purchase" action="action_purchase_order_report_all" parent="purchase_report" sequence="1" groups="purchase.group_purchase_manager"/>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import test_purchase_order_report
|
||||
@@ -0,0 +1,79 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from datetime import datetime
|
||||
from odoo.tests import common, Form, tagged
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestPurchaseOrderReport(common.TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestPurchaseOrderReport, self).setUp()
|
||||
|
||||
self.partner_id = self.env.ref('base.res_partner_1')
|
||||
self.product1 = self.env.ref('product.product_product_8')
|
||||
self.product2 = self.env.ref('product.product_product_11')
|
||||
self.PurchaseReport = self.env['purchase.report']
|
||||
|
||||
# Create a new company and set CoA
|
||||
self.company_id = self.env['res.company'].create({'name': 'new_company'})
|
||||
self.env.user.company_id = self.company_id
|
||||
self.env.ref('l10n_generic_coa.configurable_chart_template').load_for_current_company(False, False)
|
||||
|
||||
def test_00_purchase_order_report(self):
|
||||
uom_dozen = self.env.ref('uom.product_uom_dozen')
|
||||
|
||||
eur_currency = self.env.ref('base.EUR')
|
||||
self.company_id.currency_id = self.env.ref('base.USD').id
|
||||
|
||||
self.env['res.currency.rate'].search([]).unlink()
|
||||
self.env['res.currency.rate'].create({
|
||||
'name': datetime.today(),
|
||||
'rate': 2.0,
|
||||
'currency_id': eur_currency.id,
|
||||
})
|
||||
po = self.env['purchase.order'].create({
|
||||
'partner_id': self.partner_id.id,
|
||||
'currency_id': eur_currency.id,
|
||||
'order_line': [
|
||||
(0, 0, {
|
||||
'name': self.product1.name,
|
||||
'product_id': self.product1.id,
|
||||
'product_qty': 1.0,
|
||||
'product_uom': uom_dozen.id,
|
||||
'price_unit': 100.0,
|
||||
'date_planned': datetime.today(),
|
||||
}),
|
||||
(0, 0, {
|
||||
'name': self.product2.name,
|
||||
'product_id': self.product2.id,
|
||||
'product_qty': 1.0,
|
||||
'product_uom': uom_dozen.id,
|
||||
'price_unit': 200.0,
|
||||
'date_planned': datetime.today(),
|
||||
}),
|
||||
],
|
||||
})
|
||||
po.button_confirm()
|
||||
|
||||
f = Form(self.env['account.invoice'])
|
||||
f.partner_id = po.partner_id
|
||||
f.purchase_id = po
|
||||
invoice = f.save()
|
||||
invoice.action_invoice_open()
|
||||
|
||||
res_product1 = self.PurchaseReport.search([
|
||||
('order_id', '=', po.id), ('product_id', '=', self.product1.id)])
|
||||
|
||||
# check that report will convert dozen to unit or not
|
||||
self.assertEquals(res_product1.qty_ordered, 12.0, 'UoM conversion is not working')
|
||||
# report should show in company currency (amount/rate) = (100/2)
|
||||
self.assertEquals(res_product1.price_total, 50.0, 'Currency conversion is not working')
|
||||
|
||||
res_product2 = self.PurchaseReport.search([
|
||||
('order_id', '=', po.id), ('product_id', '=', self.product2.id)])
|
||||
|
||||
# Check that repost should show 6 unit of product
|
||||
self.assertEquals(res_product2.qty_ordered, 12.0, 'UoM conversion is not working')
|
||||
# report should show in company currency (amount/rate) = (200/2)
|
||||
self.assertEquals(res_product2.price_total, 100.0, 'Currency conversion is not working')
|
||||
@@ -175,7 +175,8 @@
|
||||
<field name="currency_id" groups="base.group_multi_currency"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="date_order"/>
|
||||
<field name="date_order" attrs="{'invisible': [('state','=','purchase')]}"/>
|
||||
<field name="date_approve" attrs="{'invisible': [('state','!=','purchase')]}"/>
|
||||
<field name="origin" attrs="{'invisible': [('origin','=',False)]}"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
</group>
|
||||
@@ -374,7 +375,8 @@
|
||||
<tree decoration-bf="message_unread==True" decoration-muted="state=='cancel'" decoration-info="state in ('wait','confirmed')" string="Purchase Order">
|
||||
<field name="message_unread" invisible="1"/>
|
||||
<field name="name" string="Reference"/>
|
||||
<field name="date_order" />
|
||||
<field name="date_order" invisible="not context.get('quotation_only', False)"/>
|
||||
<field name="date_approve" invisible="context.get('quotation_only', False)"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
|
||||
<field name="date_planned" invisible="context.get('quotation_only', False)"/>
|
||||
@@ -420,6 +422,7 @@
|
||||
<field name="res_model">purchase.order</field>
|
||||
<field name="view_mode">tree,kanban,form,pivot,graph,calendar,activity</field>
|
||||
<field name="search_view_id" ref="view_purchase_order_filter"/>
|
||||
<field name="context">{'quotation_only': True}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create a request for quotation
|
||||
|
||||
@@ -13,7 +13,7 @@ class PurchaseReport(models.Model):
|
||||
return super(PurchaseReport, self)._select() + ", spt.warehouse_id as picking_type_id"
|
||||
|
||||
def _from(self):
|
||||
return super(PurchaseReport, self)._from() + " left join stock_picking_type spt on (spt.id=s.picking_type_id)"
|
||||
return super(PurchaseReport, self)._from() + " left join stock_picking_type spt on (spt.id=po.picking_type_id)"
|
||||
|
||||
def _group_by(self):
|
||||
return super(PurchaseReport, self)._group_by() + ", spt.warehouse_id"
|
||||
|
||||
Reference in New Issue
Block a user