Merge branch 'master' of https://github.com/odoo/odoo
[odoo/odoo.git] / addons / mrp / report / price.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 import time
23
24 import openerp
25 from openerp.report.interface import report_rml
26 from openerp.tools import to_xml
27 from openerp.report import report_sxw
28 from datetime import datetime
29 from openerp.tools.translate import _
30
31 class report_custom(report_rml):
32     def create_xml(self, cr, uid, ids, datas, context=None):
33         number = (datas.get('form', False) and datas['form']['number']) or 1
34         registry = openerp.registry(cr.dbname)
35         product_pool = registry.get('product.product')
36         product_uom_pool = registry.get('product.uom')
37         workcenter_pool = registry.get('mrp.workcenter')
38         user_pool = registry.get('res.users')
39         bom_pool = registry.get('mrp.bom')
40         pricelist_pool = registry.get('product.pricelist')
41         rml_obj=report_sxw.rml_parse(cr, uid, product_pool._name,context)
42         rml_obj.localcontext.update({'lang':context.get('lang',False)})
43         company_currency = user_pool.browse(cr, uid, uid).company_id.currency_id
44         company_currency_symbol = company_currency.symbol or company_currency.name
45         def process_bom(bom, currency_id, factor=1):
46             xml = '<row>'
47             sum = 0
48             sum_strd = 0
49             prod = product_pool.browse(cr, uid, bom['product_id'])
50
51             prod_name = to_xml(bom['name'])
52             prod_qtty = factor * bom['product_qty']
53             product_uom = product_uom_pool.browse(cr, uid, bom['product_uom'], context=context)
54             product_uom_name = to_xml(product_uom.name)
55             main_sp_price, main_sp_name , main_strd_price = '','',''
56             sellers, sellers_price = '',''
57
58             if prod.seller_id:
59                 main_sp_name = '- <b>'+ to_xml(prod.seller_id.name) +'</b>\r\n'
60                 pricelist =  prod.seller_id.property_product_pricelist_purchase
61                 price = pricelist_pool.price_get(cr,uid,[pricelist.id],
62                      prod.id, number*prod_qtty or 1.0, prod.seller_id.id, {
63                         'uom': prod.uom_po_id.id,
64                         'date': time.strftime('%Y-%m-%d'),
65                         })[pricelist.id]
66                 main_sp_price = """<b>"""+rml_obj.formatLang(price)+' '+ (company_currency_symbol)+"""</b>\r\n"""
67                 sum += prod_qtty*price
68             std_price = product_uom_pool._compute_price(cr, uid, prod.uom_id.id, prod.standard_price, to_uom_id=product_uom.id)
69             main_strd_price = str(std_price) + '\r\n'
70             sum_strd = prod_qtty*std_price
71             for seller_id in prod.seller_ids:
72                 if seller_id.name.id == prod.seller_id.id:
73                     continue
74                 sellers +=  '- <i>'+ to_xml(seller_id.name.name) +'</i>\r\n'
75                 pricelist = seller_id.name.property_product_pricelist_purchase
76                 price = pricelist_pool.price_get(cr,uid,[pricelist.id],
77                      prod.id, number*prod_qtty or 1.0, seller_id.name.id, {
78                         'uom': prod.uom_po_id.id,
79                         'date': time.strftime('%Y-%m-%d'),
80                         })[pricelist.id]
81                 sellers_price += """<i>"""+rml_obj.formatLang(price) +' '+ (company_currency_symbol) +"""</i>\r\n"""
82             xml += """<col para='yes'> """+ prod_name +""" </col>
83                     <col para='yes'> """+ main_sp_name + sellers + """ </col>
84                     <col f='yes'>"""+ rml_obj.formatLang(prod_qtty) +' '+ product_uom_name +"""</col>
85                     <col f='yes'>"""+ rml_obj.formatLang(float(main_strd_price)) +' '+ (company_currency_symbol) +"""</col>
86                     <col f='yes'>""" + main_sp_price + sellers_price + """</col>'"""
87
88             xml += '</row>'
89             return xml, sum, sum_strd
90
91         def process_workcenter(wrk):
92             workcenter = workcenter_pool.browse(cr, uid, wrk['workcenter_id'])
93             cost_cycle = wrk['cycle']*workcenter.costs_cycle
94             cost_hour = wrk['hour']*workcenter.costs_hour
95             total = cost_cycle + cost_hour
96             xml = '<row>'
97             xml += "<col para='yes'>" + to_xml(workcenter.name) + '</col>'
98             xml += "<col/>"
99             xml += """<col f='yes'>"""+rml_obj.formatLang(cost_cycle)+' '+ (company_currency_symbol) + """</col>"""
100             xml += """<col f='yes'>"""+rml_obj.formatLang(cost_hour)+' '+ (company_currency_symbol) + """</col>"""
101             xml += """<col f='yes'>"""+rml_obj.formatLang(cost_hour + cost_cycle)+' '+ (company_currency_symbol) + """</col>"""
102             xml += '</row>'
103
104             return xml, total
105
106
107         xml = ''
108         config_start = """
109         <config>
110             <date>""" + to_xml(rml_obj.formatLang(datetime.now().strftime('%Y-%m-%d %H:%M:%S'),date_time=True)) + """</date>
111             <company>%s</company>
112             <PageSize>210.00mm,297.00mm</PageSize>
113             <PageWidth>595.27</PageWidth>
114             <PageHeight>841.88</PageHeight>
115             <tableSize>55.00mm,58.00mm,29.00mm,29.00mm,29.00mm</tableSize>
116             """ % to_xml(user_pool.browse(cr, uid, uid).company_id.name)
117         config_stop = """
118             <report-footer>Generated by Odoo</report-footer>
119         </config>
120         """
121
122         workcenter_header = """
123             <lines style='header'>
124                 <row>
125                     <col>%s</col>
126                     <col t='yes'/>
127                     <col t='yes'>%s</col>
128                     <col t='yes'>%s</col>
129                     <col t='yes'>%s</col>
130                 </row>
131             </lines>
132         """ % (_('Work Center name'), _('Cycles Cost'), _('Hourly Cost'),_('Work Cost'))
133         prod_header = """
134                 <row>
135                     <col>%s</col>
136                     <col>%s</col>
137                     <col t='yes'>%s</col>
138                     <col t='yes'>%s</col>
139                     <col t='yes'>%s</col>
140                 </row>
141         """ % (_('Components'), _('Components suppliers'), _('Quantity'),_('Cost Price per Unit of Measure'), _('Supplier Price per Unit of Measure'))
142
143         purchase_price_digits = rml_obj.get_digits(dp='Product Price')
144
145         for product in product_pool.browse(cr, uid, ids, context=context):
146             product_uom_name = to_xml(product.uom_id.name)
147             bom_id = bom_pool._bom_find(cr, uid, product_id=product.id, context=context)
148             title = "<title>%s</title>" %(_("Cost Structure"))
149             title += "<title>%s</title>" % (to_xml(product.name))
150             xml += "<lines style='header'>" + title + prod_header + "</lines>"
151             if not bom_id:
152                 total_strd = number * product.standard_price
153                 total = number * product_pool.price_get(cr, uid, [product.id], 'standard_price')[product.id]
154                 xml += """<lines style='lines'><row>
155                     <col para='yes'>-</col>
156                     <col para='yes'>-</col>
157                     <col para='yes'>-</col>
158                     <col para='yes'>-</col>
159                     <col para='yes'>-</col>
160                     </row></lines>"""
161                 xml += """<lines style='total'> <row>
162                     <col> """ + _('Total Cost of %s %s') % (str(number), product_uom_name) + """: </col>
163                     <col/>
164                     <col f='yes'/>
165                     <col t='yes'>"""+ rml_obj.formatLang(total_strd, digits=purchase_price_digits) +' '+ (company_currency_symbol) + """</col>
166                     <col t='yes'>"""+ rml_obj.formatLang(total, digits=purchase_price_digits) +' '+ (company_currency_symbol) + """</col>
167                     </row></lines>'"""
168             else:
169                 bom = bom_pool.browse(cr, uid, bom_id, context=context)
170                 factor = number * product.uom_id.factor / bom.product_uom.factor
171                 sub_boms = bom_pool._bom_explode(cr, uid, bom, product, factor / bom.product_qty, context=context)
172                 total = 0
173                 total_strd = 0
174                 parent_bom = {
175                         'product_qty': bom.product_qty,
176                         'name': bom.product_id.name,
177                         'product_uom': bom.product_uom.id,
178                         'product_id': bom.product_id.id
179                 }
180                 xml_tmp = ''
181                 for sub_bom in (sub_boms and sub_boms[0]) or [parent_bom]:
182                     txt, sum, sum_strd = process_bom(sub_bom, company_currency.id)
183                     xml_tmp +=  txt
184                     total += sum
185                     total_strd += sum_strd
186
187                 xml += "<lines style='lines'>" + xml_tmp + '</lines>'
188                 xml += """<lines style='sub_total'> <row>
189                     <col> """ + _('Components Cost of %s %s') % (str(number), product_uom_name) + """: </col>
190                     <col/>
191                     <col t='yes'/>
192                     <col t='yes'>"""+ rml_obj.formatLang(total_strd, digits=purchase_price_digits) +' '+ (company_currency_symbol) + """</col>
193                     <col t='yes'></col>
194                     </row></lines>'"""
195
196                 total2 = 0
197                 xml_tmp = ''
198                 for wrk in (sub_boms and sub_boms[1]):
199                     txt, sum = process_workcenter(wrk)
200                     xml_tmp += txt
201                     total2 += sum
202                 if xml_tmp:
203                     xml += workcenter_header
204                     xml += "<lines style='lines'>" + xml_tmp + '</lines>'
205                     xml += """<lines style='sub_total'> <row>
206                     <col> """ + _('Work Cost of %s %s') % (str(number), product_uom_name) +""": </col>
207                     <col/>
208                     <col/>
209                     <col/>
210                     <col t='yes'>"""+ rml_obj.formatLang(total2, digits=purchase_price_digits) +' '+ (company_currency_symbol) +"""</col>
211                     </row></lines>'"""
212                 xml += """<lines style='total'> <row>
213                     <col> """ + _('Total Cost of %s %s') % (str(number), product_uom_name) + """: </col>
214                     <col/>
215                     <col t='yes'/>
216                     <col t='yes'>"""+ rml_obj.formatLang(total_strd+total2, digits=purchase_price_digits) +' '+ (company_currency_symbol) + """</col>
217                     <col t='yes'></col>
218                     </row></lines>'"""
219
220         xml = '<?xml version="1.0" ?><report>' + config_start + config_stop + xml + '</report>'
221
222         return xml
223
224 report_custom('report.product.price', 'product.product', '', 'addons/mrp/report/price.xsl')
225
226 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: