diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py index f0a420f7496..066f8d1abec 100644 --- a/addons/account/account_analytic_line.py +++ b/addons/account/account_analytic_line.py @@ -107,7 +107,7 @@ class account_analytic_line(osv.osv): if journal_id: journal = analytic_journal_obj.browse(cr, uid, journal_id, context=context) if journal.type == 'sale': - product_price_type_ids = product_price_type_obj.search(cr, uid, [('field','=','list_price')], context) + product_price_type_ids = product_price_type_obj.search(cr, uid, [('field','=','list_price')], context=context) if product_price_type_ids: pricetype = product_price_type_obj.browse(cr, uid, product_price_type_ids, context=context)[0] # Take the company currency as the reference one diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index 3ca45a1dd80..302a74c27af 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -582,7 +582,7 @@ class account_move_line(osv.osv): lines = self.browse(cr, uid, ids, context=context) for l in lines: if l.account_id.type == 'view': - raise osv.except_osv(_('Error!'), _('You cannot create journal items on “View” type account %s %s.') % (l.account_id.code, l.account_id.name)) + return False return True def _check_no_closed(self, cr, uid, ids, context=None): diff --git a/addons/account_asset/account_asset.py b/addons/account_asset/account_asset.py index ac9024fd51d..0dddf441c59 100644 --- a/addons/account_asset/account_asset.py +++ b/addons/account_asset/account_asset.py @@ -386,7 +386,7 @@ class account_asset_depreciation_line(osv.osv): current_currency = line.asset_id.currency_id.id context.update({'date': depreciation_date}) amount = currency_obj.compute(cr, uid, current_currency, company_currency, line.amount, context=context) - sign = line.asset_id.category_id.journal_id.type = 'purchase' and 1 or -1 + sign = (line.asset_id.category_id.journal_id.type == 'purchase' and 1) or -1 asset_name = line.asset_id.name reference = line.name move_vals = { diff --git a/addons/account_budget/account_budget_view.xml b/addons/account_budget/account_budget_view.xml index cb0466a1c92..d24124e307d 100644 --- a/addons/account_budget/account_budget_view.xml +++ b/addons/account_budget/account_budget_view.xml @@ -220,7 +220,18 @@ - + + + account.budget.line.search + crossovered.budget.lines + search + + + + + + + crossovered.budget.line.tree crossovered.budget.lines diff --git a/addons/base_iban/base_iban.py b/addons/base_iban/base_iban.py index c29647a1176..ff492a8d34b 100644 --- a/addons/base_iban/base_iban.py +++ b/addons/base_iban/base_iban.py @@ -99,6 +99,8 @@ class res_partner_bank(osv.osv): @param iban: IBAN as string @return: True if IBAN is valid, False otherwise """ + if not iban: + return False iban = _format_iban(iban).lower() if iban[:2] in _ref_iban and len(iban) != len(_format_iban(_ref_iban[iban[:2]])): return False @@ -128,9 +130,9 @@ class res_partner_bank(osv.osv): def _construct_constraint_msg(self, cr, uid, ids, context=None): def default_iban_check(iban_cn): - return iban_cn[0] in string.ascii_lowercase and iban_cn[1] in string.ascii_lowercase + return iban_cn and iban_cn[0] in string.ascii_lowercase and iban_cn[1] in string.ascii_lowercase - iban_country = self.browse(cr, uid, ids)[0].acc_number[:2].lower() + iban_country = self.browse(cr, uid, ids)[0].acc_number and self.browse(cr, uid, ids)[0].acc_number[:2].lower() if default_iban_check(iban_country): if iban_country in _ref_iban: return _('The IBAN does not seem to be correct. You should have entered something like this %s'), \ diff --git a/addons/crm/crm_action_rule.py b/addons/crm/crm_action_rule.py index 910a1fca169..4a8ee98fbae 100644 --- a/addons/crm/crm_action_rule.py +++ b/addons/crm/crm_action_rule.py @@ -79,7 +79,7 @@ class base_action_rule(osv.osv): write['section_id'] = action.act_section_id.id if hasattr(action, 'act_categ_id') and action.act_categ_id: - write['categ_ids'] = [4, action.act_categ_id.id] + write['categ_ids'] = [(4, action.act_categ_id.id)] model_obj.write(cr, uid, [obj.id], write, context) return res diff --git a/addons/document_ftp/ftpserver/abstracted_fs.py b/addons/document_ftp/ftpserver/abstracted_fs.py index dbda715f614..326c62f7a92 100644 --- a/addons/document_ftp/ftpserver/abstracted_fs.py +++ b/addons/document_ftp/ftpserver/abstracted_fs.py @@ -272,7 +272,7 @@ class abstracted_fs(object): if path.startswith('/'): path = path[1:] - p_parts = path.split('/') # hard-code the unix sep here, by spec. + p_parts = path.split(os.sep) assert '..' not in p_parts diff --git a/addons/hr_expense/hr_expense.py b/addons/hr_expense/hr_expense.py index 96a37c0e448..ccb8af68e21 100644 --- a/addons/hr_expense/hr_expense.py +++ b/addons/hr_expense/hr_expense.py @@ -64,22 +64,22 @@ class hr_expense_expense(osv.osv): _description = "Expense" _order = "id desc" _columns = { - 'name': fields.char('Description', size=128), + 'name': fields.char('Description', size=128, required=True, readonly=True, states={'draft':[('readonly',False)], 'confirm':[('readonly',False)]}), 'id': fields.integer('Sheet ID', readonly=True), - 'date': fields.date('Date', select=True), + 'date': fields.date('Date', select=True, readonly=True, states={'draft':[('readonly',False)], 'confirm':[('readonly',False)]}), 'journal_id': fields.many2one('account.journal', 'Force Journal', help = "The journal used when the expense is done."), - 'employee_id': fields.many2one('hr.employee', "Employee", required=True), + 'employee_id': fields.many2one('hr.employee', "Employee", required=True, readonly=True, states={'draft':[('readonly',False)], 'confirm':[('readonly',False)]}), 'user_id': fields.many2one('res.users', 'User', required=True), 'date_confirm': fields.date('Confirmation Date', select=True, help="Date of the confirmation of the sheet expense. It's filled when the button Confirm is pressed."), 'date_valid': fields.date('Validation Date', select=True, help="Date of the acceptation of the sheet expense. It's filled when the button Accept is pressed."), - 'user_valid': fields.many2one('res.users', 'Validation By'), + 'user_valid': fields.many2one('res.users', 'Validation By', readonly=True, states={'draft':[('readonly',False)], 'confirm':[('readonly',False)]}), 'account_move_id': fields.many2one('account.move', 'Ledger Posting'), 'line_ids': fields.one2many('hr.expense.line', 'expense_id', 'Expense Lines', readonly=True, states={'draft':[('readonly',False)]} ), 'note': fields.text('Note'), 'amount': fields.function(_amount, string='Total Amount', digits_compute= dp.get_precision('Account')), 'voucher_id': fields.many2one('account.voucher', "Employee's Receipt"), - 'currency_id': fields.many2one('res.currency', 'Currency', required=True), - 'department_id':fields.many2one('hr.department','Department'), + 'currency_id': fields.many2one('res.currency', 'Currency', required=True, readonly=True, states={'draft':[('readonly',False)], 'confirm':[('readonly',False)]}), + 'department_id':fields.many2one('hr.department','Department', readonly=True, states={'draft':[('readonly',False)], 'confirm':[('readonly',False)]}), 'company_id': fields.many2one('res.company', 'Company', required=True), 'state': fields.selection([ ('draft', 'New'), @@ -100,6 +100,12 @@ class hr_expense_expense(osv.osv): 'currency_id': _get_currency, } + def unlink(self, cr, uid, ids, context=None): + for rec in self.browse(cr, uid, ids, context=context): + if rec.state != 'draft': + raise osv.except_osv(_('Warning!'),_('You can only delete draft expenses!')) + return super(hr_expense_expense, self).unlink(cr, uid, ids, context) + def onchange_currency_id(self, cr, uid, ids, currency_id=False, company_id=False, context=None): res = {'value': {'journal_id': False}} journal_ids = self.pool.get('account.journal').search(cr, uid, [('type','=','purchase'), ('currency','=',currency_id), ('company_id', '=', company_id)], context=context) diff --git a/addons/hr_payroll/hr_payroll.py b/addons/hr_payroll/hr_payroll.py index 640d4ed3cfd..c0e4bc39321 100644 --- a/addons/hr_payroll/hr_payroll.py +++ b/addons/hr_payroll/hr_payroll.py @@ -359,6 +359,12 @@ class hr_payslip(osv.osv): def check_done(self, cr, uid, ids, context=None): return True + def unlink(self, cr, uid, ids, context=None): + for payslip in self.browse(cr, uid, ids, context=context): + if payslip.state not in ['draft','cancel']: + raise osv.except_osv(_('Warning!'),_('You cannot delete a payslip which is not draft or cancelled!')) + return super(hr_payslip, self).unlink(cr, uid, ids, context) + #TODO move this function into hr_contract module, on hr.employee object def get_contract(self, cr, uid, employee, date_from, date_to, context=None): """ diff --git a/addons/hr_payroll/hr_payroll_demo.xml b/addons/hr_payroll/hr_payroll_demo.xml index 836814860c1..a22809b00e3 100644 --- a/addons/hr_payroll/hr_payroll_demo.xml +++ b/addons/hr_payroll/hr_payroll_demo.xml @@ -75,7 +75,7 @@ fix - worked_days.WORK100.number_of_days + worked_days.WORK100 and worked_days.WORK100.number_of_days MA @@ -89,7 +89,7 @@ Get 1% of sales - result = (inputs.SALEURO.amount + inputs.SALASIA.amount) * 0.01 + result = ((inputs.SALEURO and inputs.SALEURO.amount) + (inputs.SALASIA and inputs.SALASIA.amount)) * 0.01 diff --git a/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py b/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py index d15b300597e..53948945e04 100644 --- a/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py +++ b/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py @@ -65,6 +65,8 @@ class partner_vat(osv.osv_memory): partners = [] partner_ids = obj_partner.search(cr, uid, [('vat_subjected', '!=', False), ('vat','ilike','BE%')], context=context) + if not partner_ids: + raise osv.except_osv(_('Error'),_('No belgian contact with a VAT number in your database.')) cr.execute("""SELECT sub1.partner_id, sub1.name, sub1.vat, sub1.turnover, sub2.vat_amount FROM (SELECT l.partner_id, p.name, p.vat, SUM(CASE WHEN c.code ='49' THEN -l.tax_amount ELSE l.tax_amount END) as turnover FROM account_move_line l @@ -190,7 +192,7 @@ class partner_vat_list(osv.osv_memory): addr = obj_partner.address_get(cr, uid, [obj_cmpny.partner_id.id], ['invoice']) if addr.get('invoice',False): ads = obj_partner.browse(cr, uid, [addr['invoice']], context=context)[0] - phone = ads.phone.replace(' ','') or '' + phone = ads.phone and ads.phone.replace(' ','') or '' email = ads.email or '' name = ads.name or '' city = ads.city or '' @@ -259,6 +261,8 @@ class partner_vat_list(osv.osv_memory): # Turnover and Farmer tags are not included client_datas = self._get_datas(cr, uid, ids, context=context) + if not client_datas: + raise osv.except_osv(_('Data Insufficient!'),_('No data available for the client.')) data_client_info = '' for amount_data in client_datas: data_client_info += """ @@ -309,6 +313,8 @@ class partner_vat_list(osv.osv_memory): datas['year'] = context['year'] datas['limit_amount'] = context['limit_amount'] datas['client_datas'] = self._get_datas(cr, uid, ids, context=context) + if not datas['client_datas']: + raise osv.except_osv(_('Error!'),_('No record to print.')) return { 'type': 'ir.actions.report.xml', 'report_name': 'partner.vat.listing.print', diff --git a/addons/l10n_fr/fr_tax.xml b/addons/l10n_fr/fr_tax.xml index fc5d4608f45..36c5feb47b6 100644 --- a/addons/l10n_fr/fr_tax.xml +++ b/addons/l10n_fr/fr_tax.xml @@ -131,8 +131,8 @@ - - + + diff --git a/addons/l10n_fr/plan_comptable_general.xml b/addons/l10n_fr/plan_comptable_general.xml index 525dabfcc8a..268f4bd6336 100644 --- a/addons/l10n_fr/plan_comptable_general.xml +++ b/addons/l10n_fr/plan_comptable_general.xml @@ -3903,7 +3903,7 @@ Associés - Comptes courants 455 view - + Pour frais avancés personnellement @@ -3912,8 +3912,8 @@ Principal 4551 - receivable - + payable + @@ -3921,8 +3921,8 @@ Intérêts courus 4558 - receivable - + payable + diff --git a/addons/point_of_sale/wizard/pos_payment.py b/addons/point_of_sale/wizard/pos_payment.py index 9511aed6331..70b88f35e33 100644 --- a/addons/point_of_sale/wizard/pos_payment.py +++ b/addons/point_of_sale/wizard/pos_payment.py @@ -75,7 +75,7 @@ class pos_make_payment(osv.osv_memory): def launch_payment(self, cr, uid, ids, context=None): return { - 'name': _('Paiement'), + 'name': _('Payment'), 'view_type': 'form', 'view_mode': 'form', 'res_model': 'pos.make.payment', @@ -83,6 +83,7 @@ class pos_make_payment(osv.osv_memory): 'target': 'new', 'views': False, 'type': 'ir.actions.act_window', + 'context': context, } def print_report(self, cr, uid, ids, context=None): diff --git a/addons/product/product.py b/addons/product/product.py index b6a58fcd1e8..27cd4249a60 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -657,9 +657,9 @@ class product_product(osv.osv): # Performing a quick memory merge of ids in Python will give much better performance ids = set() ids.update(self.search(cr, user, args + [('default_code',operator,name)], limit=limit, context=context)) - if len(ids) < limit: + if not limit or len(ids) < limit: # we may underrun the limit because of dupes in the results, that's fine - ids.update(self.search(cr, user, args + [('name',operator,name)], limit=(limit-len(ids)), context=context)) + ids.update(self.search(cr, user, args + [('name',operator,name)], limit=(limit and (limit-len(ids)) or False) , context=context)) ids = list(ids) if not ids: ptrn = re.compile('(\[(.*?)\])') diff --git a/addons/product_expiry/product_expiry.py b/addons/product_expiry/product_expiry.py index c16ccc2b1ee..e4ed28db4e6 100644 --- a/addons/product_expiry/product_expiry.py +++ b/addons/product_expiry/product_expiry.py @@ -45,12 +45,13 @@ class stock_production_lot(osv.osv): _columns = { 'life_date': fields.datetime('End of Life Date', - help='The date on which the lot may become dangerous and should not be consumed.'), + help='This is the date on which the goods with this Serial Number may become dangerous and must not be consumed.'), 'use_date': fields.datetime('Best before Date', - help='The date on which the lot starts deteriorating without becoming dangerous.'), + help='This is the date on which the goods with this Serial Number start deteriorating, without being dangerous yet.'), 'removal_date': fields.datetime('Removal Date', - help='The date on which the lot should be removed.'), - 'alert_date': fields.datetime('Alert Date', help="The date on which an alert should be notified about the serial number."), + help='This is the date on which the goods with this Serial Number should be removed from the stock.'), + 'alert_date': fields.datetime('Alert Date', + help="This is the date on which an alert should be notified about the goods with this Serial Number."), } # Assign dates according to products data def create(self, cr, uid, vals, context=None): @@ -78,12 +79,13 @@ class product_product(osv.osv): _inherit = 'product.product' _columns = { 'life_time': fields.integer('Product Life Time', - help='The number of days before a serial number may become dangerous and should not be consumed.'), + help='When a new a Serial Number is issued, this is the number of days before the goods may become dangerous and must not be consumed.'), 'use_time': fields.integer('Product Use Time', - help='The number of days before a serial number starts deteriorating without becoming dangerous.'), + help='When a new a Serial Number is issued, this is the number of days before the goods starts deteriorating, without being dangerous yet.'), 'removal_time': fields.integer('Product Removal Time', - help='The number of days before a serial number should be removed.'), - 'alert_time': fields.integer('Product Alert Time', help="The number of days after which an alert should be notified about the serial number."), + help='When a new a Serial Number is issued, this is the number of days before the goods should be removed from the stock.'), + 'alert_time': fields.integer('Product Alert Time', + help='When a new a Serial Number is issued, this is the number of days before an alert should be notified.'), } product_product() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project/project.py b/addons/project/project.py index 42df632851a..9c28fadeab9 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -474,7 +474,7 @@ def Project(): resource = %s """ % ( project.id, - project.date_start, working_days, + project.date_start or time.strftime('%Y-%m-%d'), working_days, '|'.join(['User_'+str(x) for x in puids]) ) vacation = calendar_id and tuple(resource_pool.compute_vacation(cr, uid, calendar_id, context=context)) or False diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 5fe84c34bc3..c1af024ad9c 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -281,6 +281,7 @@ class sale_order(osv.osv): } def onchange_pricelist_id(self, cr, uid, ids, pricelist_id, order_lines, context=None): + context = context or {} if not pricelist_id: return {} value = { @@ -617,6 +618,7 @@ class sale_order(osv.osv): } def action_wait(self, cr, uid, ids, context=None): + context = context or {} for o in self.browse(cr, uid, ids): if not o.order_line: raise osv.except_osv(_('Error!'),_('You cannot confirm a sale order which has no line.')) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index ee8d57a50c7..d18a55ea49a 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1553,7 +1553,7 @@ class stock_production_lot(osv.osv): 'product_id': lambda x, y, z, c: c.get('product_id', False), } _sql_constraints = [ - ('name_ref_uniq', 'unique (name, ref)', 'The combination of serial number and internal reference must be unique !'), + ('name_ref_uniq', 'unique (name, ref)', 'The combination of Serial Number and internal reference must be unique !'), ] def action_traceability(self, cr, uid, ids, context=None): """ It traces the information of a product @@ -2433,14 +2433,17 @@ class stock_move(osv.osv): if move.picking_id: picking_ids.append(move.picking_id.id) if move.move_dest_id.id and (move.state != 'done'): - self.write(cr, uid, [move.id], {'move_history_ids': [(4, move.move_dest_id.id)]}) - #cr.execute('insert into stock_move_history_ids (parent_id,child_id) values (%s,%s)', (move.id, move.move_dest_id.id)) - if move.move_dest_id.state in ('waiting', 'confirmed'): - self.force_assign(cr, uid, [move.move_dest_id.id], context=context) - if move.move_dest_id.picking_id: - wf_service.trg_write(uid, 'stock.picking', move.move_dest_id.picking_id.id, cr) - if move.move_dest_id.auto_validate: - self.action_done(cr, uid, [move.move_dest_id.id], context=context) + # Downstream move should only be triggered if this move is the last pending upstream move + other_upstream_move_ids = self.search(cr, uid, [('id','!=',move.id),('state','not in',['done','cancel']), + ('move_dest_id','=',move.move_dest_id.id)], context=context) + if not other_upstream_move_ids: + self.write(cr, uid, [move.id], {'move_history_ids': [(4, move.move_dest_id.id)]}) + if move.move_dest_id.state in ('waiting', 'confirmed'): + self.force_assign(cr, uid, [move.move_dest_id.id], context=context) + if move.move_dest_id.picking_id: + wf_service.trg_write(uid, 'stock.picking', move.move_dest_id.picking_id.id, cr) + if move.move_dest_id.auto_validate: + self.action_done(cr, uid, [move.move_dest_id.id], context=context) self._create_product_valuation_moves(cr, uid, move, context=context) if move.state not in ('confirmed','done','assigned'):