diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py index de4948f0bd1..a982ca51182 100644 --- a/addons/account/account_analytic_line.py +++ b/addons/account/account_analytic_line.py @@ -112,13 +112,29 @@ class account_analytic_line(osv.osv): (prod.name, prod_id,)) amount_unit = prod.price_get('list_price', context)[prod_id] - prec = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account') - amount = amount_unit * quantity or 1.0 - result = round(amount, prec) - if is_purchase: - result *= -1 - return { - 'value': { + if not company_id: + company_id=company_obj._company_default_get(cr, uid, 'account.analytic.line', context) + flag = False + # Compute based on pricetype + product_price_type_ids = product_price_type_obj.search(cr, uid, [('field','=','standard_price')], context) + pricetype = product_price_type_obj.browse(cr, uid, product_price_type_ids, context)[0] + if journal_id: + journal = analytic_journal_obj.browse(cr, uid, journal_id) + if journal.type == 'sale': + product_price_type_ids = product_price_type_obj.search(cr, uid, [('field','=','list_price')], context) + if product_price_type_ids: + pricetype = product_price_type_obj.browse(cr, uid, product_price_type_ids, context)[0] + # Take the company currency as the reference one + if pricetype.field == 'list_price': + flag = True + amount_unit = prod.price_get(pricetype.field, context)[prod.id] + amount = amount_unit*unit_amount or 1.0 + prec = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account') + amount = amount_unit*unit_amount or 1.0 + result = round(amount, prec) + if not flag: + result *= -1 + return {'value': { 'amount': result, 'general_account_id': a, } diff --git a/addons/account/board_account_view.xml b/addons/account/board_account_view.xml index 190479f63a7..89767eb1507 100644 --- a/addons/account/board_account_view.xml +++ b/addons/account/board_account_view.xml @@ -68,6 +68,6 @@ - + diff --git a/addons/account/product_view.xml b/addons/account/product_view.xml index cc9351d55f4..67352fd1120 100644 --- a/addons/account/product_view.xml +++ b/addons/account/product_view.xml @@ -9,7 +9,7 @@ - + diff --git a/addons/crm/crm_opportunity.py b/addons/crm/crm_opportunity.py index 2b0062eb9d5..9047007d52c 100644 --- a/addons/crm/crm_opportunity.py +++ b/addons/crm/crm_opportunity.py @@ -19,8 +19,7 @@ # ############################################################################## -from datetime import datetime -from osv import fields,osv,orm +from osv import fields,osv from tools.translate import _ import crm import time @@ -121,7 +120,7 @@ class crm_opportunity(osv.osv): """ res = super(crm_opportunity, self).case_reset(cr, uid, ids, *args) self.write(cr, uid, ids, {'stage_id': False}) - return True + return res def case_open(self, cr, uid, ids, *args): diff --git a/addons/decimal_precision/decimal_precision.py b/addons/decimal_precision/decimal_precision.py index 1986eb8c441..5dbb2006b52 100644 --- a/addons/decimal_precision/decimal_precision.py +++ b/addons/decimal_precision/decimal_precision.py @@ -27,7 +27,7 @@ import pooler class decimal_precision(osv.osv): _name = 'decimal.precision' _columns = { - 'name': fields.char('Usage', size=50, required=True), + 'name': fields.char('Usage', size=50, select=True, required=True), 'digits': fields.integer('Digits', required=True), } _defaults = { @@ -35,7 +35,7 @@ class decimal_precision(osv.osv): } _sql_constraints = [ - ('name_uniq', 'unique (name)', """The Usage of the decimal precision must be unique!"""), + ('name_uniq', 'unique (name)', """Only one value can be defined for each given usage!"""), ] @cache(skiparg=3) diff --git a/addons/email_template/email_template.py b/addons/email_template/email_template.py index ee82c917351..02ebb1c0bb6 100644 --- a/addons/email_template/email_template.py +++ b/addons/email_template/email_template.py @@ -31,10 +31,8 @@ TEMPLATE_ENGINES = [] from osv import osv, fields from tools.translate import _ -from mako.template import Template #For backward combatibility try: from mako.template import Template as MakoTemplate - from mako import exceptions TEMPLATE_ENGINES.append(('mako', 'Mako Templates')) except: LOGGER.notifyChannel( @@ -302,7 +300,6 @@ This is useful for CRM leads for example"), def unlink_action(self, cr, uid, ids, context): for template in self.browse(cr, uid, ids, context): - obj = self.pool.get(template.object_name.model) try: if template.ref_ir_act_window: self.pool.get('ir.actions.act_window').unlink(cr, uid, template.ref_ir_act_window.id, context) diff --git a/addons/event/event.py b/addons/event/event.py index e2d51474689..16bf5f8677d 100644 --- a/addons/event/event.py +++ b/addons/event/event.py @@ -19,11 +19,10 @@ # ############################################################################## -import time - from crm import crm from osv import fields, osv from tools.translate import _ +import time import tools import decimal_precision as dp @@ -37,7 +36,7 @@ class event_type(osv.osv): } event_type() -class event_event(crm.crm_case, osv.osv): +class event_event(osv.osv): """Event""" _name = 'event.event' _description = __doc__ @@ -55,7 +54,6 @@ class event_event(crm.crm_case, osv.osv): 'registration_ids': False, }) return super(event_event, self).copy(cr, uid, id, default=default, context=context) - def onchange_product(self, cr, uid, ids, product_id): """This function returns value of product's unit price based on product id. @param self: The object pointer @@ -162,9 +160,10 @@ class event_event(crm.crm_case, osv.osv): cr.execute('SELECT SUM(nb_register) FROM event_registration WHERE id IN %s', (tuple(reg_ids),)) number = cr.fetchone() if 'register_current' in fields: - res[event.id]['register_current'] = number and number[0] + res[event.id]['register_current'] = len(reg_ids) if 'register_prospect' in fields: - res[event.id]['register_prospect'] = number and number[0] + res[event.id]['register_prospect'] = len(reg_ids) + return res def write(self, cr, uid, ids, vals, context=None): @@ -245,7 +244,6 @@ class event_event(crm.crm_case, osv.osv): 'state': 'draft', 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'event.event', context=c), 'user_id': lambda obj, cr, uid, context: uid, - 'section_id': crm.crm_case._get_section, } def _check_recursion(self, cr, uid, ids): @@ -340,8 +338,8 @@ class event_registration(osv.osv): _defaults = { 'nb_register': 1, 'tobe_invoiced': True, - 'state': 'draft', - 'active': True, + 'state': lambda *a: 'draft', + 'active': lambda *a: 1, 'user_id': lambda self, cr, uid, ctx: uid, } @@ -357,9 +355,6 @@ class event_registration(osv.osv): val_invoice = inv_pool.onchange_partner_id(cr, uid, [], 'out_invoice', reg.partner_invoice_id.id, False, False) val_invoice['value'].update({'partner_id': reg.partner_invoice_id.id}) - - inv_lines_pool.product_id_change(cr, uid, [], reg.event_id.product_id.id, uom=False, partner_id=reg.partner_invoice_id.id, fposition_id=reg.partner_invoice_id.property_account_position.id) - val_invoice['value'].update({ 'origin': reg.event_product, 'reference': False, @@ -591,6 +586,7 @@ class event_registration(osv.osv): data ={} if not contact: return data + contact_obj = self.pool.get('res.partner.contact') addr_obj = self.pool.get('res.partner.address') job_obj = self.pool.get('res.partner.job') @@ -670,6 +666,7 @@ class event_registration(osv.osv): data['contact_id'] = job_obj.browse(cr, uid, job_ids[0]).contact_id.id d = self.onchange_contact_id(cr, uid, ids, data['contact_id'], part) data.update(d['value']) + partner_data = res_obj.browse(cr, uid, part) return {'value': data} def onchange_partner_invoice_id(self, cr, uid, ids, event_id, partner_invoice_id): @@ -716,4 +713,5 @@ class event_registration_badge(osv.osv): } event_registration_badge() -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/hr_attendance/report/timesheet.py b/addons/hr_attendance/report/timesheet.py index b0845422655..abedddd50c5 100644 --- a/addons/hr_attendance/report/timesheet.py +++ b/addons/hr_attendance/report/timesheet.py @@ -83,7 +83,6 @@ class report_custom(report_rml): dt = datetime.strptime(att['name'], '%Y-%m-%d %H:%M:%S') if att['action'] == 'sign_out': week_wh[ldt.date().weekday()] = week_wh.get(ldt.date().weekday(), 0) + ((dt - ldt).seconds/3600) - ldt = dt # Week xml representation week_repr = ['', '%s' % monday.strftime('%Y-%m-%d'), '%s' % n_monday.strftime('%Y-%m-%d')] diff --git a/addons/hr_expense/hr_expense.py b/addons/hr_expense/hr_expense.py index e9e64f76c4e..0679fee37b1 100644 --- a/addons/hr_expense/hr_expense.py +++ b/addons/hr_expense/hr_expense.py @@ -253,10 +253,8 @@ class hr_expense_line(osv.osv): product = self.pool.get('product.product').browse(cr, uid, product_id, context=context) v['name'] = product.name # Compute based on pricetype of employee company - pricetype_id = self.pool.get('hr.employee').browse(cr, uid, employee_id, context=context).user_id.company_id.property_valuation_price_type.id context['currency_id'] = self.pool.get('hr.employee').browse(cr, uid, employee_id, context=context).user_id.company_id.currency_id.id - pricetype = self.pool.get('product.price.type').browse(cr, uid, pricetype_id, context=context) - amount_unit = product.price_get(pricetype.field, context)[product.id] + amount_unit = product.price_get('standard_price', context)[product.id] v['unit_amount'] = amount_unit if not uom_id: v['uom_id'] = product.uom_id.id diff --git a/addons/mrp/board_manufacturing_view.xml b/addons/mrp/board_manufacturing_view.xml index aa8bd2ab69e..c5474670d9b 100644 --- a/addons/mrp/board_manufacturing_view.xml +++ b/addons/mrp/board_manufacturing_view.xml @@ -15,7 +15,7 @@ - + diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index eea2e4a5224..5f2695cf3a7 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -861,7 +861,7 @@ class mrp_production(osv.osv): source = production.product_id.product_tmpl_id.property_stock_production.id data = { 'name':'PROD:' + production.name, - 'date_planned': production.date_planned, + 'date': production.date_planned, 'product_id': production.product_id.id, 'product_qty': production.product_qty, 'product_uom': production.product_uom.id, @@ -883,7 +883,7 @@ class mrp_production(osv.osv): if line.product_id.type in ('product', 'consu'): res_dest_id = move_obj.create(cr, uid, { 'name':'PROD:' + production.name, - 'date_planned': production.date_planned, + 'date': production.date_planned, 'product_id': line.product_id.id, 'product_qty': line.product_qty, 'product_uom': line.product_uom.id, @@ -904,7 +904,7 @@ class mrp_production(osv.osv): 'product_uom': line.product_uom.id, 'product_uos_qty': line.product_uos and line.product_uos_qty or False, 'product_uos': line.product_uos and line.product_uos.id or False, - 'date_planned': newdate, + 'date': newdate, 'move_dest_id': res_dest_id, 'location_id': production.location_src_id.id, 'location_dest_id': routing_loc or production.location_src_id.id, diff --git a/addons/mrp/mrp_view.xml b/addons/mrp/mrp_view.xml index 6fda888190c..7addfbc3194 100644 --- a/addons/mrp/mrp_view.xml +++ b/addons/mrp/mrp_view.xml @@ -5,10 +5,9 @@ - - + - - - - - - - - - - mrp.production.tree mrp.production diff --git a/addons/mrp/process/procurement_process.xml b/addons/mrp/process/procurement_process.xml index 5b9c8d8f661..eac65932bc0 100644 --- a/addons/mrp/process/procurement_process.xml +++ b/addons/mrp/process/procurement_process.xml @@ -16,7 +16,7 @@ - + @@ -26,7 +26,7 @@ - + @@ -38,7 +38,7 @@ - + @@ -50,7 +50,7 @@ - + @@ -62,7 +62,7 @@ - + @@ -74,7 +74,7 @@ - + @@ -85,7 +85,7 @@ - + @@ -118,7 +118,7 @@ Process Transition --> - + diff --git a/addons/mrp/process/service_product_process.xml b/addons/mrp/process/service_product_process.xml index 74353d02e8c..281c53c80ee 100644 --- a/addons/mrp/process/service_product_process.xml +++ b/addons/mrp/process/service_product_process.xml @@ -9,7 +9,7 @@ - + diff --git a/addons/mrp/process/stockable_product_process.xml b/addons/mrp/process/stockable_product_process.xml index c845801194b..8c07b5c6fb2 100644 --- a/addons/mrp/process/stockable_product_process.xml +++ b/addons/mrp/process/stockable_product_process.xml @@ -17,7 +17,7 @@ --> - + @@ -28,7 +28,7 @@ - + diff --git a/addons/mrp/report/mrp_report.py b/addons/mrp/report/mrp_report.py index 6ae1b2e63e5..d677184586e 100644 --- a/addons/mrp/report/mrp_report.py +++ b/addons/mrp/report/mrp_report.py @@ -71,7 +71,7 @@ class report_mrp_inout(osv.osv): create or replace view report_mrp_inout as ( select min(sm.id) as id, - to_char(sm.date_planned,'YYYY:IW') as date, + to_char(sm.date,'YYYY:IW') as date, sum(case when (sl.usage='internal') then pt.standard_price * sm.product_qty else @@ -94,7 +94,7 @@ class report_mrp_inout(osv.osv): where sm.state in ('waiting','confirmed','assigned') group by - to_char(sm.date_planned,'YYYY:IW') + to_char(sm.date,'YYYY:IW') )""") report_mrp_inout() diff --git a/addons/mrp/stock.py b/addons/mrp/stock.py index 248e39989d8..9f149dda6bd 100644 --- a/addons/mrp/stock.py +++ b/addons/mrp/stock.py @@ -79,7 +79,7 @@ class StockMove(osv.osv): proc_id = procurement_obj.create(cr, uid, { 'name': (move.picking_id.origin or ''), 'origin': (move.picking_id.origin or ''), - 'date_planned': move.date_planned, + 'date_planned': move.date, 'product_id': line['product_id'], 'product_qty': line['product_qty'], 'product_uom': line['product_uom'], diff --git a/addons/mrp_repair/test/test_mrp_repair.yml b/addons/mrp_repair/test/test_mrp_repair.yml index 7d38ab8a94d..1cf82635825 100644 --- a/addons/mrp_repair/test/test_mrp_repair.yml +++ b/addons/mrp_repair/test/test_mrp_repair.yml @@ -8,7 +8,6 @@ company_id: base.main_company date: '2010-06-24 20:10:28' date_expected: '2010-06-24 20:10:55' - date_planned: '2010-06-24 20:10:28' location_dest_id: stock.stock_location_stock location_id: stock.stock_location_stock name: '[PC1] Basic PC' diff --git a/addons/mrp_subproduct/mrp_subproduct.py b/addons/mrp_subproduct/mrp_subproduct.py index 0478b0d1779..5519bba3a5c 100644 --- a/addons/mrp_subproduct/mrp_subproduct.py +++ b/addons/mrp_subproduct/mrp_subproduct.py @@ -83,7 +83,7 @@ class mrp_production(osv.osv): qty2 *= production.product_uos_qty / (production.bom_id.product_uos_qty or 1.0) data = { 'name': 'PROD:'+production.name, - 'date_planned': production.date_planned, + 'date': production.date_planned, 'product_id': sub_product.product_id.id, 'product_qty': qty1, 'product_uom': sub_product.product_uom.id, diff --git a/addons/point_of_sale/wizard/pos_return.py b/addons/point_of_sale/wizard/pos_return.py index 96187d78ce2..99e697ea826 100644 --- a/addons/point_of_sale/wizard/pos_return.py +++ b/addons/point_of_sale/wizard/pos_return.py @@ -206,8 +206,7 @@ class pos_return(osv.osv_memory): 'product_id': line.product_id.id, 'location_dest_id': stock_dest_id, 'name': '%s (return)' %order_id.name, - 'date': date_cur, - 'date_planned': date_cur + 'date': date_cur }) if qty != 0.0: line_obj.copy(cr, uid, line.id, {'qty': -qty, 'order_id': new_order}) @@ -294,8 +293,7 @@ class add_product(osv.osv_memory): 'product_id':prod_id.id, 'location_dest_id':stock_dest_id, 'name':'%s (return)' %order_id.name, - 'date':date_cur, - 'date_planned':date_cur + 'date':date_cur }) wf_service.trg_validate(uid, 'stock.picking', new_picking, 'button_confirm', cr) @@ -371,7 +369,6 @@ class add_product(osv.osv_memory): 'location_dest_id':stock_dest_id, 'name':'%s (return)' % order_id.name, 'date':date_cur, - 'date_planned':date_cur }) wf_service.trg_validate(uid, 'stock.picking',new_picking,'button_confirm', cr) picking_obj.force_assign(cr, uid, [new_picking], context) diff --git a/addons/procurement/board_mrp_procurement_view.xml b/addons/procurement/board_mrp_procurement_view.xml index d5f71f6d4bc..3b18a876f4f 100644 --- a/addons/procurement/board_mrp_procurement_view.xml +++ b/addons/procurement/board_mrp_procurement_view.xml @@ -1,6 +1,15 @@ + + Procurement Exceptions + ir.actions.act_window + procurement.order + form + tree,form + [('state','=','exception')] + + board.mrp.procurement.form board.board @@ -8,7 +17,7 @@ form - + diff --git a/addons/procurement/process/procurement_process.xml b/addons/procurement/process/procurement_process.xml index 42ee50782a1..955d9cf6416 100644 --- a/addons/procurement/process/procurement_process.xml +++ b/addons/procurement/process/procurement_process.xml @@ -12,7 +12,7 @@ - + @@ -28,7 +28,7 @@ - + diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index 3842ac5ebd3..c8cb8f460f0 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -157,34 +157,19 @@ class procurement_order(osv.osv): """ Checks product type. @return: True or False """ - for procurement in self.browse(cr, uid, ids): - if procurement.product_id.type in ('product', 'consu'): - return True - return False + return all(procurement.product_id.type in ('product', 'consu') for procurement in self.browse(cr, uid, ids)) def check_move_cancel(self, cr, uid, ids, context={}): """ Checks if move is cancelled or not. @return: True or False. """ - res = True - ok = False - for procurement in self.browse(cr, uid, ids, context): - if procurement.move_id: - ok = True - if not procurement.move_id.state == 'cancel': - res = False - return res and ok + return all(procurement.move_id.state == 'cancel' for procurement in self.browse(cr, uid, ids)) def check_move_done(self, cr, uid, ids, context={}): """ Checks if move is done or not. @return: True or False. """ - res = True - for proc in self.browse(cr, uid, ids, context): - if proc.move_id: - if not proc.move_id.state == 'done': - res = False - return res + return all(procurement.move_id.state == 'done' for procurement in self.browse(cr, uid, ids)) # # This method may be overrided by objects that override procurement.order @@ -343,9 +328,10 @@ class procurement_order(osv.osv): 'product_id': procurement.product_id.id, 'product_qty': procurement.product_qty, 'product_uom': procurement.product_uom.id, - 'date_planned': procurement.date_planned, + 'date_expected': procurement.date_planned, 'state': 'draft', 'company_id': procurement.company_id.id, + 'auto_validate': True, }) move_obj.action_confirm(cr, uid, [id], context=context) self.write(cr, uid, [procurement.id], {'move_id': id, 'close_move': 1}) diff --git a/addons/procurement/procurement_view.xml b/addons/procurement/procurement_view.xml index 1e6395c660e..03a4c5aad82 100644 --- a/addons/procurement/procurement_view.xml +++ b/addons/procurement/procurement_view.xml @@ -23,6 +23,21 @@ + + + procurement.order.tree.board + procurement.order + tree + + + + + + + + + + procurement.order.form @@ -85,11 +100,13 @@ - - + + + + @@ -106,29 +123,29 @@ + Procurement Orders ir.actions.act_window procurement.order form - {'search_default_current':1} - {'search_default_Current':1} - The procurement order will schedule a proposal for automatic procurement for the product concerned. This procurement will start a task, a purchase order form for the supplier or a production depending on the product configuration. + {'search_default_current':1} + Procurement Orders represent the need for a certain quantity of products, at a given time, in a given location. Sale Orders are one typical source of Procurement Orders (but these are distinct documents). Depending on the procurement parameters and the products configuration, the procurement engine will attempt to satisfy the need by reserving products from stock, or ordering products from a supplier, or passing a manufacturing order, etc. - - Procurements + + Procurement Exceptions ir.actions.act_window procurement.order form tree,form + {'search_default_perm_exceptions':1} - [] - {} + Procurement Orders represent the need for a certain quantity of products, at a given time, in a given location. Sale Orders are one typical source of Procurement Orders (but these are distinct documents). Depending on the procurement parameters and the products configuration, the procurement engine will attempt to satisfy the need by reserving products from stock, or ordering products from a supplier, or passing a manufacturing order, etc. A Procurement Exception occurs when the system cannot find a way to fulfill a procurement. Some exceptions will resolve themselves automatically, but others require manual intervention (those are identified by a specific error message) - + Procurement Exceptions ir.actions.act_window @@ -136,26 +153,6 @@ form tree,form [('state','=','exception')] - For each customer order line or raw materials in a manufacturing order, there is a procurement form . In normal system use, procurement orders are automatically generated by OpenERP. But if there are configuration problems, the system can remain blocked by a procurement without generating a corresponding document. It is a procurement exception. Some problems are link to timing and will be correct automatically by the system. If there is no procurement rule, the exception must be corrected manually. - - - - Procurement Exceptions to Fix - ir.actions.act_window - procurement.order - form - tree,form - [('state','=','exception'), ('message', '<>', '')] - - - - - Temporary Procurement Exceptions - ir.actions.act_window - procurement.order - form - tree,form - [('state','=','exception'), ('message', '=', '')] @@ -263,8 +260,12 @@ res_model="stock.warehouse.orderpoint" src_model="procurement.order"/> - - - + + + + + + + diff --git a/addons/procurement/schedulers.py b/addons/procurement/schedulers.py index 777a8de45cc..06cbb86957a 100644 --- a/addons/procurement/schedulers.py +++ b/addons/procurement/schedulers.py @@ -241,7 +241,7 @@ class procurement_order(osv.osv): 'product_id': op.product_id.id, 'product_qty': qty, 'product_uom': op.product_uom.id, - 'location_id': op.warehouse_id.lot_input_id.id, + 'location_id': op.location_id.id, 'procure_method': 'make_to_order', 'origin': op.name }) diff --git a/addons/product/__init__.py b/addons/product/__init__.py index 3052a02d212..4247b49d41b 100644 --- a/addons/product/__init__.py +++ b/addons/product/__init__.py @@ -23,6 +23,5 @@ import pricelist import report import partner import wizard -import company # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/product/__openerp__.py b/addons/product/__openerp__.py index 5d099489859..851031e0424 100644 --- a/addons/product/__openerp__.py +++ b/addons/product/__openerp__.py @@ -55,7 +55,6 @@ 'product_view.xml', 'pricelist_view.xml', 'partner_view.xml', - 'company_view.xml', 'process/product_process.xml' ], 'test':['test/product_report.yml'], diff --git a/addons/product/company.py b/addons/product/company.py deleted file mode 100644 index 0f248dba309..00000000000 --- a/addons/product/company.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2009 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from osv import fields, osv - - -class res_company(osv.osv): - _inherit = 'res.company' - _columns = { - 'property_valuation_price_type': fields.property( - 'product.price.type', - type='many2one', - relation='product.price.type', - domain=[], - string="Valuation Price Type", - method=True, - view_load=True, - help="The price type field in the selected price type will be used, instead of the default one, \ - for valuation of product in the current company"), - } - -res_company() - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/product/company_view.xml b/addons/product/company_view.xml deleted file mode 100644 index eb0294e2daa..00000000000 --- a/addons/product/company_view.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - res.company.product.property.form.inherit - res.company - form - - - - - - - - - - diff --git a/addons/product/product.py b/addons/product/product.py index 09732a9bff3..22f57ac981f 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -69,15 +69,15 @@ class product_uom(osv.osv): 'name': fields.char('Name', size=64, required=True, translate=True), 'category_id': fields.many2one('product.uom.categ', 'UoM Category', required=True, ondelete='cascade', help="Quantity conversions may happen automatically between Units of Measure in the same category, according to their respective ratios."), - 'factor': fields.float('Ratio', digits=(12, 6), required=True, + 'factor': fields.float('Ratio', required=True,digits=(12, 6), help='How many times this UoM is smaller than the reference UoM in this category:\n'\ '1 * (reference unit) = ratio * (this unit)'), - 'factor_inv': fields.function(_factor_inv, digits=(12, 6), + 'factor_inv': fields.function(_factor_inv, digits_compute=dp.get_precision('Product UoM'), fnct_inv=_factor_inv_write, method=True, string='Ratio', help='How many times this UoM is bigger than the reference UoM in this category:\n'\ '1 * (this unit) = ratio * (reference unit)', required=True), - 'rounding': fields.float('Rounding Precision', digits=(16, 3), required=True, + 'rounding': fields.float('Rounding Precision', digits_compute=dp.get_precision('Product UoM'), required=True, help="The computed quantity will be a multiple of this value. "\ "Use 1.0 for a UoM that cannot be further split, such as a piece."), 'active': fields.boolean('Active', help="By unchecking the active field you can disable a unit of measure without deleting it."), diff --git a/addons/product/product_data.xml b/addons/product/product_data.xml index 2052221cf78..31e93f46d5f 100644 --- a/addons/product/product_data.xml +++ b/addons/product/product_data.xml @@ -144,12 +144,6 @@ parameter) will see those record just disappear. - - property_valuation_price_type - - - - Sale Price 2 @@ -166,6 +160,9 @@ parameter) will see those record just disappear. Stock Weight 2 - + + Product UoM + + diff --git a/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml b/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml index b08300b8d33..76762ef8c28 100644 --- a/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml +++ b/addons/project_timesheet/test/worktask_entry_to_timesheetline_entry.yml @@ -7,6 +7,8 @@ login: hr name: HR Manager password: hr + groups_id: + - base.group_hr_manager - Create a product with type service used to specify employees designation diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index eb1f2a1ace0..1522c4543f3 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -451,7 +451,7 @@ class purchase_order(osv.osv): 'product_uos_qty': order_line.product_qty, 'product_uom': order_line.product_uom.id, 'product_uos': order_line.product_uom.id, - 'date_planned': order_line.date_planned, + 'date': order_line.date_planned, 'date_expected': order_line.date_planned, 'location_id': loc_id, 'location_dest_id': dest, diff --git a/addons/purchase/stock.py b/addons/purchase/stock.py index 49a28e352b2..fb3d8f0b078 100644 --- a/addons/purchase/stock.py +++ b/addons/purchase/stock.py @@ -31,6 +31,21 @@ class stock_move(osv.osv): _defaults = { 'purchase_line_id': False } + + def _get_reference_accounting_values_for_valuation(self, cr, uid, move, context=None): + """ + Overrides the default stock valuation to take into account the currency that was specified + on the purchase order in case the valuation data was not directly specified during picking + confirmation. + """ + reference_amount, reference_currency_id = super(stock_move, self)._get_reference_accounting_values_for_valuation(cr, uid, move, context=context) + if move.product_id.cost_method != 'average' or not move.price_unit: + # no average price costing or cost not specified during picking validation, we will + # plug the purchase line values if they are found. + if move.purchase_line_id and move.picking_id.purchase_id.pricelist_id: + reference_amount, reference_currency_id = move.purchase_line_id.price_unit, move.picking_id.purchase_id.pricelist_id.currency_id.id + return reference_amount, reference_currency_id + stock_move() # @@ -86,6 +101,9 @@ class stock_picking(osv.osv): user, picking, move_line) def _invoice_line_hook(self, cursor, user, move_line, invoice_line_id): + if move_line.purchase_line_id: + invoice_line_obj = self.pool.get('account.invoice.line') + invoice_line_obj.write(cursor, user, [invoice_line_id], {'note': move_line.purchase_line_id.notes,}) return super(stock_picking, self)._invoice_line_hook(cursor, user, move_line, invoice_line_id) @@ -99,5 +117,48 @@ class stock_picking(osv.osv): stock_picking() +class stock_partial_picking(osv.osv_memory): + _inherit = 'stock.partial.picking' + + def default_get(self, cr, uid, fields, context=None): + """ To get default values for the object. + @param self: The object pointer. + @param cr: A database cursor + @param uid: ID of the user currently logged in + @param fields: List of fields for which we want default values + @param context: A standard dictionary + @return: A dictionary which of fields with values. + """ + pick_obj = self.pool.get('stock.picking') + res = super(stock_partial_picking, self).default_get(cr, uid, fields, context=context) + for pick in pick_obj.browse(cr, uid, context.get('active_ids', [])): + for m in pick.move_lines: + if (m.product_id.cost_method == 'average'): + if pick.type == 'in' and pick.purchase_id and m.purchase_line_id: + res['move%s_product_price'%(m.id)] = m.purchase_line_id.price_unit + res['move%s_product_currency'%(m.id)] = pick.purchase_id.pricelist_id.currency_id.id + return res +stock_partial_picking() + +class stock_partial_move(osv.osv_memory): + _inherit = "stock.partial.move" + def default_get(self, cr, uid, fields, context=None): + """ To get default values for the object. + @param self: The object pointer. + @param cr: A database cursor + @param uid: ID of the user currently logged in + @param fields: List of fields for which we want default values + @param context: A standard dictionary + @return: A dictionary which of fields with values. + """ + res = super(stock_partial_move, self).default_get(cr, uid, fields, context=context) + move_obj = self.pool.get('stock.move') + for m in move_obj.browse(cr, uid, context.get('active_ids', [])): + if (m.product_id.cost_method == 'average'): + if m.picking_id.type == 'in' and m.purchase_line_id and m.picking_id.purchase_id: + res['move%s_product_price'%(m.id)] = m.purchase_line_id.price_unit + res['move%s_product_currency'%(m.id)] = m.picking_id.purchase_id.pricelist_id.currency_id.id + return res +stock_partial_move() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/purchase/stock_view.xml b/addons/purchase/stock_view.xml index d5a645b4b98..a65f557a3b2 100644 --- a/addons/purchase/stock_view.xml +++ b/addons/purchase/stock_view.xml @@ -1,7 +1,17 @@ - + + stock.move.form + stock.move + form + + + + + + + Picking list stock.picking diff --git a/addons/sale/process/sale_process.xml b/addons/sale/process/sale_process.xml index 3351c265e3d..20f20a7ef72 100644 --- a/addons/sale/process/sale_process.xml +++ b/addons/sale/process/sale_process.xml @@ -63,7 +63,7 @@ - + diff --git a/addons/sale/sale.py b/addons/sale/sale.py index fe5deac13a7..ac2b1a620cf 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -712,7 +712,7 @@ class sale_order(osv.osv): 'name': line.name[:64], 'picking_id': picking_id, 'product_id': line.product_id.id, - 'date_planned': date_planned, + 'date': date_planned, 'date_expected': date_planned, 'product_qty': line.product_uom_qty, 'product_uom': line.product_uom.id, diff --git a/addons/sale/stock.py b/addons/sale/stock.py index 39260e759b4..0bb47110213 100644 --- a/addons/sale/stock.py +++ b/addons/sale/stock.py @@ -29,7 +29,25 @@ class stock_move(osv.osv): _defaults = { 'sale_line_id': False } - + + def _get_reference_accounting_values_for_valuation(self, cr, uid, move, context=None): + """ + Overrides the default stock valuation to take into account the currency that was specified + on the sale order in case the valuation data was not directly specified during picking + confirmation. + """ + reference_amount, reference_currency_id = super(stock_move, self)._get_reference_accounting_values_for_valuation(cr, uid, move, context=context) + if move.product_id.cost_method != 'average' or not move.price_unit: + # no average price costing or cost not specified during picking validation, we will + # plug the sale line values if they are found. + if move.sale_line_id and move.picking_id.sale_id.pricelist_id: + reference_amount, reference_currency_id = move.sale_line_id.price_unit, move.picking_id.sale_id.pricelist_id.currency_id.id + return reference_amount, reference_currency_id + def _create_chained_picking(self, cr, uid, pick_name,picking,ptype,move, context=None): + res=super(stock_move, self)._create_chained_picking(cr, uid, pick_name,picking,ptype,move, context=context) + if picking.sale_id: + picking_obj = self.pool.get('stock.picking').write(cr,uid,[res],{'sale_id':picking.sale_id.id}) + return res stock_move() class stock_picking(osv.osv): @@ -186,6 +204,7 @@ class stock_picking(osv.osv): 'quantity': sale_line.product_uos_qty, 'invoice_line_tax_id': [(6, 0, tax_ids)], 'account_analytic_id': account_analytic_id, + 'notes':sale_line.notes }, context=context) self.pool.get('sale.order.line').write(cursor, user, [sale_line.id], {'invoiced':True, 'invoice_lines': [(6, 0, [invoice_line_id])], @@ -208,4 +227,47 @@ class stock_picking(osv.osv): stock_picking() -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file +class stock_partial_picking(osv.osv_memory): + _inherit = 'stock.partial.picking' + + def default_get(self, cr, uid, fields, context=None): + """ To get default values for the object. + @param self: The object pointer. + @param cr: A database cursor + @param uid: ID of the user currently logged in + @param fields: List of fields for which we want default values + @param context: A standard dictionary + @return: A dictionary which of fields with values. + """ + pick_obj = self.pool.get('stock.picking') + res = super(stock_partial_picking, self).default_get(cr, uid, fields, context=context) + for pick in pick_obj.browse(cr, uid, context.get('active_ids', [])): + for m in pick.move_lines: + if (m.product_id.cost_method == 'average'): + if pick.type == 'out' and pick.sale_id and m.sale_line_id: + res['move%s_product_price'%(m.id)] = m.sale_line_id.price_unit + res['move%s_product_currency'%(m.id)] = pick.sale_id.pricelist_id.currency_id.id + return res +stock_partial_picking() + +class stock_partial_move(osv.osv_memory): + _inherit = "stock.partial.move" + def default_get(self, cr, uid, fields, context=None): + """ To get default values for the object. + @param self: The object pointer. + @param cr: A database cursor + @param uid: ID of the user currently logged in + @param fields: List of fields for which we want default values + @param context: A standard dictionary + @return: A dictionary which of fields with values. + """ + res = super(stock_partial_move, self).default_get(cr, uid, fields, context=context) + move_obj = self.pool.get('stock.move') + for m in move_obj.browse(cr, uid, context.get('active_ids', [])): + if (m.product_id.cost_method == 'average'): + if m.picking_id.type == 'out' and m.sale_line_id and m.picking_id.sale_id: + res['move%s_product_price'%(m.id)] = m.sale_line_id.price_unit + res['move%s_product_currency'%(m.id)] = m.picking_id.sale_id.pricelist_id.currency_id.id + return res +stock_partial_move() +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale/stock_view.xml b/addons/sale/stock_view.xml index 6b3c0e2c684..93529fd3b7d 100644 --- a/addons/sale/stock_view.xml +++ b/addons/sale/stock_view.xml @@ -13,6 +13,17 @@ + + stock.move.form + stock.move + form + + + + + + + diff --git a/addons/sale_journal/test/picking_journal.yml b/addons/sale_journal/test/picking_journal.yml index af4ee8ec8a0..9412c3d40d1 100644 --- a/addons/sale_journal/test/picking_journal.yml +++ b/addons/sale_journal/test/picking_journal.yml @@ -20,7 +20,7 @@ move_lines: - company_id: base.main_company date_expected: '2010-08-04 14:09:38' - date_planned: '2010-08-04 14:09:38' + date: '2010-08-04 14:09:38' location_id: stock.stock_location_stock product_id: product.product_product_24 product_qty: 50.0 @@ -84,4 +84,4 @@ - !python {model: sale_journal.picking.journal}: | pick_jour = self.browse(cr, uid, ref("sale_journal_picking_journal_pickjournal0")) - assert (pick_jour.state == 'close'), "Journal is not in the open state" \ No newline at end of file + assert (pick_jour.state == 'close'), "Journal is not in the open state" diff --git a/addons/stock/__openerp__.py b/addons/stock/__openerp__.py index 432f95242bd..79d6c860e65 100644 --- a/addons/stock/__openerp__.py +++ b/addons/stock/__openerp__.py @@ -45,11 +45,12 @@ Thanks to the double entry management, the inventory controlling is powerful and "init_xml" : [], "demo_xml" : ["stock_demo.xml"], "update_xml" : [ + "security/stock_security.xml", + "security/ir.model.access.csv", "stock_data.xml", "wizard/stock_move_view.xml", "wizard/stock_partial_picking_view.xml", "wizard/stock_partial_move_view.xml", - "wizard/stock_inventory_set_stock_zero_view.xml", "wizard/stock_fill_inventory_view.xml", "wizard/stock_invoice_onshipping_view.xml", "wizard/stock_inventory_merge_view.xml", @@ -68,10 +69,7 @@ Thanks to the double entry management, the inventory controlling is powerful and "product_view.xml", "partner_view.xml", "report/report_stock_move_view.xml", - "report/report_stock_picking_view.xml", "report/report_stock_view.xml", - "security/stock_security.xml", - "security/ir.model.access.csv", "board_warehouse_view.xml" ], 'test': ['test/stock_test.yml', diff --git a/addons/stock/board_warehouse_view.xml b/addons/stock/board_warehouse_view.xml index 8467688d994..84a24f3d0b2 100644 --- a/addons/stock/board_warehouse_view.xml +++ b/addons/stock/board_warehouse_view.xml @@ -5,30 +5,56 @@ Warehouse - - Reception Picking Stock Move + + + Incoming Product stock.move ir.actions.act_window form tree,form - [('picking_id','!=',False),('picking_id.type','=','in'),('date','<=',time.strftime('%Y-%m-%d 23:59:59'))] - + ['|','&',('picking_id','=',False),('location_id.usage', 'in', ['customer','supplier']),'&',('picking_id','!=',False),('picking_id.type','=','in')] + - + + + Outgoing Product + stock.move + ir.actions.act_window + form + tree,form + ['|','&',('picking_id','=',False),('location_dest_id.usage', 'in', ['customer','supplier']),'&',('picking_id','!=',False),('picking_id.type','=','out')] + + + + + report.stock.move + form + graph,tree + + {'search_default_month-1':1,'search_default_in':1,'group_by':['day'], 'group_by_no_leaf':1} + + + report.stock.move + form + graph,tree + + {'search_default_month-1':1,'search_default_out':1,'group_by':['day'], 'group_by_no_leaf':1} + board.warehouse.form board.board form
- + - + + - - + + @@ -43,9 +69,9 @@
- - - + + +
diff --git a/addons/stock/product.py b/addons/stock/product.py index 19b6570a31a..e1d4c71b46c 100644 --- a/addons/stock/product.py +++ b/addons/stock/product.py @@ -21,6 +21,7 @@ from osv import fields, osv from tools.translate import _ +import decimal_precision as dp class product_product(osv.osv): _inherit = "product.product" @@ -228,16 +229,25 @@ class product_product(osv.osv): results = [] results2 = [] - from_date=context.get('from_date',False) - to_date=context.get('to_date',False) - date_str=False + from_date = context.get('from_date',False) + to_date = context.get('to_date',False) + date_str = False + date_values = False + where = [tuple(location_ids),tuple(location_ids),tuple(ids),tuple(states)] if from_date and to_date: - date_str="date_planned>='%s' and date_planned<='%s'"%(from_date,to_date) + date_str = "date>=%s and date<=%s" + where.append(tuple([from_date])) + where.append(tuple([to_date])) elif from_date: - date_str="date_planned>='%s'"%(from_date) + date_str = "date>=%s" + date_values = [from_date] elif to_date: - date_str="date_planned<='%s'"%(to_date) + date_str = "date<=%s" + date_values = [to_date] + + if date_values: + where.append(tuple(date_values)) if 'in' in what: # all moves from a location out of the set to a location in the set cr.execute( @@ -247,8 +257,7 @@ class product_product(osv.osv): 'and location_dest_id IN %s'\ 'and product_id IN %s'\ 'and state IN %s' + (date_str and 'and '+date_str+' ' or '') +''\ - 'group by product_id,product_uom',(tuple(location_ids),tuple(location_ids),tuple(ids),tuple(states),) - ) + 'group by product_id,product_uom',tuple(where)) results = cr.fetchall() if 'out' in what: # all moves from a location in the set to a location out of the set @@ -259,8 +268,7 @@ class product_product(osv.osv): 'and location_dest_id NOT IN %s '\ 'and product_id IN %s'\ 'and state in %s' + (date_str and 'and '+date_str+' ' or '') + ''\ - 'group by product_id,product_uom',(tuple(location_ids),tuple(location_ids),tuple(ids),tuple(states),) - ) + 'group by product_id,product_uom',tuple(where)) results2 = cr.fetchall() uom_obj = self.pool.get('product.uom') uoms = map(lambda x: x[2], results) + map(lambda x: x[2], results2) @@ -309,16 +317,19 @@ class product_product(osv.osv): return res _columns = { - 'qty_available': fields.function(_product_available, method=True, type='float', string='Real Stock', help="Current quantities of products in selected locations or all internal if none have been selected.", multi='qty_available'), - 'virtual_available': fields.function(_product_available, method=True, type='float', string='Virtual Stock', help="Future stock for this product according to the selected locations or all internal if none have been selected. Computed as: Real Stock - Outgoing + Incoming.", multi='qty_available'), - 'incoming_qty': fields.function(_product_available, method=True, type='float', string='Incoming', help="Quantities of products that are planned to arrive in selected locations or all internal if none have been selected.", multi='qty_available'), - 'outgoing_qty': fields.function(_product_available, method=True, type='float', string='Outgoing', help="Quantities of products that are planned to leave in selected locations or all internal if none have been selected.", multi='qty_available'), + 'qty_available': fields.function(_product_available, method=True, type='float', string='Real Stock', help="Current quantities of products in selected locations or all internal if none have been selected.", multi='qty_available', digits_compute=dp.get_precision('Product UoM')), + 'virtual_available': fields.function(_product_available, method=True, type='float', string='Virtual Stock', help="Future stock for this product according to the selected locations or all internal if none have been selected. Computed as: Real Stock - Outgoing + Incoming.", multi='qty_available', digits_compute=dp.get_precision('Product UoM')), + 'incoming_qty': fields.function(_product_available, method=True, type='float', string='Incoming', help="Quantities of products that are planned to arrive in selected locations or all internal if none have been selected.", multi='qty_available', digits_compute=dp.get_precision('Product UoM')), + 'outgoing_qty': fields.function(_product_available, method=True, type='float', string='Outgoing', help="Quantities of products that are planned to leave in selected locations or all internal if none have been selected.", multi='qty_available', digits_compute=dp.get_precision('Product UoM')), 'track_production': fields.boolean('Track Manufacturing Lots' , help="Forces to specify a Production Lot for all moves containing this product and generated by a Manufacturing Order"), 'track_incoming': fields.boolean('Track Incoming Lots', help="Forces to specify a Production Lot for all moves containing this product and coming from a Supplier Location"), 'track_outgoing': fields.boolean('Track Outgoing Lots', help="Forces to specify a Production Lot for all moves containing this product and going to a Customer Location"), 'location_id': fields.dummy(string='Stock Location', relation='stock.location', type='many2one'), - 'valuation':fields.selection([('manual_periodic', 'Periodic (manual)'), - ('real_time','Real Time (automatized)'),], 'Stock Valuation', help="Decide if the system must automatically create account moves based on stock moves", required=True), + 'valuation':fields.selection([('manual_periodic', 'Periodical (manual)'), + ('real_time','Real Time (automated)'),], 'Inventory Valuation', + help="If real-time valuation is enabled for a product, the system will automatically write journal entries corresponding to stock moves." \ + "The inventory variation account set on the product category will represent the current inventory value, and the stock input and stock output account will hold the counterpart moves for incoming and outgoing products." + , required=True), } _defaults = { @@ -404,11 +415,11 @@ class product_template(osv.osv): 'property_stock_account_input': fields.property('account.account', type='many2one', relation='account.account', string='Stock Input Account', method=True, view_load=True, - help='This account will be used, instead of the default one, to value input stock'), + help='When doing real-time inventory valuation, counterpart Journal Items for all incoming stock moves will be posted in this account. If not set on the product, the one from the product category is used.'), 'property_stock_account_output': fields.property('account.account', type='many2one', relation='account.account', string='Stock Output Account', method=True, view_load=True, - help='This account will be used, instead of the default one, to value output stock'), + help='When doing real-time inventory valuation, counterpart Journal Items for all outgoing stock moves will be posted in this account. If not set on the product, the one from the product category is used.'), } product_template() @@ -420,23 +431,23 @@ class product_category(osv.osv): 'property_stock_journal': fields.property('account.journal', relation='account.journal', type='many2one', string='Stock journal', method=True, view_load=True, - help="This journal will be used for the accounting move generated by stock move"), + help="When doing real-time inventory valuation, this is the Accounting Journal in which entries will be automatically posted when stock moves are processed."), 'property_stock_account_input_categ': fields.property('account.account', type='many2one', relation='account.account', string='Stock Input Account', method=True, view_load=True, - help='This account will be used to value the input stock'), + help='When doing real-time inventory valuation, counterpart Journal Items for all incoming stock moves will be posted in this account. This is the default value for all products in this category, it can also directly be set on each product.'), 'property_stock_account_output_categ': fields.property('account.account', type='many2one', relation='account.account', string='Stock Output Account', method=True, view_load=True, - help='This account will be used to value the output stock'), + help='When doing real-time inventory valuation, counterpart Journal Items for all outgoing stock moves will be posted in this account. This is the default value for all products in this category, it can also directly be set on each product.'), 'property_stock_variation': fields.property('account.account', type='many2one', relation='account.account', string="Stock Variation Account", method=True, view_load=True, - help="This account will be used in product when valuation type is real-time valuation ",), + help="When real-time inventory valuation is enabled on a product, this account will hold the current value of the products.",), } product_category() -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/product_view.xml b/addons/stock/product_view.xml index fea019a12ab..561bb9f2206 100644 --- a/addons/stock/product_view.xml +++ b/addons/stock/product_view.xml @@ -60,10 +60,9 @@ -