diff --git a/addons/account/account.py b/addons/account/account.py index e11479e4dc0..e5e29f178a3 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -111,7 +111,7 @@ class account_payment_term_line(osv.osv): 'days': fields.integer('Number of Days', required=True, help="Number of days to add before computation of the day of month." \ "If Date=15/01, Number of Days=22, Day of Month=-1, then the due date is 28/02."), 'days2': fields.integer('Day of the Month', required=True, help="Day of the month, set -1 for the last day of the current month. If it's positive, it gives the day of the next month. Set 0 for net days (otherwise it's based on the beginning of the month)."), - 'payment_id': fields.many2one('account.payment.term', 'Payment Term', required=True, select=True), + 'payment_id': fields.many2one('account.payment.term', 'Payment Term', required=True, select=True, ondelete='cascade'), } _defaults = { 'value': 'balance', @@ -1375,7 +1375,7 @@ class account_move(osv.osv): balance = 0.0 for line in line_ids: if line[2]: - balance += (line[2]['debit'] or 0.00)- (line[2]['credit'] or 0.00) + balance += (line[2].get('debit',0.00)- (line[2].get('credit',0.00))) return {'value': {'balance': balance}} def write(self, cr, uid, ids, vals, context=None): @@ -1398,7 +1398,7 @@ class account_move(osv.osv): if not l[0]: l[2].update({ 'reconcile_id':False, - 'reconcil_partial_id':False, + 'reconcile_partial_id':False, 'analytic_lines':False, 'invoice':False, 'ref':False, @@ -2516,22 +2516,25 @@ class account_account_template(osv.osv): 'nocreate': False, } - def _check_type(self, cr, uid, ids, context=None): - if context is None: - context = {} - accounts = self.browse(cr, uid, ids, context=context) - for account in accounts: - if account.parent_id and account.parent_id.type != 'view': - return False - return True - _check_recursion = check_cycle _constraints = [ (_check_recursion, 'Error!\nYou cannot create recursive account templates.', ['parent_id']), - (_check_type, 'Configuration Error!\nYou cannot define children to an account that has internal type other than "View".', ['type']), - ] + def create(self, cr, uid, vals, context=None): + if 'parent_id' in vals: + parent = self.read(cr, uid, [vals['parent_id']], ['type']) + if parent and parent[0]['type'] != 'view': + raise osv.except_osv(_('Warning!'), _("You may only select a parent account of type 'View'.")) + return super(account_account_template, self).create(cr, uid, vals, context=context) + + def write(self, cr, uid, ids, vals, context=None): + if 'parent_id' in vals: + parent = self.read(cr, uid, [vals['parent_id']], ['type']) + if parent and parent[0]['type'] != 'view': + raise osv.except_osv(_('Warning!'), _("You may only select a parent account of type 'View'.")) + return super(account_account_template, self).write(cr, uid, ids, vals, context=context) + def name_get(self, cr, uid, ids, context=None): if not ids: return [] @@ -2999,6 +3002,7 @@ class wizard_multi_charts_accounts(osv.osv_memory): _columns = { 'company_id':fields.many2one('res.company', 'Company', required=True), + 'currency_id': fields.many2one('res.currency', 'Currency', help="Currency as per company's country."), 'only_one_chart_template': fields.boolean('Only One Chart Template Available'), 'chart_template_id': fields.many2one('account.chart.template', 'Chart Template', required=True), 'bank_accounts_id': fields.one2many('account.bank.accounts.wizard', 'bank_account_id', 'Cash and Banks', required=True), @@ -3009,6 +3013,13 @@ class wizard_multi_charts_accounts(osv.osv_memory): 'purchase_tax_rate': fields.float('Purchase Tax(%)'), 'complete_tax_set': fields.boolean('Complete Set of Taxes', help='This boolean helps you to choose if you want to propose to the user to encode the sales and purchase rates or use the usual m2o fields. This last choice assumes that the set of tax defined for the chosen template is complete'), } + + def onchange_company_id(self, cr, uid, ids, company_id, context=None): + currency_id = False + if company_id: + currency_id = self.pool.get('res.company').browse(cr, uid, company_id, context=context).currency_id.id + return {'value': {'currency_id': currency_id}} + def onchange_tax_rate(self, cr, uid, ids, rate=False, context=None): return {'value': {'purchase_tax_rate': rate or False}} @@ -3039,6 +3050,13 @@ class wizard_multi_charts_accounts(osv.osv_memory): res.update({'bank_accounts_id': [{'acc_name': _('Cash'), 'account_type': 'cash'},{'acc_name': _('Bank'), 'account_type': 'bank'}]}) if 'company_id' in fields: res.update({'company_id': self.pool.get('res.users').browse(cr, uid, [uid], context=context)[0].company_id.id}) + if 'currency_id' in fields: + company_id = res.get('company_id') or False + if company_id: + company_obj = self.pool.get('res.company') + country_id = company_obj.browse(cr, uid, company_id, context=context).country_id.id + currency_id = company_obj.on_change_country(cr, uid, company_id, country_id, context=context)['value']['currency_id'] + res.update({'currency_id': currency_id}) ids = self.pool.get('account.chart.template').search(cr, uid, [('visible', '=', True)], context=context) if ids: @@ -3343,6 +3361,7 @@ class wizard_multi_charts_accounts(osv.osv_memory): ir_values_obj = self.pool.get('ir.values') obj_wizard = self.browse(cr, uid, ids[0]) company_id = obj_wizard.company_id.id + self.pool.get('res.company').write(cr, uid, [company_id], {'currency_id': obj_wizard.currency_id.id}) # If the floats for sale/purchase rates have been filled, create templates from them self._create_tax_templates_from_rates(cr, uid, obj_wizard, company_id, context=context) diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index 8df291a98d1..095d461ff3b 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -430,7 +430,7 @@ class account_bank_statement(osv.osv): 'name': st_number, 'balance_end_real': st.balance_end }, context=context) - self.message_append_note(cr, uid, [st.id], body=_('Statement %s is confirmed, journal items are created.') % (st_number,), context=context) + self.message_post(cr, uid, [st.id], body=_('Statement %s confirmed, journal items were created.') % (st_number,), context=context) return self.write(cr, uid, ids, {'state':'confirm'}, context=context) def button_cancel(self, cr, uid, ids, context=None): diff --git a/addons/account/account_bank_view.xml b/addons/account/account_bank_view.xml index 8ceb8a91885..ef793a1bef5 100644 --- a/addons/account/account_bank_view.xml +++ b/addons/account/account_bank_view.xml @@ -15,7 +15,7 @@ - + @@ -28,7 +28,7 @@ - + diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index 7bc9ceaaf61..19af105c950 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -214,7 +214,7 @@ class account_invoice(osv.osv): \n* The \'Cancelled\' state is used when user cancel invoice.'), 'sent': fields.boolean('Sent', readonly=True, help="It indicates that the invoice has been sent."), 'date_invoice': fields.date('Invoice Date', readonly=True, states={'draft':[('readonly',False)]}, select=True, help="Keep empty to use the current date"), - 'date_due': fields.date('Due Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]}, select=True, + 'date_due': fields.date('Due Date', readonly=True, states={'draft':[('readonly',False)]}, select=True, help="If you use payment terms, the due date will be computed automatically at the generation "\ "of accounting entries. If you keep the payment term and the due date empty, it means direct payment. The payment term may compute several due dates, for example 50% now, 50% in one month."), 'partner_id': fields.many2one('res.partner', 'Partner', change_default=True, readonly=True, required=True, states={'draft':[('readonly',False)]}), @@ -253,7 +253,7 @@ class account_invoice(osv.osv): 'currency_id': fields.many2one('res.currency', 'Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}), 'journal_id': fields.many2one('account.journal', 'Journal', required=True, readonly=True, states={'draft':[('readonly',False)]}), 'company_id': fields.many2one('res.company', 'Company', required=True, change_default=True, readonly=True, states={'draft':[('readonly',False)]}), - 'check_total': fields.float('Verification Total', digits_compute=dp.get_precision('Account'), states={'open':[('readonly',True)],'close':[('readonly',True)]}), + 'check_total': fields.float('Verification Total', digits_compute=dp.get_precision('Account'), readonly=True, states={'draft':[('readonly',False)]}), 'reconciled': fields.function(_reconciled, string='Paid/Reconciled', type='boolean', store={ 'account.invoice': (lambda self, cr, uid, ids, c={}: ids, None, 50), # Check if we can remove ? @@ -767,17 +767,20 @@ class account_invoice(osv.osv): if not key in tax_key: raise osv.except_osv(_('Warning!'), _('Taxes are missing!\nClick on compute button.')) - def compute_invoice_totals(self, cr, uid, inv, company_currency, ref, invoice_move_lines): + def compute_invoice_totals(self, cr, uid, inv, company_currency, ref, invoice_move_lines, context=None): + if context is None: + context={} total = 0 total_currency = 0 cur_obj = self.pool.get('res.currency') for i in invoice_move_lines: if inv.currency_id.id != company_currency: + context.update({'date': inv.date_invoice or time.strftime('%Y-%m-%d')}) i['currency_id'] = inv.currency_id.id i['amount_currency'] = i['price'] i['price'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, i['price'], - context={'date': inv.date_invoice or time.strftime('%Y-%m-%d')}) + context=context) else: i['amount_currency'] = False i['currency_id'] = False @@ -887,7 +890,7 @@ class account_invoice(osv.osv): # create one move line for the total and possibly adjust the other lines amount total = 0 total_currency = 0 - total, total_currency, iml = self.compute_invoice_totals(cr, uid, inv, company_currency, ref, iml) + total, total_currency, iml = self.compute_invoice_totals(cr, uid, inv, company_currency, ref, iml, context=ctx) acc_id = inv.account_id.id name = inv['name'] or '/' @@ -1045,7 +1048,7 @@ class account_invoice(osv.osv): if obj_inv.type in ('out_invoice', 'out_refund'): ctx = self.get_log_context(cr, uid, context=ctx) message = _("Invoice '%s' is validated.") % name - self.message_append_note(cr, uid, [inv_id], body=message, context=context) + self.message_post(cr, uid, [inv_id], body=message, context=context) return True def action_cancel(self, cr, uid, ids, *args): @@ -1275,7 +1278,7 @@ class account_invoice(osv.osv): # TODO: use currency's formatting function msg = _("Invoice '%s' is paid partially: %s%s of %s%s (%s%s remaining).") % \ (name, pay_amount, code, invoice.amount_total, code, total, code) - self.message_append_note(cr, uid, [inv_id], body=msg, context=context) + self.message_post(cr, uid, [inv_id], body=msg, context=context) self.pool.get('account.move.line').reconcile_partial(cr, uid, line_ids, 'manual', context) # Update the stored value (fields.function), so we write to trigger recompute @@ -1288,24 +1291,25 @@ class account_invoice(osv.osv): def _get_document_type(self, type): type_dict = { - 'out_invoice': 'Customer invoice', - 'in_invoice': 'Supplier invoice', - 'out_refund': 'Customer Refund', - 'in_refund': 'Supplier Refund', + # Translation markers will have no effect at runtime, only used to properly flag export + 'out_invoice': _('Customer invoice'), + 'in_invoice': _('Supplier invoice'), + 'out_refund': _('Customer Refund'), + 'in_refund': _('Supplier Refund'), } return type_dict.get(type, 'Invoice') def create_send_note(self, cr, uid, ids, context=None): for obj in self.browse(cr, uid, ids, context=context): - self.message_append_note(cr, uid, [obj.id],body=_("%s created.") % (self._get_document_type(obj.type)), context=context) + self.message_post(cr, uid, [obj.id], body=_("%s created.") % (_(self._get_document_type(obj.type))), context=context) def confirm_paid_send_note(self, cr, uid, ids, context=None): - for obj in self.browse(cr, uid, ids, context=context): - self.message_append_note(cr, uid, [obj.id], body=_("%s paid.") % (self._get_document_type(obj.type)), context=context) + for obj in self.browse(cr, uid, ids, context=context): + self.message_post(cr, uid, [obj.id], body=_("%s paid.") % (_(self._get_document_type(obj.type))), context=context) def invoice_cancel_send_note(self, cr, uid, ids, context=None): for obj in self.browse(cr, uid, ids, context=context): - self.message_append_note(cr, uid, [obj.id], body=_("%s cancelled.") % (self._get_document_type(obj.type)), context=context) + self.message_post(cr, uid, [obj.id], body=_("%s cancelled.") % (_(self._get_document_type(obj.type))), context=context) account_invoice() @@ -1361,10 +1365,16 @@ class account_invoice_line(osv.osv): 'company_id': fields.related('invoice_id','company_id',type='many2one',relation='res.company',string='Company', store=True, readonly=True), 'partner_id': fields.related('invoice_id','partner_id',type='many2one',relation='res.partner',string='Partner',store=True) } + + def _default_account_id(self, cr, uid, ids, context=None): + prop = self.pool.get('ir.property').get(cr, uid, 'property_account_income_categ', 'product.category', context=context) + return prop and prop.id or False + _defaults = { 'quantity': 1, 'discount': 0.0, 'price_unit': _price_unit_default, + 'account_id': _default_account_id, } def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): @@ -1473,10 +1483,11 @@ class account_invoice_line(osv.osv): prod = self.pool.get('product.product').browse(cr, uid, product, context=context) prod_uom = self.pool.get('product.uom').browse(cr, uid, uom, context=context) if prod.uom_id.category_id.id != prod_uom.category_id.id: - warning = { + warning = { 'title': _('Warning!'), 'message': _('The selected unit of measure is not compatible with the unit of measure of the product.') - } + } + res['value'].update({'uos_id': prod.uom_id.id}) return {'value': res['value'], 'warning': warning} return res diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml index 143c5514141..1c4d83106ca 100644 --- a/addons/account/account_invoice_view.xml +++ b/addons/account/account_invoice_view.xml @@ -127,7 +127,7 @@ - + @@ -184,24 +184,30 @@ name="account_id" groups="account.group_account_user"/> - + - - - - + + + + + + + + - - - - @@ -265,7 +271,7 @@ - + @@ -326,8 +332,8 @@ - - '%(object.user_id.email) or ''} - -You can view the invoice document, download it and pay online using the following link: - ${ctx.get('edi_web_url_view') or 'n/a'} - -% if object.company_id.paypal_account and object.type in ('out_invoice', 'in_refund'): -<% -comp_name = quote(object.company_id.name) -inv_number = quote(object.number) -paypal_account = quote(object.company_id.paypal_account) -inv_amount = quote(str(object.amount_total)) -cur_name = quote(object.currency_id.name) -paypal_url = "https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=%s&item_name=%s%%20Invoice%%20%s"\ - "&invoice=%s&amount=%s¤cy_code=%s&button_subtype=services&no_note=1&bn=OpenERP_Invoice_PayNow_%s" % \ - (paypal_account,comp_name,inv_number,inv_number,inv_amount,cur_name,cur_name) -%> -It is also possible to directly pay with Paypal: - ${paypal_url} -% endif - -If you have any question, do not hesitate to contact us. - - -Thank you for choosing ${object.company_id.name}! - - --- -${object.user_id.name} ${object.user_id.email and '<%s>'%(object.user_id.email) or ''} -${object.company_id.name} -% if object.company_id.street: -${object.company_id.street or ''} -% endif -% if object.company_id.street2: -${object.company_id.street2} -% endif -% if object.company_id.city or object.company_id.zip: -${object.company_id.zip or ''} ${object.company_id.city or ''} -% endif -% if object.company_id.country_id: -${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''} -% endif -% if object.company_id.phone: -Phone: ${object.company_id.phone} -% endif -% if object.company_id.website: -${object.company_id.website or ''} -% endif - ]]> diff --git a/addons/account/i18n/account.pot b/addons/account/i18n/account.pot index 174002a8d8d..0d5439719e2 100644 --- a/addons/account/i18n/account.pot +++ b/addons/account/i18n/account.pot @@ -9538,7 +9538,7 @@ msgid "Refund" msgstr "" #. module: account -#: model:email.template,body_text:account.email_template_edi_invoice +#: model:email.template,body:account.email_template_edi_invoice msgid "\n" "Hello${object.address_invoice_id.name and ' ' or ''}${object.address_invoice_id.name or ''},\n" "\n" diff --git a/addons/account/project/project_view.xml b/addons/account/project/project_view.xml index e3b902a000f..da1a11b9cb6 100644 --- a/addons/account/project/project_view.xml +++ b/addons/account/project/project_view.xml @@ -56,7 +56,7 @@ - + @@ -137,8 +137,8 @@ -