[MERGE] forward port of branch saas-3 up to 8c4a7cb
authorDenis Ledoux <dle@odoo.com>
Tue, 4 Nov 2014 11:30:01 +0000 (12:30 +0100)
committerDenis Ledoux <dle@odoo.com>
Tue, 4 Nov 2014 11:30:01 +0000 (12:30 +0100)
1  2 
.gitignore
addons/account/account_invoice.py
addons/base_action_rule/base_action_rule.py
addons/marketing_campaign/marketing_campaign_view.xml
addons/payment_paypal/models/paypal.py
addons/product/product.py
addons/project_issue/project_issue.py
addons/web/static/src/js/view_form.js

diff --cc .gitignore
Simple merge
@@@ -707,54 -847,56 +707,54 @@@ class account_invoice(models.Model)
          """
          return move_lines
  
 -    def check_tax_lines(self, cr, uid, inv, compute_taxes, ait_obj):
 -        company_currency = self.pool['res.company'].browse(cr, uid, inv.company_id.id).currency_id
 -        if not inv.tax_line:
 +    @api.multi
 +    def check_tax_lines(self, compute_taxes):
 +        account_invoice_tax = self.env['account.invoice.tax']
 +        company_currency = self.company_id.currency_id
 +        if not self.tax_line:
              for tax in compute_taxes.values():
 -                ait_obj.create(cr, uid, tax)
 +                account_invoice_tax.create(tax)
          else:
              tax_key = []
 -            for tax in inv.tax_line:
 +            precision = self.env['decimal.precision'].precision_get('Account')
 +            for tax in self.tax_line:
                  if tax.manual:
                      continue
-                 key = (tax.tax_code_id.id, tax.base_code_id.id, tax.account_id.id, tax.account_analytic_id.id)
+                 key = (tax.tax_code_id.id, tax.base_code_id.id, tax.account_id.id)
                  tax_key.append(key)
 -                if not key in compute_taxes:
 -                    raise osv.except_osv(_('Warning!'), _('Global taxes defined, but they are not in invoice lines !'))
 +                if key not in compute_taxes:
 +                    raise except_orm(_('Warning!'), _('Global taxes defined, but they are not in invoice lines !'))
                  base = compute_taxes[key]['base']
 -                precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')
                  if float_compare(abs(base - tax.base), company_currency.rounding, precision_digits=precision) == 1:
 -                    raise osv.except_osv(_('Warning!'), _('Tax base different!\nClick on compute to update the tax base.'))
 +                    raise except_orm(_('Warning!'), _('Tax base different!\nClick on compute to update the tax base.'))
              for key in compute_taxes:
 -                if not key in tax_key:
 -                    raise osv.except_osv(_('Warning!'), _('Taxes are missing!\nClick on compute button.'))
 +                if key not in tax_key:
 +                    raise except_orm(_('Warning!'), _('Taxes are missing!\nClick on compute button.'))
  
 -    def compute_invoice_totals(self, cr, uid, inv, company_currency, ref, invoice_move_lines, context=None):
 -        if context is None:
 -            context={}
 +    @api.multi
 +    def compute_invoice_totals(self, company_currency, ref, invoice_move_lines):
          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 fields.date.context_today(self, cr, uid, context=context)})
 -                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=context)
 +        for line in invoice_move_lines:
 +            if self.currency_id != company_currency:
 +                currency = self.currency_id.with_context(date=self.date_invoice or fields.Date.context_today(self))
 +                line['currency_id'] = currency.id
 +                line['amount_currency'] = line['price']
 +                line['price'] = currency.compute(line['price'], company_currency)
              else:
 -                i['amount_currency'] = False
 -                i['currency_id'] = False
 -            i['ref'] = ref
 -            if inv.type in ('out_invoice','in_refund'):
 -                total += i['price']
 -                total_currency += i['amount_currency'] or i['price']
 -                i['price'] = - i['price']
 +                line['currency_id'] = False
 +                line['amount_currency'] = False
 +            line['ref'] = ref
 +            if self.type in ('out_invoice','in_refund'):
 +                total += line['price']
 +                total_currency += line['amount_currency'] or line['price']
 +                line['price'] = - line['price']
              else:
 -                total -= i['price']
 -                total_currency -= i['amount_currency'] or i['price']
 +                total -= line['price']
 +                total_currency -= line['amount_currency'] or line['price']
          return total, total_currency, invoice_move_lines
  
 -    def inv_line_characteristic_hashcode(self, invoice, invoice_line):
 +    def inv_line_characteristic_hashcode(self, invoice_line):
          """Overridable hashcode generation for invoice lines. Lines having the same hashcode
          will be grouped together if the journal has the 'group line' option. Of course a module
          can add fields to invoice lines that would need to be tested too before merging lines
@@@ -230,14 -219,12 +230,14 @@@ class base_action_rule(osv.osv)
              ids = self.search(cr, SUPERUSER_ID, [])
          for action_rule in self.browse(cr, SUPERUSER_ID, ids):
              model = action_rule.model_id.model
-             model_obj = self.pool[model]
-             if not hasattr(model_obj, 'base_action_ruled'):
+             model_obj = self.pool.get(model)
+             if model_obj and not hasattr(model_obj, 'base_action_ruled'):
 -                model_obj.create = self._wrap_create(model_obj.create, model)
 -                model_obj.write = self._wrap_write(model_obj.write, model)
 +                # monkey-patch methods create and write
 +                model_obj._patch_method('create', make_create())
 +                model_obj._patch_method('write', make_write())
                  model_obj.base_action_ruled = True
                  updated = True
 +
          return updated
  
      def _update_cron(self, cr, uid, context=None):
                          <field name="interval_nbr"/>
                          <field name="interval_type"/>
                      </tree>
 -                    <form string="Incoming Transitions" version="7.0">
 +                    <form string="Incoming Transitions">
                          <group col="4">
-                             <field name="activity_from_id" domain="[('campaign_id', '=', parent.campaign_id)]"/>
+                             <field name="activity_from_id" domain="[('campaign_id', '=', parent.campaign_id)]" options="{'no_create': True}" />
                              <field name='trigger'/>
                              <field name="interval_nbr"/>
                              <field name="interval_type"/>
                          <field name="interval_nbr"/>
                          <field name="interval_type"/>
                      </tree>
 -                    <form string="Outgoing Transitions" version="7.0">
 +                    <form string="Outgoing Transitions">
                          <group col="4">
-                             <field name="activity_to_id" domain="[('campaign_id', '=', parent.campaign_id)]"/>
+                             <field name="activity_to_id" domain="[('campaign_id', '=', parent.campaign_id)]" options="{'no_create': True}" />
                              <field name='trigger'/>
                              <field name="interval_nbr"/>
                              <field name="interval_type"/>
@@@ -544,70 -418,13 +544,72 @@@ class product_template(osv.osv)
              help="Small-sized image of the product. It is automatically "\
                   "resized as a 64x64px image, with aspect ratio preserved. "\
                   "Use this field anywhere a small image is required."),
 -        'product_variant_ids': fields.one2many('product.product', 'product_tmpl_id', 'Product Variants', required=True),
 +        'packaging_ids': fields.one2many(
 +            'product.packaging', 'product_tmpl_id', 'Logistical Units',
 +            help="Gives the different ways to package the same product. This has no impact on "
 +                 "the picking order and is mainly used if you use the EDI module."),
 +        'seller_ids': fields.one2many('product.supplierinfo', 'product_tmpl_id', 'Supplier'),
 +        'seller_delay': fields.related('seller_ids','delay', type='integer', string='Supplier Lead Time',
 +            help="This is the average delay in days between the purchase order confirmation and the receipts for this product and for the default supplier. It is used by the scheduler to order requests based on reordering delays."),
 +        'seller_qty': fields.related('seller_ids','qty', type='float', string='Supplier Quantity',
 +            help="This is minimum quantity to purchase from Main Supplier."),
 +        'seller_id': fields.related('seller_ids','name', type='many2one', relation='res.partner', string='Main Supplier',
 +            help="Main Supplier who has highest priority in Supplier List."),
 +
 +        'active': fields.boolean('Active', help="If unchecked, it will allow you to hide the product without removing it."),
 +        'color': fields.integer('Color Index'),
 +        'is_product_variant': fields.function( _is_product_variant, type='boolean', string='Is product variant'),
 +
 +        'attribute_line_ids': fields.one2many('product.attribute.line', 'product_tmpl_id', 'Product Attributes'),
 +        'product_variant_ids': fields.one2many('product.product', 'product_tmpl_id', 'Products', required=True),
 +        'product_variant_count': fields.function( _get_product_variant_count, type='integer', string='# of Product Variants'),
 +
 +        # related to display product product information if is_product_variant
 +        'ean13': fields.related('product_variant_ids', 'ean13', type='char', string='EAN13 Barcode'),
 +        'default_code': fields.related('product_variant_ids', 'default_code', type='char', string='Internal Reference'),
      }
  
 +    def _price_get_list_price(self, product):
 +        return 0.0
 +
 +    def _price_get(self, cr, uid, products, ptype='list_price', context=None):
 +        if context is None:
 +            context = {}
 +
 +        if 'currency_id' in context:
 +            pricetype_obj = self.pool.get('product.price.type')
 +            price_type_id = pricetype_obj.search(cr, uid, [('field','=',ptype)])[0]
 +            price_type_currency_id = pricetype_obj.browse(cr,uid,price_type_id).currency_id.id
 +
 +        res = {}
 +        product_uom_obj = self.pool.get('product.uom')
 +        for product in products:
 +            # standard_price field can only be seen by users in base.group_user
 +            # Thus, in order to compute the sale price from the cost price for users not in this group
 +            # We fetch the standard price as the superuser
 +            if ptype != 'standard_price':
 +                res[product.id] = product[ptype] or 0.0
 +            else:
-                 res[product.id] = product.sudo()[ptype]
++                company_id = self.pool['res.users'].read(cr, uid, uid, ['company_id'], context=context)[0]
++                product = product.with_context(force_company=company_id)
++                res[product.id] = res[product.id] = product.sudo()[ptype]
 +            if ptype == 'list_price':
 +                res[product.id] += product._name == "product.product" and product.price_extra or 0.0
 +            if 'uom' in context:
 +                uom = product.uom_id or product.uos_id
 +                res[product.id] = product_uom_obj._compute_price(cr, uid,
 +                        uom.id, res[product.id], context['uom'])
 +            # Convert from price_type currency to asked one
 +            if 'currency_id' in context:
 +                # Take the price_type currency from the product field
 +                # This is right cause a field cannot be in more than one currency
 +                res[product.id] = self.pool.get('res.currency').compute(cr, uid, price_type_currency_id,
 +                    context['currency_id'], res[product.id],context=context)
 +
 +        return res
 +
      def _get_uom_id(self, cr, uid, *args):
 -        cr.execute('select id from product_uom order by id limit 1')
 -        res = cr.fetchone()
 -        return res and res[0] or False
 +        return self.pool["product.uom"].search(cr, uid, [], limit=1, order='id')[0]
  
      def _default_category(self, cr, uid, context=None):
          if context is None:
Simple merge
Simple merge