diff --git a/addons/account/partner.py b/addons/account/partner.py
index d9bb6083f437fd8d5b217ef1169cffcf10c29c9b..70f5280b86190d16e4d472f63eff963d990e60e4 100644
--- a/addons/account/partner.py
+++ b/addons/account/partner.py
@@ -27,13 +27,19 @@ from openerp.osv import fields, osv
 class account_fiscal_position(osv.osv):
     _name = 'account.fiscal.position'
     _description = 'Fiscal Position'
+    _order = 'sequence'
     _columns = {
+        'sequence': fields.integer('Sequence'),
         'name': fields.char('Fiscal Position', required=True),
         'active': fields.boolean('Active', help="By unchecking the active field, you may hide a fiscal position without deleting it."),
         'company_id': fields.many2one('res.company', 'Company'),
         'account_ids': fields.one2many('account.fiscal.position.account', 'position_id', 'Account Mapping'),
         'tax_ids': fields.one2many('account.fiscal.position.tax', 'position_id', 'Tax Mapping'),
         'note': fields.text('Notes'),
+        'auto_apply': fields.boolean('Automatic', help="Apply automatically this fiscal position."),
+        'vat_required': fields.boolean('VAT required', help="Apply only if partner has a VAT number."),
+        'country_id': fields.many2one('res.country', 'Countries', help="Apply only if delivery or invoicing country match."),
+        'country_group_id': fields.many2one('res.country.group', 'Country Group', help="Apply only if delivery or invocing country match the group."),
     }
 
     _defaults = {
@@ -66,6 +72,33 @@ class account_fiscal_position(osv.osv):
                 break
         return account_id
 
+    def get_fiscal_position(self, cr, uid, company_id, partner_id, delivery_id=None, context=None):
+        if not partner_id:
+            return False
+        # This can be easily overriden to apply more complex fiscal rules
+        part_obj = self.pool['res.partner']
+        partner = part_obj.browse(cr, uid, partner_id, context=context)
+
+        # partner manually set fiscal position always win
+        if partner.property_account_position:
+            return part.property_account_position.id
+
+        # if no delivery use invocing
+        if delivery_id:
+            delivery = part_obj.browse(cr, uid, delivery_id, context=context)
+        else:
+            delivery = partner
+
+        domain = [
+            ('auto_apply', '=', True),
+            '|', ('vat_required', '=', False), ('vat_required', '=', partner.vat_subjected),
+            '|', ('country_id', '=', None), ('country_id', '=', delivery.country_id.id),
+            '|', ('country_group_id', '=', None), ('country_group_id.country_ids', '=', delivery.country_id.id)
+        ]
+        fiscal_position_ids = self.search(cr, uid, domain, context=context)
+        if fiscal_position_ids:
+            return fiscal_position_ids[0]
+        return False
 
 class account_fiscal_position_tax(osv.osv):
     _name = 'account.fiscal.position.tax'
@@ -206,6 +239,7 @@ class res_partner(osv.osv):
         return self.write(cr, uid, ids, {'last_reconciliation_date': time.strftime('%Y-%m-%d %H:%M:%S')}, context=context)
 
     _columns = {
+        'vat_subjected': fields.boolean('VAT Legal Statement', help="Check this box if the partner is subjected to the VAT. It will be used for the VAT legal statement."),
         'credit': fields.function(_credit_debit_get,
             fnct_search=_credit_search, string='Total Receivable', multi='dc', help="Total amount this customer owes you."),
         'debit': fields.function(_credit_debit_get, fnct_search=_debit_search, string='Total Payable', multi='dc', help="Total amount you have to pay to this supplier."),
diff --git a/addons/account/partner_view.xml b/addons/account/partner_view.xml
index c2a01c7e40a5db2ed10511181341908461a9403e..309296c7955a4f1a5e633a4196d9a9690f918f74 100644
--- a/addons/account/partner_view.xml
+++ b/addons/account/partner_view.xml
@@ -12,6 +12,13 @@
                         <field name="active"/>
                         <field name="company_id" widget="selection" groups="base.group_multi_company"/>
                     </group>
+                    <group>
+                        <field name="auto_apply"/>
+                        <field name="sequence"/>
+                        <field name="vat_required" attrs="{'readonly': [('auto_apply', '=', False)]}"/>
+                        <field name="country_id" attrs="{'readonly': ['|', ('country_group_id','!=',False), ('auto_apply', '=', False)]}" />
+                        <field name="country_group_id" attrs="{'readonly': ['|', ('country_id','!=',False), ('auto_apply', '=', False)]}"/>
+                    </group>
                     <separator string="Taxes Mapping"/>
                     <field name="tax_ids" widget="one2many_list">
                         <tree string="Tax Mapping" editable="bottom">
@@ -44,6 +51,7 @@
             <field name="model">account.fiscal.position</field>
             <field name="arch" type="xml">
                 <tree string="Fiscal Position">
+                    <field name="sequence"/>
                     <field name="name"/>
                     <field name="company_id" groups="base.group_multi_company" widget="selection"/>
                 </tree>
diff --git a/addons/base_vat/base_vat.py b/addons/base_vat/base_vat.py
index 9b3862508b050f3b779c0a097461e02efc2538c3..b7ac9592dd31ca2b6213413143a8901bdc53059b 100644
--- a/addons/base_vat/base_vat.py
+++ b/addons/base_vat/base_vat.py
@@ -133,10 +133,6 @@ class res_partner(osv.osv):
     def vat_change(self, cr, uid, ids, value, context=None):
         return {'value': {'vat_subjected': bool(value)}}
 
-    _columns = {
-        'vat_subjected': fields.boolean('VAT Legal Statement', help="Check this box if the partner is subjected to the VAT. It will be used for the VAT legal statement.")
-    }
-
     def _commercial_fields(self, cr, uid, context=None):
         return super(res_partner, self)._commercial_fields(cr, uid, context=context) + ['vat_subjected']
 
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index 87ad2d80be00a0536c9cbe783185de7fed37e2c0..5e44ad5b0f4f2fb65dcc31e011d906a454d7408b 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -320,6 +320,16 @@ class sale_order(osv.osv):
             context_lang.update({'lang': partner_lang})
         return self.pool.get('res.users').browse(cr, uid, uid, context=context_lang).company_id.sale_note
 
+    def onchange_delivery_id(self, cr, uid, ids, company_id, partner_id, delivery_id, fiscal_position, context=None):
+        r = {'value': {}}
+        if not fiscal_position:
+            if not company_id:
+                company_id = self._get_default_company(cr, uid, context=context)
+            fiscal_position = self.pool['account.fiscal.position'].get_fiscal_position(cr, uid, company_id, partner_id, delivery_id, context=context)
+            if fiscal_position:
+                r['value']['fiscal_position'] = fiscal_position
+        return r
+
     def onchange_partner_id(self, cr, uid, ids, part, context=None):
         if not part:
             return {'value': {'partner_invoice_id': False, 'partner_shipping_id': False,  'payment_term': False, 'fiscal_position': False}}
@@ -328,15 +338,15 @@ class sale_order(osv.osv):
         addr = self.pool.get('res.partner').address_get(cr, uid, [part.id], ['delivery', 'invoice', 'contact'])
         pricelist = part.property_product_pricelist and part.property_product_pricelist.id or False
         payment_term = part.property_payment_term and part.property_payment_term.id or False
-        fiscal_position = part.property_account_position and part.property_account_position.id or False
         dedicated_salesman = part.user_id and part.user_id.id or uid
         val = {
             'partner_invoice_id': addr['invoice'],
             'partner_shipping_id': addr['delivery'],
             'payment_term': payment_term,
-            'fiscal_position': fiscal_position,
             'user_id': dedicated_salesman,
         }
+        delivery_onchange = self.onchange_delivery_id(cr, uid, ids, False, part.id, addr['delivery'], False,  context=context)
+        val.update(delivery_onchange['value'])
         if pricelist:
             val['pricelist_id'] = pricelist
         sale_note = self.get_salenote(cr, uid, ids, part.id, context=context)
@@ -345,11 +355,14 @@ class sale_order(osv.osv):
 
     def create(self, cr, uid, vals, context=None):
         if context is None:
-            context = {}        
+            context = {}
         if vals.get('name', '/') == '/':
             vals['name'] = self.pool.get('ir.sequence').get(cr, uid, 'sale.order') or '/'
-        if vals.get('partner_id') and any(f not in vals for f in ['partner_invoice_id', 'partner_shipping_id', 'pricelist_id']):
-            defaults = self.onchange_partner_id(cr, uid, [], vals['partner_id'], context)['value']
+        if vals.get('partner_id') and any(f not in vals for f in ['partner_invoice_id', 'partner_shipping_id', 'pricelist_id', 'fiscal_position']):
+            defaults = self.onchange_partner_id(cr, uid, [], vals['partner_id'], context=context)['value']
+            if not vals.get('fiscal_position') and vals.get('partner_shipping_id'):
+                delivery_onchange = self.onchange_delivery_id(cr, uid, [], vals.get('company_id'), None, vals['partner_id'], vals.get('partner_shipping_id'), context=context)
+                defaults.update(delivery_onchange['value'])
             vals = dict(defaults, **vals)
         context.update({'mail_create_nolog': True})
         new_id = super(sale_order, self).create(cr, uid, vals, context=context)
diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml
index d5d072c4513ba52a25cfb3ee768c371b04ed7d42..f61c518918ee24215c3b42ae086e14d7b44a0e00 100644
--- a/addons/sale/sale_view.xml
+++ b/addons/sale/sale_view.xml
@@ -102,7 +102,7 @@
                         <group>
                             <field name="partner_id" on_change="onchange_partner_id(partner_id, context)" domain="[('customer','=',True)]" context="{'search_default_customer':1, 'show_address': 1}" options='{"always_reload": True}'/>
                             <field name="partner_invoice_id" groups="sale.group_delivery_invoice_address" context="{'default_type':'invoice'}"/>
-                            <field name="partner_shipping_id" groups="sale.group_delivery_invoice_address" context="{'default_type':'delivery'}"/>
+                            <field name="partner_shipping_id" on_change="onchange_delivery_id(company_id, partner_id, partner_shipping_id, fiscal_position)" groups="sale.group_delivery_invoice_address" context="{'default_type':'delivery'}"/>
                             <field name="project_id" context="{'partner_id':partner_invoice_id, 'default_pricelist_id':pricelist_id, 'default_name':name, 'default_type': 'contract'}" groups="sale.group_analytic_accounting" domain="[('type','in',['view','normal','contract'])]"/>
                         </group>
                         <group>
diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py
index f187e6799ac2f044b6ef83a8cf02740e0568075f..656f581bc63fa8091ad46e922afbc6600c762b16 100644
--- a/addons/website_sale/controllers/main.py
+++ b/addons/website_sale/controllers/main.py
@@ -456,6 +456,7 @@ class website_sale(http.Controller):
         if partner_id and request.website.partner_id.id != partner_id:
             orm_partner.write(cr, SUPERUSER_ID, [partner_id], billing_info, context=context)
         else:
+            # create partner
             partner_id = orm_partner.create(cr, SUPERUSER_ID, billing_info, context=context)
 
         # create a new shipping partner
@@ -472,7 +473,9 @@ class website_sale(http.Controller):
             'partner_invoice_id': partner_id,
             'partner_shipping_id': shipping_id or partner_id
         }
-        order_info.update(registry.get('sale.order').onchange_partner_id(cr, SUPERUSER_ID, [], partner_id, context=context)['value'])
+        order_info.update(order_obj.onchange_partner_id(cr, SUPERUSER_ID, [], partner_id, context=context)['value'])
+        order_info.update(order_obj.onchange_delivery_id(cr, SUPERUSER_ID, [], order.company_id.id, partner_id, shipping_id, None, context=context)['value'])
+
         order_info.pop('user_id')
 
         order_obj.write(cr, SUPERUSER_ID, [order.id], order_info, context=context)
@@ -512,6 +515,8 @@ class website_sale(http.Controller):
         self.checkout_form_save(values["checkout"])
         request.session['sale_last_order_id'] = order.id
 
+        request.website.sale_get_order(update_pricelist=True, context=context)
+
         return request.redirect("/shop/payment")
 
     #------------------------------------------------------
diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py
index 165030f9f1aee8b5e8a7d95a452f0b5dd0031d08..7c0700a555a4eee69d2567fd59bfefb6388db41d 100644
--- a/addons/website_sale/models/sale_order.py
+++ b/addons/website_sale/models/sale_order.py
@@ -128,7 +128,7 @@ class website(orm.Model):
     def sale_product_domain(self, cr, uid, ids, context=None):
         return [("sale_ok", "=", True)]
 
-    def sale_get_order(self, cr, uid, ids, force_create=False, code=None, context=None):
+    def sale_get_order(self, cr, uid, ids, force_create=False, code=None, update_pricelist=None, context=None):
         sale_order_obj = self.pool['sale.order']
         sale_order_id = request.session.get('sale_order_id')
         sale_order = None
@@ -157,26 +157,20 @@ class website(orm.Model):
                 request.session['sale_order_id'] = None
                 return None
 
-            def update_pricelist(pricelist_id):
-                values = {'pricelist_id': pricelist_id}
-                values.update(sale_order.onchange_pricelist_id(pricelist_id, None)['value'])
-                sale_order.write(values)
-                for line in sale_order.order_line:
-                    sale_order._cart_update(product_id=line.product_id.id, add_qty=0)
-
             # check for change of pricelist with a coupon
             if code and code != sale_order.pricelist_id.code:
                 pricelist_ids = self.pool['product.pricelist'].search(cr, SUPERUSER_ID, [('code', '=', code)], context=context)
                 if pricelist_ids:
                     pricelist_id = pricelist_ids[0]
                     request.session['sale_order_code_pricelist_id'] = pricelist_id
-                    update_pricelist(pricelist_id)
+                    update_pricelist = True
                 request.session['sale_order_code_pricelist_id'] = False
 
+            pricelist_id = request.session.get('sale_order_code_pricelist_id') or partner.property_product_pricelist.id
+
             # check for change of partner_id ie after signup
             if sale_order.partner_id.id != partner.id and request.website.partner_id.id != partner.id:
                 flag_pricelist = False
-                pricelist_id = request.session.get('sale_order_code_pricelist_id') or partner.property_product_pricelist.id
                 if pricelist_id != sale_order.pricelist_id.id:
                     flag_pricelist = True
                 fiscal_position = sale_order.fiscal_position and sale_order.fiscal_position.id or False
@@ -190,7 +184,15 @@ class website(orm.Model):
                 sale_order_obj.write(cr, SUPERUSER_ID, [sale_order_id], values, context=context)
 
                 if flag_pricelist or values.get('fiscal_position') != fiscal_position:
-                    update_pricelist(pricelist_id)
+                    update_pricelist = True
+
+            # update the pricelist
+            if update_pricelist:
+                values = {'pricelist_id': pricelist_id}
+                values.update(sale_order.onchange_pricelist_id(pricelist_id, None)['value'])
+                sale_order.write(values)
+                for line in sale_order.order_line:
+                    sale_order._cart_update(product_id=line.product_id.id, add_qty=0)
 
             # update browse record
             if (code and code != sale_order.pricelist_id.code) or sale_order.partner_id.id !=  partner.id:
diff --git a/openerp/addons/base/res/res_country.py b/openerp/addons/base/res/res_country.py
index 10f82df2ee85a0e72a7e0c7bad6a4244e0956e61..f086f1440e82ef7a412305ee5eef3e38fcb0c026 100644
--- a/openerp/addons/base/res/res_country.py
+++ b/openerp/addons/base/res/res_country.py
@@ -84,6 +84,14 @@ addresses belonging to this country.\n\nYou can use the python-style string pate
                 context=context)
 
 
+class CountryGroup(osv.osv):
+    _description="Country Group"
+    _name = 'res.country.group'
+    _columns = {
+        'name': fields.char('Name', required=True),
+        'country_ids': fields.many2many('res.country', string='Countries'),
+    }
+
 class CountryState(osv.osv):
     _description="Country state"
     _name = 'res.country.state'
diff --git a/openerp/addons/base/res/res_country_data.xml b/openerp/addons/base/res/res_country_data.xml
index 633b4cc42c4c46e2bdd81094f9d277ea2c357ba2..1bdd6a73460df253f19967e1a35c1ae538517076 100644
--- a/openerp/addons/base/res/res_country_data.xml
+++ b/openerp/addons/base/res/res_country_data.xml
@@ -1516,5 +1516,18 @@
             <field name="image" type="base64" file="base/static/img/country_flags/zw.png"></field>
             <field name="currency_id" ref="ZWD"/>
         </record>
+
+
+
+        <record id="europe" model="res.country.group">
+            <field name="name">Europe</field>
+            <field name="country_ids" eval="[(6,0,[
+                ref('at'),ref('be'),ref('bg'),ref('hr'),ref('cy'),
+                ref('cz'),ref('dk'),ref('ee'),ref('fi'),ref('fr'),
+                ref('de'),ref('gr'),ref('hu'),ref('ie'),ref('it'),
+                ref('lv'),ref('lt'),ref('lu'),ref('mt'),ref('nl'),
+                ref('pl'),ref('pt'),ref('ro'),ref('sk'),ref('si'),
+                ref('es'),ref('se'),ref('uk')])]"/>
+        </record>
     </data>
 </openerp>
diff --git a/openerp/addons/base/res/res_country_view.xml b/openerp/addons/base/res/res_country_view.xml
index ad46235c5c6451382ec42254d057ed664289b905..f1316844dd71d0dd8e9c03f6441785429df00716 100644
--- a/openerp/addons/base/res/res_country_view.xml
+++ b/openerp/addons/base/res/res_country_view.xml
@@ -50,6 +50,38 @@
 
         <menuitem action="action_country" id="menu_country_partner" parent="menu_localisation" sequence="0" groups="base.group_no_one"/>
 
+        <record id="view_country_group_tree" model="ir.ui.view">
+            <field name="name">res.country.group.tree</field>
+            <field name="model">res.country.group</field>
+            <field name="arch" type="xml">
+                <tree string="Country Group">
+                    <field name="name"/>
+                </tree>
+            </field>
+        </record>
+
+        <record id="view_country_group_form" model="ir.ui.view">
+            <field name="name">res.country.group.form</field>
+            <field name="model">res.country.group</field>
+            <field name="arch" type="xml">
+                <form string="Country Group">
+                    <field name="name"/>
+                    <field name="country_ids" widget="many2many_tags"/>
+                </form>
+            </field>
+        </record>
+
+        <record id="action_country_group" model="ir.actions.act_window">
+            <field name="name">Country Group</field>
+            <field name="type">ir.actions.act_window</field>
+            <field name="res_model">res.country.group</field>
+            <field name="view_type">form</field>
+            <field name="help">Display and manage the list of all countries group. You can create or delete country group to make sure the ones you are working on will be maintained.</field>
+        </record>
+
+
+        <menuitem action="action_country_group" id="menu_country_group" name="Country Group" parent="menu_localisation" sequence="1" groups="base.group_no_one"/>
+
         <!--
           State
         -->
diff --git a/openerp/addons/base/security/ir.model.access.csv b/openerp/addons/base/security/ir.model.access.csv
index c70733b5140a73a1dcbfd890888b0fc5a506958d..bbf579486a48181b4f84603d72eb7727bd421e9f 100644
--- a/openerp/addons/base/security/ir.model.access.csv
+++ b/openerp/addons/base/security/ir.model.access.csv
@@ -45,8 +45,10 @@
 "access_res_company_group_user","res_company group_user","model_res_company",,1,0,0,0
 "access_res_country_group_all","res_country group_user_all","model_res_country",,1,0,0,0
 "access_res_country_state_group_all","res_country_state group_user_all","model_res_country_state",,1,0,0,0
+"access_res_country_group_group_all","res_country_group group_user_all","model_res_country_group",,1,0,0,0
 "access_res_country_group_user","res_country group_user","model_res_country","group_partner_manager",1,1,1,1
 "access_res_country_state_group_user","res_country_state group_user","model_res_country_state","group_partner_manager",1,1,1,1
+"access_res_country_group_group_user","res_country_group group_user","model_res_country_group","group_partner_manager",1,1,1,1
 "access_res_currency_group_all","res_currency group_all","model_res_currency",,1,0,0,0
 "access_res_currency_rate_group_all","res_currency_rate group_all","model_res_currency_rate",,1,0,0,0
 "access_res_currency_rate_type_group_all","res_currency_rate_type group_all","model_res_currency_rate_type",,1,0,0,0