From a36146430decfca525de11e34424c8388ddb258e Mon Sep 17 00:00:00 2001
From: ara <>
Date: Wed, 30 May 2012 16:01:20 +0530
Subject: [PATCH 001/408] portal:Improve portal wizard of contact
bzr revid: mma@tinyerp.com-20120530103120-as3coz6hx3y2cvbg
---
addons/portal/wizard/portal_wizard.py | 68 ++++++++++++++++++---------
1 file changed, 45 insertions(+), 23 deletions(-)
diff --git a/addons/portal/wizard/portal_wizard.py b/addons/portal/wizard/portal_wizard.py
index 1ec4cbb0e4b..3b5a0c31b8c 100644
--- a/addons/portal/wizard/portal_wizard.py
+++ b/addons/portal/wizard/portal_wizard.py
@@ -91,11 +91,20 @@ class wizard(osv.osv_memory):
def _default_user_ids(self, cr, uid, context):
""" determine default user_ids from the active records """
def create_user_from_address(address):
- return { # a user config based on a contact (address)
+ has_portal=False
+ portal_id = context.get('portal_id',False)
+ portal_users = self.pool.get('res.portal').browse(cr,uid,portal_id).group_id.users
+ active_user = [u.login for u in portal_users]
+ if address.email in active_user:
+ has_portal = True
+
+ return { # a user config based on a contact (address)
'name': address.name,
'user_email': extract_email(address.email),
'lang': address.parent_id and address.parent_id.lang or 'en_US',
'partner_id': address.parent_id and address.parent_id.id,
+ 'has_portal_user':has_portal,
+ 'portal_id': context.get('portal_id', False)
}
user_ids = []
@@ -112,9 +121,13 @@ class wizard(osv.osv_memory):
return user_ids
- _defaults = {
- 'user_ids': _default_user_ids
- }
+ def onchange_portal_id(self, cr, uid, ids, portal_id=False, context=None):
+ if not portal_id:
+ return {'value': {}}
+ user_obj = self.pool.get('res.users')
+ context.update({'portal_id':portal_id})
+ user_list = self._default_user_ids(cr, uid, context=context)
+ return {'value': {'user_ids': user_list}}
def action_create(self, cr, uid, ids, context=None):
""" create new users in portal(s), and notify them by email """
@@ -133,25 +146,33 @@ class wizard(osv.osv_memory):
portal_obj = self.pool.get('res.portal')
for wiz in self.browse(cr, uid, ids, context):
# determine existing users
- login_cond = [('login', 'in', [u.user_email for u in wiz.user_ids])]
- existing_uids = user_obj.search(cr, ROOT_UID, login_cond)
- existing_users = user_obj.browse(cr, ROOT_UID, existing_uids)
- existing_logins = [u.login for u in existing_users]
-
- # create new users in portal (skip existing logins)
- new_users_data = [ {
- 'name': u.name,
- 'login': u.user_email,
- 'password': random_password(),
- 'user_email': u.user_email,
- 'context_lang': u.lang,
- 'share': True,
- 'action_id': wiz.portal_id.home_action_id and wiz.portal_id.home_action_id.id or False,
- 'partner_id': u.partner_id and u.partner_id.id,
- } for u in wiz.user_ids if u.user_email not in existing_logins ]
- portal_obj.write(cr, ROOT_UID, [wiz.portal_id.id],
- {'users': [(0, 0, data) for data in new_users_data]}, context0)
-
+
+ for u in wiz.user_ids:
+ login_cond = [('login', 'in', [u.user_email])]
+ existing_uids = user_obj.search(cr, ROOT_UID, login_cond)
+ existing_users = user_obj.browse(cr, ROOT_UID, existing_uids)
+ existing_logins = [user.login for user in existing_users]
+ new_users_data = []
+ if u.has_portal_user==False:
+ new_users_data = []
+ if u.user_email in existing_logins:
+ portal_uids = user_obj.search(cr, ROOT_UID, [('login','=',u.user_email),('partner_id', '=', u.partner_id.id)])
+ user_obj.unlink(cr,uid,portal_uids)
+ else:
+ if u.user_email not in existing_logins:
+ new_users_data.append({
+ 'name': u.name,
+ 'login': u.user_email,
+ 'password': random_password(),
+ 'user_email': u.user_email,
+ 'context_lang': u.lang,
+ 'share': True,
+ 'action_id': wiz.portal_id.home_action_id and wiz.portal_id.home_action_id.id or False,
+ 'partner_id': u.partner_id and u.partner_id.id,
+ } )
+ portal_obj.write(cr, ROOT_UID, [wiz.portal_id.id],
+ {'users': [(0, 0, data) for data in new_users_data]}, context0)
+
# send email to all users (translated in their language)
data = {
'company': user.company_id.name,
@@ -205,6 +226,7 @@ class wizard_user(osv.osv_memory):
help="The language for the user's user interface"),
'partner_id': fields.many2one('res.partner',
string='Partner'),
+ 'has_portal_user':fields.boolean('Has portal access')
}
def _check_email(self, cr, uid, ids):
From 60df377cdfc992b75657749e9ec6f3f6903dee4c Mon Sep 17 00:00:00 2001
From: ara-desktop <>
Date: Wed, 30 May 2012 16:37:44 +0530
Subject: [PATCH 002/408] portal:add missing xml file changes
bzr revid: mma@tinyerp.com-20120530110744-4lufcl4veemhvewn
---
addons/portal/wizard/portal_wizard_view.xml | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/addons/portal/wizard/portal_wizard_view.xml b/addons/portal/wizard/portal_wizard_view.xml
index 7f36272720c..0f49c25d108 100644
--- a/addons/portal/wizard/portal_wizard_view.xml
+++ b/addons/portal/wizard/portal_wizard_view.xml
@@ -17,7 +17,7 @@
form
@@ -48,6 +48,7 @@
+
From 297ee5313a5ca72d4d77af6c65fcfb35a48840ac Mon Sep 17 00:00:00 2001
From: "ara@tinyerp.com" <>
Date: Wed, 30 May 2012 19:27:57 +0530
Subject: [PATCH 003/408] portal: add default user
bzr revid: ara@tinyerp.com-20120530135757-34eu8xtx3ybcaazn
---
addons/portal/wizard/portal_wizard.py | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/addons/portal/wizard/portal_wizard.py b/addons/portal/wizard/portal_wizard.py
index 3b5a0c31b8c..8ad99a00cbe 100644
--- a/addons/portal/wizard/portal_wizard.py
+++ b/addons/portal/wizard/portal_wizard.py
@@ -93,10 +93,11 @@ class wizard(osv.osv_memory):
def create_user_from_address(address):
has_portal=False
portal_id = context.get('portal_id',False)
- portal_users = self.pool.get('res.portal').browse(cr,uid,portal_id).group_id.users
- active_user = [u.login for u in portal_users]
- if address.email in active_user:
- has_portal = True
+ if portal_id:
+ portal_users = self.pool.get('res.portal').browse(cr,uid,portal_id).group_id.users
+ active_user = [u.login for u in portal_users]
+ if address.email in active_user:
+ has_portal = True
return { # a user config based on a contact (address)
'name': address.name,
@@ -121,6 +122,10 @@ class wizard(osv.osv_memory):
return user_ids
+ _defaults = {
+ 'user_ids': _default_user_ids
+ }
+
def onchange_portal_id(self, cr, uid, ids, portal_id=False, context=None):
if not portal_id:
return {'value': {}}
From 1e49be80c99bf752b4264d74a7f30e1d748f04f9 Mon Sep 17 00:00:00 2001
From: "ara@tinyerp.com" <>
Date: Mon, 4 Jun 2012 12:40:51 +0530
Subject: [PATCH 004/408] [IMP] Improve portal wizard string
bzr revid: ara@tinyerp.com-20120604071051-mwr1o7vq72s0iewh
---
addons/portal/wizard/portal_wizard.py | 13 ++++++-------
addons/portal/wizard/portal_wizard_view.xml | 4 ++--
2 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/addons/portal/wizard/portal_wizard.py b/addons/portal/wizard/portal_wizard.py
index 8ad99a00cbe..0e42a68f757 100644
--- a/addons/portal/wizard/portal_wizard.py
+++ b/addons/portal/wizard/portal_wizard.py
@@ -158,12 +158,7 @@ class wizard(osv.osv_memory):
existing_users = user_obj.browse(cr, ROOT_UID, existing_uids)
existing_logins = [user.login for user in existing_users]
new_users_data = []
- if u.has_portal_user==False:
- new_users_data = []
- if u.user_email in existing_logins:
- portal_uids = user_obj.search(cr, ROOT_UID, [('login','=',u.user_email),('partner_id', '=', u.partner_id.id)])
- user_obj.unlink(cr,uid,portal_uids)
- else:
+ if u.has_portal_user:
if u.user_email not in existing_logins:
new_users_data.append({
'name': u.name,
@@ -177,7 +172,11 @@ class wizard(osv.osv_memory):
} )
portal_obj.write(cr, ROOT_UID, [wiz.portal_id.id],
{'users': [(0, 0, data) for data in new_users_data]}, context0)
-
+ else:
+ new_users_data = []
+ if u.user_email in existing_logins:
+ portal_uids = user_obj.search(cr, ROOT_UID, [('login','=',u.user_email),('partner_id', '=', u.partner_id.id)])
+ user_obj.unlink(cr,uid,portal_uids)
# send email to all users (translated in their language)
data = {
'company': user.company_id.name,
diff --git a/addons/portal/wizard/portal_wizard_view.xml b/addons/portal/wizard/portal_wizard_view.xml
index 0f49c25d108..ad64362ddb8 100644
--- a/addons/portal/wizard/portal_wizard_view.xml
+++ b/addons/portal/wizard/portal_wizard_view.xml
@@ -3,7 +3,7 @@
- Add Portal Access
+ Portal Access Management Wizardres.portal.wizardform
From a93cdd0dc11232296debc71690d5cc76e07a1a72 Mon Sep 17 00:00:00 2001
From: "ara@tinyerp.com" <>
Date: Wed, 6 Jun 2012 11:02:15 +0530
Subject: [PATCH 005/408] [IMP] create user when user not in current userlist
bzr revid: ara@tinyerp.com-20120606053215-4dnotn7dq5o6119g
---
addons/portal/wizard/portal_wizard.py | 35 ++++++++++++---------
addons/portal/wizard/portal_wizard_view.xml | 6 ++--
2 files changed, 23 insertions(+), 18 deletions(-)
diff --git a/addons/portal/wizard/portal_wizard.py b/addons/portal/wizard/portal_wizard.py
index 0e42a68f757..c1c6856b5ac 100644
--- a/addons/portal/wizard/portal_wizard.py
+++ b/addons/portal/wizard/portal_wizard.py
@@ -158,21 +158,22 @@ class wizard(osv.osv_memory):
existing_users = user_obj.browse(cr, ROOT_UID, existing_uids)
existing_logins = [user.login for user in existing_users]
new_users_data = []
- if u.has_portal_user:
- if u.user_email not in existing_logins:
- new_users_data.append({
- 'name': u.name,
- 'login': u.user_email,
- 'password': random_password(),
- 'user_email': u.user_email,
- 'context_lang': u.lang,
- 'share': True,
- 'action_id': wiz.portal_id.home_action_id and wiz.portal_id.home_action_id.id or False,
- 'partner_id': u.partner_id and u.partner_id.id,
- } )
- portal_obj.write(cr, ROOT_UID, [wiz.portal_id.id],
- {'users': [(0, 0, data) for data in new_users_data]}, context0)
- else:
+
+ if u.user_email not in existing_logins:
+ new_users_data.append({
+ 'name': u.name,
+ 'login': u.user_email,
+ 'password': random_password(),
+ 'user_email': u.user_email,
+ 'context_lang': u.lang,
+ 'share': True,
+ 'action_id': wiz.portal_id.home_action_id and wiz.portal_id.home_action_id.id or False,
+ 'partner_id': u.partner_id and u.partner_id.id,
+ } )
+ portal_obj.write(cr, ROOT_UID, [wiz.portal_id.id],
+ {'users': [(0, 0, data) for data in new_users_data]}, context0)
+
+ if not u.has_portal_user:
new_users_data = []
if u.user_email in existing_logins:
portal_uids = user_obj.search(cr, ROOT_UID, [('login','=',u.user_email),('partner_id', '=', u.partner_id.id)])
@@ -243,6 +244,10 @@ class wizard_user(osv.osv_memory):
(_check_email, 'Invalid email address', ['email']),
]
+ _defaults = {
+ 'lang': lambda self,cr,uid,c: self.browse(cr, uid, uid, c).partner_id.lang or 'en_US',
+ }
+
wizard_user()
diff --git a/addons/portal/wizard/portal_wizard_view.xml b/addons/portal/wizard/portal_wizard_view.xml
index ad64362ddb8..77ccd44cd44 100644
--- a/addons/portal/wizard/portal_wizard_view.xml
+++ b/addons/portal/wizard/portal_wizard_view.xml
@@ -3,7 +3,7 @@
- Portal Access Management Wizard
+ Portal Access Managementres.portal.wizardform
+
+
+ account.move.line.form
+ account.move.line
+ form
+
+
+
+
+ Journal Items
@@ -1161,9 +1177,7 @@
-
-
-
+
@@ -1192,7 +1206,9 @@
{}This view can be used by accountants in order to quickly record entries in OpenERP. If you want to record a supplier invoice, start by recording the line of the expense account. OpenERP will propose to you automatically the Tax related to this account and the counterpart "Account Payable".
-
+
+
+
+
- Journal Items
+ Journal sssssdfdsItemsaccount.move.lineformtree,form
+ {'search_default_account_id': [active_id]}
@@ -1456,13 +1474,14 @@
src_model="account.move"/>
- Journal Items
+ Journssssal Itemsir.actions.act_windowaccount.move.lineformtree,form
+
@@ -1900,12 +1919,13 @@
- Journal Items
+ Journal Itemaaaaasaccount.move.lineformtree,form[('account_id','child_of', [active_id]),('state','<>','draft')]{'account_id':active_id}
+
@@ -1933,7 +1953,7 @@
- Journal Items
+ Jouffffffffrnal Itemsaccount.move.lineformtree,form
diff --git a/addons/account/static/src/js/account.js b/addons/account/static/src/js/account.js
index a6f266b54e1..5bb8236fde3 100644
--- a/addons/account/static/src/js/account.js
+++ b/addons/account/static/src/js/account.js
@@ -1 +1,19 @@
-console.log('loading account.....')
+openerp.account = function(instance) {
+ instance.account.extend_view = instance.web.ViewManager.include({
+ start : function(){
+ this._super()
+ this.setup_exended_list_view()
+ },
+
+ setup_exended_list_view: function(parent){
+ if (this.action && this.action.extended_form_view_id){
+ view_id = this.action.extended_form_view_id[0]
+ var from_view = this.registry.get_object('form');
+ var options = {}
+ var obj_from_view = new from_view(this, this.dataset, view_id, options);
+ obj_from_view.template = 'ExtendedFormView'
+ obj_from_view.appendTo(this.$element.find('.oe_extended_form_view'))
+ }
+ },
+ })
+}
diff --git a/addons/account/static/src/xml/account.xml b/addons/account/static/src/xml/account.xml
index 388cd96f49b..9b3ae75cc9b 100644
--- a/addons/account/static/src/xml/account.xml
+++ b/addons/account/static/src/xml/account.xml
@@ -3,10 +3,15 @@
-->
-
+
test
-
+
+
+
+
+
+
From 3a6097e85ea7d1d8bb62d0f16bbf372f4551f762 Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Tue, 12 Jun 2012 15:50:38 +0530
Subject: [PATCH 022/408] [IMP] account reconcilation action
bzr revid: rgaopenerp-20120612102038-o96d42kipvkdttcq
---
addons/account/account_view.xml | 62 ++++++++++++++++-----------------
1 file changed, 30 insertions(+), 32 deletions(-)
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index 0a29167fa7a..d65483a543b 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -974,6 +974,21 @@
+
+ account.move.line.form
+ account.move.line
+ form
+
+
+
+
+ account.move.line.tree
@@ -1139,22 +1154,6 @@
-
-
- account.move.line.form
- account.move.line
- form
-
-
-
-
- Journal Items
@@ -1206,9 +1205,7 @@
{}This view can be used by accountants in order to quickly record entries in OpenERP. If you want to record a supplier invoice, start by recording the line of the expense account. OpenERP will propose to you automatically the Tax related to this account and the counterpart "Account Payable".
-
-
-
+
-
- Journal sssssdfdsItems
+ Journal Itemsaccount.move.lineformtree,form
- {'search_default_account_id': [active_id]}
@@ -1474,14 +1469,13 @@
src_model="account.move"/>
- Journssssal Items
+ Journal Itemsir.actions.act_windowaccount.move.lineformtree,form
-
@@ -1495,11 +1489,16 @@
-
+
+
+ Entries To Reconcile
+ account.move.line
+ form
+ tree,form
+
+
+ {'search_default_next_partner':1,'view_mode':True}
+
diff --git a/addons/sale/report/sale_report.py b/addons/sale/report/sale_report.py
index 6beac7cfd38..0062ca4313c 100644
--- a/addons/sale/report/sale_report.py
+++ b/addons/sale/report/sale_report.py
@@ -30,8 +30,6 @@ class sale_report(osv.osv):
_columns = {
'date': fields.date('Date Order', readonly=True),
'date_confirm': fields.date('Date Confirm', readonly=True),
- 'shipped': fields.boolean('Shipped', readonly=True),
- 'shipped_qty_1': fields.integer('Shipped', readonly=True),
'year': fields.char('Year', size=4, readonly=True),
'month': fields.selection([('01', 'January'), ('02', 'February'), ('03', 'March'), ('04', 'April'),
('05', 'May'), ('06', 'June'), ('07', 'July'), ('08', 'August'), ('09', 'September'),
@@ -54,7 +52,6 @@ class sale_report(osv.osv):
('waiting_date', 'Waiting Schedule'),
('manual', 'Manual In Progress'),
('progress', 'In Progress'),
- ('shipping_except', 'Shipping Exception'),
('invoice_except', 'Invoice Exception'),
('done', 'Done'),
('cancel', 'Cancelled')
@@ -86,8 +83,6 @@ class sale_report(osv.osv):
extract(epoch from avg(date_trunc('day',s.date_confirm)-date_trunc('day',s.create_date)))/(24*60*60)::decimal(16,2) as delay,
s.state,
t.categ_id as categ_id,
- s.shipped,
- s.shipped::integer as shipped_qty_1,
s.pricelist_id as pricelist_id,
s.project_id as analytic_account_id
from
@@ -110,7 +105,6 @@ class sale_report(osv.osv):
s.shop_id,
s.company_id,
s.state,
- s.shipped,
s.pricelist_id,
s.project_id
)
diff --git a/addons/sale/report/sale_report_view.xml b/addons/sale/report/sale_report_view.xml
index 8eb4fc85ce6..d572a47b80f 100644
--- a/addons/sale/report/sale_report_view.xml
+++ b/addons/sale/report/sale_report_view.xml
@@ -21,7 +21,6 @@
-
diff --git a/addons/sale/res_config.py b/addons/sale/res_config.py
index 45c01c582a0..1b1d167578d 100644
--- a/addons/sale/res_config.py
+++ b/addons/sale/res_config.py
@@ -30,14 +30,6 @@ class sale_configuration(osv.osv_memory):
'group_invoice_so_lines': fields.boolean('Based on Sale Orders',
implied_group='sale.group_invoice_so_lines',
help="To allow your salesman to make invoices for sale order lines using the menu 'Lines to Invoice'."),
- 'group_invoice_deli_orders': fields.boolean('Based on Delivery Orders',
- implied_group='sale.group_invoice_deli_orders',
- help="To allow your salesman to make invoices for Delivery Orders using the menu 'Deliveries to Invoice'."),
- 'task_work': fields.boolean('Based on Task Activities',
- help="""Lets you transfer the entries under tasks defined for Project Management to
- the Timesheet line entries for particular date and particular user with the effect of creating, editing and deleting either ways
- and to automatically creates project tasks from procurement lines.
- This installs the modules project_timesheet and project_mrp."""),
'timesheet': fields.boolean('Based on Timesheet',
help = """For modifying account analytic view to show important data to project manager of services companies.
You can also view the report of account analytic summary user-wise as well as month wise.
@@ -49,16 +41,10 @@ class sale_configuration(osv.osv_memory):
You will be able to follow the progress of the contract and invoice automatically.
It installs the account_analytic_analysis module."""),
'default_order_policy': fields.selection(
- [('manual', 'Invoice Based on Sales Orders'), ('picking', 'Invoice Based on Deliveries')],
+ [('manual', 'Invoice Based on Sales Orders')],
'Default Method', default_model='sale.order',
- help="You can generate invoices based on sales orders or based on shippings."),
- 'module_delivery': fields.boolean('Allow Charging Shipping Costs',
- help ="""Allows you to add delivery methods in sale orders and delivery orders.
- You can define your own carrier and delivery grids for prices.
- This installs the module delivery."""),
+ help="You can generate invoices based on sales orders."),
'time_unit': fields.many2one('product.uom', 'Working Time Unit'),
- 'default_picking_policy' : fields.boolean("Configurable Shipping Policy",
- help = "You will be able to configure, per sale order, if you deliver all products at once or if you deliver each product when it is available. This may have an impact on the shipping price."),
'group_sale_pricelist':fields.boolean("Pricelist per Customer",
implied_group='product.group_sale_pricelist',
help="""Allows to manage different prices based on rules per category of customers.
@@ -69,15 +55,9 @@ class sale_configuration(osv.osv_memory):
'group_sale_delivery_address': fields.boolean("Allow Different Addresses for Delivery and Invoice",
implied_group='sale.group_delivery_invoice_address',
help="Allows you to specify different delivery and invoice addresses on a sale order."),
- 'group_mrp_properties': fields.boolean('Properties on Lines',
- implied_group='sale.group_mrp_properties',
- help="Allows you to tag sale order lines with properties."),
'group_discount_per_so_line': fields.boolean("Discount per Line",
implied_group='sale.group_discount_per_so_line',
help="Allows you to apply some discount per sale order line."),
- 'group_multiple_shops': fields.boolean("Manage Multiple Shops",
- implied_group='stock.group_locations',
- help="This allows to configure and use multiple shops."),
'module_warning': fields.boolean("Alerts by Products or Customers",
help="""Allow to configure warnings on products and trigger them when a user wants to sale a given product or a given customer.
Example: Product: this product is deprecated, do not purchase more than 5.
@@ -95,8 +75,6 @@ class sale_configuration(osv.osv_memory):
This is mostly used when a user encodes his timesheet. The values are retrieved and the fields are auto-filled.
But the possibility to change these values is still available.
This installs the module analytic_user_function."""),
- 'module_project_timesheet': fields.boolean("Project Timesheet"),
- 'module_project_mrp': fields.boolean("Project MRP"),
'module_project': fields.boolean("Project"),
'decimal_precision': fields.integer('Decimal Precision on Price',help="As an example, a decimal precision of 2 will allow prices like: 9.99 EUR, whereas a decimal precision of 4 will allow prices like: 0.0231 EUR per unit."),
}
@@ -113,8 +91,6 @@ class sale_configuration(osv.osv_memory):
def default_get(self, cr, uid, fields, context=None):
ir_model_data = self.pool.get('ir.model.data')
res = super(sale_configuration, self).default_get(cr, uid, fields, context)
- # task_work, time_unit depend on other fields
- res['task_work'] = res.get('module_project_mrp') and res.get('module_project_timesheet')
if res.get('module_project'):
user = self.pool.get('res.users').browse(cr, uid, uid, context)
res['time_unit'] = user.company_id.project_time_mode_id.id
@@ -123,13 +99,6 @@ class sale_configuration(osv.osv_memory):
res['time_unit'] = product.uom_id.id
return res
- def get_default_sale_config(self, cr, uid, ids, context=None):
- ir_values = self.pool.get('ir.values')
- default_picking_policy = ir_values.get_default(cr, uid, 'sale.order', 'picking_policy')
- return {
- 'default_picking_policy': default_picking_policy == 'one',
- }
-
def _get_default_time_unit(self, cr, uid, context=None):
ids = self.pool.get('product.uom').search(cr, uid, [('name', '=', _('Hour'))], context=context)
return ids and ids[0] or False
@@ -149,13 +118,9 @@ class sale_configuration(osv.osv_memory):
dp.write({'digits': config.decimal_precision})
def set_sale_defaults(self, cr, uid, ids, context=None):
- ir_values = self.pool.get('ir.values')
ir_model_data = self.pool.get('ir.model.data')
wizard = self.browse(cr, uid, ids)[0]
- default_picking_policy = 'one' if wizard.default_picking_policy else 'direct'
- ir_values.set_default(cr, uid, 'sale.order', 'picking_policy', default_picking_policy)
-
if wizard.time_unit:
product = ir_model_data.get_object(cr, uid, 'product', 'product_consultant')
product.write({'uom_id': wizard.time_unit.id, 'uom_po_id': wizard.time_unit.id})
@@ -166,11 +131,9 @@ class sale_configuration(osv.osv_memory):
return {}
- def onchange_invoice_methods(self, cr, uid, ids, group_invoice_so_lines, group_invoice_deli_orders, context=None):
- if not group_invoice_deli_orders:
+ def onchange_invoice_methods(self, cr, uid, ids, group_invoice_so_lines, context=None):
+ if group_invoice_so_lines:
return {'value': {'default_order_policy': 'manual'}}
- if not group_invoice_so_lines:
- return {'value': {'default_order_policy': 'picking'}}
return {}
def onchange_task_work(self, cr, uid, ids, task_work, context=None):
diff --git a/addons/sale/res_config_view.xml b/addons/sale/res_config_view.xml
index ee05a6d2d26..acd545122ce 100644
--- a/addons/sale/res_config_view.xml
+++ b/addons/sale/res_config_view.xml
@@ -9,29 +9,21 @@
-
-
-
-
-
-
-
-
-
+
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index f920b34ca42..a5316ce10fa 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -35,7 +35,6 @@ class sale_shop(osv.osv):
_columns = {
'name': fields.char('Shop Name', size=64, required=True),
'payment_default_id': fields.many2one('account.payment.term', 'Default Payment Term', required=True),
- 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'),
'pricelist_id': fields.many2one('product.pricelist', 'Pricelist'),
'project_id': fields.many2one('account.analytic.account', 'Analytic Account', domain=[('parent_id', '!=', False)]),
'company_id': fields.many2one('res.company', 'Company', required=False),
@@ -50,16 +49,13 @@ class sale_order(osv.osv):
_name = "sale.order"
_inherit = ['ir.needaction_mixin', 'mail.thread']
_description = "Sales Order"
-
def copy(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
default.update({
'state': 'draft',
- 'shipped': False,
'invoice_ids': [],
- 'picking_ids': [],
'date_confirm': False,
'name': self.pool.get('ir.sequence').get(cr, uid, 'sale.order'),
})
@@ -90,44 +86,6 @@ class sale_order(osv.osv):
res[order.id]['amount_total'] = res[order.id]['amount_untaxed'] + res[order.id]['amount_tax']
return res
- # This is False
- def _picked_rate(self, cr, uid, ids, name, arg, context=None):
- if not ids:
- return {}
- res = {}
- tmp = {}
- for id in ids:
- tmp[id] = {'picked': 0.0, 'total': 0.0}
- cr.execute('''SELECT
- p.sale_id as sale_order_id, sum(m.product_qty) as nbr, mp.state as procurement_state, m.state as move_state, p.type as picking_type
- FROM
- stock_move m
- LEFT JOIN
- stock_picking p on (p.id=m.picking_id)
- LEFT JOIN
- procurement_order mp on (mp.move_id=m.id)
- WHERE
- p.sale_id IN %s GROUP BY m.state, mp.state, p.sale_id, p.type''', (tuple(ids),))
-
- for item in cr.dictfetchall():
- if item['move_state'] == 'cancel':
- continue
-
- if item['picking_type'] == 'in':#this is a returned picking
- tmp[item['sale_order_id']]['total'] -= item['nbr'] or 0.0 # Deducting the return picking qty
- if item['procurement_state'] == 'done' or item['move_state'] == 'done':
- tmp[item['sale_order_id']]['picked'] -= item['nbr'] or 0.0
- else:
- tmp[item['sale_order_id']]['total'] += item['nbr'] or 0.0
- if item['procurement_state'] == 'done' or item['move_state'] == 'done':
- tmp[item['sale_order_id']]['picked'] += item['nbr'] or 0.0
-
- for order in self.browse(cr, uid, ids, context=context):
- if order.shipped:
- res[order.id] = 100.0
- else:
- res[order.id] = tmp[order.id]['total'] and (100.0 * tmp[order.id]['picked'] / tmp[order.id]['total']) or 0.0
- return res
def _invoiced_rate(self, cursor, user, ids, name, arg, context=None):
res = {}
@@ -208,11 +166,9 @@ class sale_order(osv.osv):
('cancel', 'Cancelled'),
('waiting_date', 'Waiting Schedule'),
('progress', 'Sale Order'),
- ('manual', 'Sale to Invoice'),
- ('shipping_except', 'Shipping Exception'),
('invoice_except', 'Invoice Exception'),
('done', 'Done'),
- ], 'Status', readonly=True, help="Gives the state of the quotation or sales order. \nThe exception state is automatically set when a cancel operation occurs in the invoice validation (Invoice Exception) or in the picking list process (Shipping Exception). \nThe 'Waiting Schedule' state is set when the invoice is confirmed but waiting for the scheduler to run on the order date.", select=True),
+ ], 'Status', readonly=True, help="Gives the state of the quotation or sales order. \nThe exception state is automatically set when a cancel operation occurs in the invoice validation (Invoice Exception). \nThe 'Waiting Schedule' state is set when the invoice is confirmed but waiting for the scheduler to run on the order date.", select=True),
'date_order': fields.date('Date', required=True, readonly=True, select=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}),
'create_date': fields.datetime('Creation Date', readonly=True, select=True, help="Date on which sales order is created."),
'date_confirm': fields.date('Confirmation Date', readonly=True, select=True, help="Date on which sales order is confirmed."),
@@ -220,28 +176,16 @@ class sale_order(osv.osv):
'partner_id': fields.many2one('res.partner', 'Customer', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, required=True, change_default=True, select=True),
'partner_invoice_id': fields.many2one('res.partner', 'Invoice Address', readonly=True, required=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Invoice address for current sales order."),
'partner_shipping_id': fields.many2one('res.partner', 'Shipping Address', readonly=True, required=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Shipping address for current sales order."),
-
- 'incoterm': fields.many2one('stock.incoterms', 'Incoterm', help="Incoterm which stands for 'International Commercial terms' implies its a series of sales terms which are used in the commercial transaction."),
- 'picking_policy': fields.selection([('direct', 'Deliver each product when available'), ('one', 'Deliver all products at once')],
- 'Shipping Policy', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
- help="""If you don't have enough stock available to deliver all at once, do you accept partial shipments or not?"""),
'order_policy': fields.selection([
- ('manual', 'On Demand'),
- ('picking', 'On Delivery Order'),
('prepaid', 'Before Delivery'),
], 'Create Invoice', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
help="""This field controls how invoice and delivery operations are synchronized.
- - With 'On Demand', the invoice is created manually when needed.
- - With 'On Delivery Order', a draft invoice is generated after all pickings have been processed.
- With 'Before Delivery', a draft invoice is created, and it must be paid before delivery."""),
'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Pricelist for current sales order."),
'project_id': fields.many2one('account.analytic.account', 'Contract/Analytic Account', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="The analytic account related to a sales order."),
'order_line': fields.one2many('sale.order.line', 'order_id', 'Order Lines', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}),
'invoice_ids': fields.many2many('account.invoice', 'sale_order_invoice_rel', 'order_id', 'invoice_id', 'Invoices', readonly=True, help="This is the list of invoices that have been generated for this sales order. The same sales order may have been invoiced in several times (by line for example)."),
- 'picking_ids': fields.one2many('stock.picking.out', 'sale_id', 'Related Picking', readonly=True, help="This is a list of delivery orders that has been generated for this sales order."),
- 'shipped': fields.boolean('Delivered', readonly=True, help="It indicates that the sales order has been delivered. This field is updated only after the scheduler(s) have been launched."),
- 'picked_rate': fields.function(_picked_rate, string='Picked', type='float'),
'invoiced_rate': fields.function(_invoiced_rate, string='Invoiced', type='float'),
'invoiced': fields.function(_invoiced, string='Paid',
fnct_search=_invoiced_search, type='boolean', help="It indicates that an invoice has been paid."),
@@ -266,15 +210,14 @@ class sale_order(osv.osv):
},
multi='sums', help="The total amount."),
- 'invoice_quantity': fields.selection([('order', 'Ordered Quantities'), ('procurement', 'Shipped Quantities')], 'Invoice on', help="The sale order will automatically create the invoice proposition (draft invoice). Ordered and delivered quantities may not be the same. You have to choose if you want your invoice based on ordered or shipped quantities. If the product is a service, shipped quantities means hours spent on the associated tasks.", required=True, readonly=True, states={'draft': [('readonly', False)]}),
+ 'invoice_quantity': fields.selection([('order', 'Ordered Quantities')], 'Invoice on', help="The sale order will automatically create the invoice proposition (draft invoice). Ordered and delivered quantities may not be the same. You have to choose if you want your invoice based on ordered or shipped quantities. If the product is a service, shipped quantities means hours spent on the associated tasks.", required=True, readonly=True, states={'draft': [('readonly', False)]}),
'payment_term': fields.many2one('account.payment.term', 'Payment Term'),
'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position'),
'company_id': fields.related('shop_id','company_id',type='many2one',relation='res.company',string='Company',store=True,readonly=True)
}
_defaults = {
- 'picking_policy': 'direct',
'date_order': fields.date.context_today,
- 'order_policy': 'manual',
+ 'order_policy': 'prepaid',
'state': 'draft',
'user_id': lambda obj, cr, uid, context: uid,
'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'sale.order'),
@@ -295,8 +238,7 @@ class sale_order(osv.osv):
if s['state'] in ['draft', 'cancel']:
unlink_ids.append(s['id'])
else:
- raise osv.except_osv(_('Invalid action !'), _('In order to delete a confirmed sale order, you must cancel it before ! To cancel a sale order, you must first cancel related picking or delivery orders.'))
-
+ raise osv.except_osv(_('Invalid action !'), _('In order to delete a confirmed sale order, you must cancel it before !'))
return osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
def onchange_shop_id(self, cr, uid, ids, shop_id):
@@ -309,20 +251,6 @@ class sale_order(osv.osv):
v['pricelist_id'] = shop.pricelist_id.id
return {'value': v}
- def action_cancel_draft(self, cr, uid, ids, context=None):
- if not len(ids):
- return False
- cr.execute('select id from sale_order_line where order_id IN %s and state=%s', (tuple(ids), 'cancel'))
- line_ids = map(lambda x: x[0], cr.fetchall())
- self.write(cr, uid, ids, {'state': 'draft', 'invoice_ids': [], 'shipped': 0})
- self.pool.get('sale.order.line').write(cr, uid, line_ids, {'invoiced': False, 'state': 'draft', 'invoice_lines': [(6, 0, [])]})
- wf_service = netsvc.LocalService("workflow")
- for inv_id in ids:
- # Deleting the existing instance of workflow for SO
- wf_service.trg_delete(uid, 'sale.order', inv_id, cr)
- wf_service.trg_create(uid, 'sale.order', inv_id, cr)
- self.action_cancel_draft_send_note(cr, uid, ids, context=context)
- return True
def onchange_pricelist_id(self, cr, uid, ids, pricelist_id, order_lines, context={}):
if (not pricelist_id) or (not order_lines):
@@ -333,15 +261,6 @@ class sale_order(osv.osv):
}
return {'warning': warning}
- def onchange_partner_order_id(self, cr, uid, ids, order_id, invoice_id=False, shipping_id=False, context={}):
- if not order_id:
- return {}
- val = {}
- if not invoice_id:
- val['partner_invoice_id'] = order_id
- if not shipping_id:
- val['partner_shipping_id'] = order_id
- return {'value': val}
def onchange_partner_id(self, cr, uid, ids, part):
if not part:
@@ -364,30 +283,7 @@ class sale_order(osv.osv):
val['pricelist_id'] = pricelist
return {'value': val}
- def shipping_policy_change(self, cr, uid, ids, policy, context=None):
- if not policy:
- return {}
- inv_qty = 'order'
- if policy == 'prepaid':
- inv_qty = 'order'
- elif policy == 'picking':
- inv_qty = 'procurement'
- return {'value': {'invoice_quantity': inv_qty}}
-
- def write(self, cr, uid, ids, vals, context=None):
- if vals.get('order_policy', False):
- if vals['order_policy'] == 'prepaid':
- vals.update({'invoice_quantity': 'order'})
- elif vals['order_policy'] == 'picking':
- vals.update({'invoice_quantity': 'procurement'})
- return super(sale_order, self).write(cr, uid, ids, vals, context=context)
-
def create(self, cr, uid, vals, context=None):
- if vals.get('order_policy', False):
- if vals['order_policy'] == 'prepaid':
- vals.update({'invoice_quantity': 'order'})
- if vals['order_policy'] == 'picking':
- vals.update({'invoice_quantity': 'procurement'})
order = super(sale_order, self).create(cr, uid, vals, context=context)
if order:
self.create_send_note(cr, uid, [order], context=context)
@@ -547,46 +443,10 @@ class sale_order(osv.osv):
result.update(view_id = res and res[1] or False)
return result
-
- def action_view_delivery(self, cr, uid, ids, context=None):
- '''
- This function returns an action that display existing delivery orders of given sale order ids. It can either be a in a list or in a form view, if there is only one delivery order to show.
- '''
- mod_obj = self.pool.get('ir.model.data')
- result = {
- 'name': _('Delivery Order'),
- 'view_type': 'form',
- 'res_model': 'stock.picking',
- 'context': "{'type':'out'}",
- 'type': 'ir.actions.act_window',
- 'nodestroy': True,
- 'target': 'current',
- }
- #compute the number of delivery orders to display
- pick_ids = []
- for so in self.browse(cr, uid, ids, context=context):
- pick_ids += [picking.id for picking in so.picking_ids]
- #choose the view_mode accordingly
- if len(pick_ids) > 1:
- res = mod_obj.get_object_reference(cr, uid, 'stock', 'view_picking_out_tree')
- result.update({
- 'view_mode': 'tree,form',
- 'res_id': pick_ids or False
- })
- else:
- res = mod_obj.get_object_reference(cr, uid, 'stock', 'view_picking_out_form')
- result.update({
- 'view_mode': 'form',
- 'res_id': pick_ids and pick_ids[0] or False,
- })
- result.update(view_id = res and res[1] or False)
- return result
-
def action_invoice_create(self, cr, uid, ids, grouped=False, states=['confirmed', 'done', 'exception'], date_inv = False, context=None):
res = False
invoices = {}
invoice_ids = []
- picking_obj = self.pool.get('stock.picking')
invoice = self.pool.get('account.invoice')
obj_sale_order_line = self.pool.get('sale.order.line')
partner_currency = {}
@@ -625,8 +485,6 @@ class sale_order(osv.osv):
for o, l in val:
invoice_ref += o.name + '|'
self.write(cr, uid, [o.id], {'state': 'progress'})
- if o.order_policy == 'picking':
- picking_obj.write(cr, uid, map(lambda x: x.id, o.picking_ids), {'invoice_state': 'invoiced'})
cr.execute('insert into sale_order_invoice_rel (order_id,invoice_id) values (%s,%s)', (o.id, res))
invoice.write(cr, uid, [res], {'origin': invoice_ref, 'name': invoice_ref})
else:
@@ -634,8 +492,6 @@ class sale_order(osv.osv):
res = self._make_invoice(cr, uid, order, il, context=context)
invoice_ids.append(res)
self.write(cr, uid, [order.id], {'state': 'progress'})
- if order.order_policy == 'picking':
- picking_obj.write(cr, uid, map(lambda x: x.id, order.picking_ids), {'invoice_state': 'invoiced'})
cr.execute('insert into sale_order_invoice_rel (order_id,invoice_id) values (%s,%s)', (order.id, res))
if res:
self.invoice_send_note(cr, uid, ids, res, context)
@@ -697,22 +553,7 @@ class sale_order(osv.osv):
if context is None:
context = {}
sale_order_line_obj = self.pool.get('sale.order.line')
- proc_obj = self.pool.get('procurement.order')
for sale in self.browse(cr, uid, ids, context=context):
- for pick in sale.picking_ids:
- if pick.state not in ('draft', 'cancel'):
- raise osv.except_osv(
- _('Could not cancel sales order !'),
- _('You must first cancel all picking attached to this sales order.'))
- if pick.state == 'cancel':
- for mov in pick.move_lines:
- proc_ids = proc_obj.search(cr, uid, [('move_id', '=', mov.id)])
- if proc_ids:
- for proc in proc_ids:
- wf_service.trg_validate(uid, 'procurement.order', proc, 'button_check', cr)
- for r in self.read(cr, uid, ids, ['picking_ids']):
- for pick in r['picking_ids']:
- wf_service.trg_validate(uid, 'stock.picking', pick, 'button_cancel', cr)
for inv in sale.invoice_ids:
if inv.state not in ('draft', 'cancel'):
raise osv.except_osv(
@@ -751,10 +592,7 @@ class sale_order(osv.osv):
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.'))
- if (o.order_policy == 'manual'):
- self.write(cr, uid, [o.id], {'state': 'manual', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)})
- else:
- self.write(cr, uid, [o.id], {'state': 'progress', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)})
+ self.write(cr, uid, [o.id], {'state': 'progress', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)})
self.pool.get('sale.order.line').button_confirm(cr, uid, [x.id for x in o.order_line])
self.confirm_send_note(cr, uid, ids, context)
return True
@@ -783,241 +621,6 @@ class sale_order(osv.osv):
'nodestroy': True,
}
- def procurement_lines_get(self, cr, uid, ids, *args):
- res = []
- for order in self.browse(cr, uid, ids, context={}):
- for line in order.order_line:
- if line.procurement_id:
- res.append(line.procurement_id.id)
- return res
-
- # if mode == 'finished':
- # returns True if all lines are done, False otherwise
- # if mode == 'canceled':
- # returns True if there is at least one canceled line, False otherwise
- def test_state(self, cr, uid, ids, mode, *args):
- assert mode in ('finished', 'canceled'), _("invalid mode for test_state")
- finished = True
- canceled = False
- notcanceled = False
- write_done_ids = []
- write_cancel_ids = []
- for order in self.browse(cr, uid, ids, context={}):
- for line in order.order_line:
- if (not line.procurement_id) or (line.procurement_id.state=='done'):
- if line.state != 'done':
- write_done_ids.append(line.id)
- else:
- finished = False
- if line.procurement_id:
- if (line.procurement_id.state == 'cancel'):
- canceled = True
- if line.state != 'exception':
- write_cancel_ids.append(line.id)
- else:
- notcanceled = True
- if write_done_ids:
- self.pool.get('sale.order.line').write(cr, uid, write_done_ids, {'state': 'done'})
- if write_cancel_ids:
- self.pool.get('sale.order.line').write(cr, uid, write_cancel_ids, {'state': 'exception'})
-
- if mode == 'finished':
- return finished
- elif mode == 'canceled':
- return canceled
- if notcanceled:
- return False
- return canceled
-
- def _prepare_order_line_procurement(self, cr, uid, order, line, move_id, date_planned, context=None):
- return {
- 'name': line.name.split('\n')[0],
- 'origin': order.name,
- 'date_planned': date_planned,
- 'product_id': line.product_id.id,
- 'product_qty': line.product_uom_qty,
- 'product_uom': line.product_uom.id,
- 'product_uos_qty': (line.product_uos and line.product_uos_qty)\
- or line.product_uom_qty,
- 'product_uos': (line.product_uos and line.product_uos.id)\
- or line.product_uom.id,
- 'location_id': order.shop_id.warehouse_id.lot_stock_id.id,
- 'procure_method': line.type,
- 'move_id': move_id,
- 'company_id': order.company_id.id,
- 'note': '\n'.join(line.name.split('\n')[1:]),
- 'property_ids': [(6, 0, [x.id for x in line.property_ids])]
- }
-
- def _prepare_order_line_move(self, cr, uid, order, line, picking_id, date_planned, context=None):
- location_id = order.shop_id.warehouse_id.lot_stock_id.id
- output_id = order.shop_id.warehouse_id.lot_output_id.id
- return {
- 'name': line.name.split('\n')[0][:250],
- 'picking_id': picking_id,
- 'product_id': line.product_id.id,
- 'date': date_planned,
- 'date_expected': date_planned,
- 'product_qty': line.product_uom_qty,
- 'product_uom': line.product_uom.id,
- 'product_uos_qty': (line.product_uos and line.product_uos_qty) or line.product_uom_qty,
- 'product_uos': (line.product_uos and line.product_uos.id)\
- or line.product_uom.id,
- 'product_packaging': line.product_packaging.id,
- 'partner_id': line.address_allotment_id.id or order.partner_shipping_id.id,
- 'location_id': location_id,
- 'location_dest_id': output_id,
- 'sale_line_id': line.id,
- 'tracking_id': False,
- 'state': 'draft',
- #'state': 'waiting',
- 'note': '\n'.join(line.name.split('\n')[1:]),
- 'company_id': order.company_id.id,
- 'price_unit': line.product_id.standard_price or 0.0
- }
-
- def _prepare_order_picking(self, cr, uid, order, context=None):
- pick_name = self.pool.get('ir.sequence').get(cr, uid, 'stock.picking.out')
- return {
- 'name': pick_name,
- 'origin': order.name,
- 'date': order.date_order,
- 'type': 'out',
- 'state': 'auto',
- 'move_type': order.picking_policy,
- 'sale_id': order.id,
- 'partner_id': order.partner_shipping_id.id,
- 'note': order.note,
- 'invoice_state': (order.order_policy=='picking' and '2binvoiced') or 'none',
- 'company_id': order.company_id.id,
- }
-
- def ship_recreate(self, cr, uid, order, line, move_id, proc_id):
- # FIXME: deals with potentially cancelled shipments, seems broken (specially if shipment has production lot)
- """
- Define ship_recreate for process after shipping exception
- param order: sale order to which the order lines belong
- param line: sale order line records to procure
- param move_id: the ID of stock move
- param proc_id: the ID of procurement
- """
- move_obj = self.pool.get('stock.move')
- if order.state == 'shipping_except':
- for pick in order.picking_ids:
- for move in pick.move_lines:
- if move.state == 'cancel':
- mov_ids = move_obj.search(cr, uid, [('state', '=', 'cancel'),('sale_line_id', '=', line.id),('picking_id', '=', pick.id)])
- if mov_ids:
- for mov in move_obj.browse(cr, uid, mov_ids):
- # FIXME: the following seems broken: what if move_id doesn't exist? What if there are several mov_ids? Shouldn't that be a sum?
- move_obj.write(cr, uid, [move_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty})
- self.pool.get('procurement.order').write(cr, uid, [proc_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty})
- return True
-
- def _get_date_planned(self, cr, uid, order, line, start_date, context=None):
- date_planned = datetime.strptime(start_date, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(days=line.delay or 0.0)
- date_planned = (date_planned - timedelta(days=order.company_id.security_lead)).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
- return date_planned
-
- def _create_pickings_and_procurements(self, cr, uid, order, order_lines, picking_id=False, context=None):
- """Create the required procurements to supply sale order lines, also connecting
- the procurements to appropriate stock moves in order to bring the goods to the
- sale order's requested location.
-
- If ``picking_id`` is provided, the stock moves will be added to it, otherwise
- a standard outgoing picking will be created to wrap the stock moves, as returned
- by :meth:`~._prepare_order_picking`.
-
- Modules that wish to customize the procurements or partition the stock moves over
- multiple stock pickings may override this method and call ``super()`` with
- different subsets of ``order_lines`` and/or preset ``picking_id`` values.
-
- :param browse_record order: sale order to which the order lines belong
- :param list(browse_record) order_lines: sale order line records to procure
- :param int picking_id: optional ID of a stock picking to which the created stock moves
- will be added. A new picking will be created if ommitted.
- :return: True
- """
- move_obj = self.pool.get('stock.move')
- picking_obj = self.pool.get('stock.picking')
- procurement_obj = self.pool.get('procurement.order')
- proc_ids = []
-
- for line in order_lines:
- if line.state == 'done':
- continue
-
- date_planned = self._get_date_planned(cr, uid, order, line, order.date_order, context=context)
-
- if line.product_id:
- if line.product_id.product_tmpl_id.type in ('product', 'consu'):
- if not picking_id:
- picking_id = picking_obj.create(cr, uid, self._prepare_order_picking(cr, uid, order, context=context))
- move_id = move_obj.create(cr, uid, self._prepare_order_line_move(cr, uid, order, line, picking_id, date_planned, context=context))
- else:
- # a service has no stock move
- move_id = False
-
- proc_id = procurement_obj.create(cr, uid, self._prepare_order_line_procurement(cr, uid, order, line, move_id, date_planned, context=context))
- proc_ids.append(proc_id)
- line.write({'procurement_id': proc_id})
- self.ship_recreate(cr, uid, order, line, move_id, proc_id)
-
- wf_service = netsvc.LocalService("workflow")
- if picking_id:
- wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr)
- self.delivery_send_note(cr, uid, [order.id], picking_id, context)
-
-
- for proc_id in proc_ids:
- wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_confirm', cr)
-
- val = {}
- if order.state == 'shipping_except':
- val['state'] = 'progress'
- val['shipped'] = False
-
- if (order.order_policy == 'manual'):
- for line in order.order_line:
- if (not line.invoiced) and (line.state not in ('cancel', 'draft')):
- val['state'] = 'manual'
- break
- order.write(val)
- return True
-
- def action_ship_create(self, cr, uid, ids, context=None):
- for order in self.browse(cr, uid, ids, context=context):
- self._create_pickings_and_procurements(cr, uid, order, order.order_line, None, context=context)
- return True
-
- def action_ship_end(self, cr, uid, ids, context=None):
- for order in self.browse(cr, uid, ids, context=context):
- val = {'shipped': True}
- if order.state == 'shipping_except':
- val['state'] = 'progress'
- if (order.order_policy == 'manual'):
- for line in order.order_line:
- if (not line.invoiced) and (line.state not in ('cancel', 'draft')):
- val['state'] = 'manual'
- break
- for line in order.order_line:
- towrite = []
- if line.state == 'exception':
- towrite.append(line.id)
- if towrite:
- self.pool.get('sale.order.line').write(cr, uid, towrite, {'state': 'done'}, context=context)
- res = self.write(cr, uid, [order.id], val)
- if res:
- self.delivery_end_send_note(cr, uid, [order.id], context=context)
- return True
-
- def has_stockable_products(self, cr, uid, ids, *args):
- for order in self.browse(cr, uid, ids):
- for order_line in order.order_line:
- if order_line.product_id and order_line.product_id.product_tmpl_id.type in ('product', 'consu'):
- return True
- return False
-
# ------------------------------------------------
# OpenChatter methods and notifications
# ------------------------------------------------
@@ -1025,7 +628,7 @@ class sale_order(osv.osv):
def get_needaction_user_ids(self, cr, uid, ids, context=None):
result = super(sale_order, self).get_needaction_user_ids(cr, uid, ids, context=context)
for obj in self.browse(cr, uid, ids, context=context):
- if (obj.state == 'manual' or obj.state == 'progress'):
+ if (obj.state == 'progress'):
result[obj.id].append(obj.user_id.id)
return result
@@ -1042,18 +645,7 @@ class sale_order(osv.osv):
for obj in self.browse(cr, uid, ids, context=context):
self.message_append_note(cr, uid, [obj.id], body=_("Sale Order for %scancelled.") % (obj.partner_id.name), context=context)
- def delivery_send_note(self, cr, uid, ids, picking_id, context=None):
- for order in self.browse(cr, uid, ids, context=context):
- for picking in (pck for pck in order.picking_ids if pck.id == picking_id):
- # convert datetime field to a datetime, using server format, then
- # convert it to the user TZ and re-render it with %Z to add the timezone
- picking_datetime = fields.DT.datetime.strptime(picking.min_date, DEFAULT_SERVER_DATETIME_FORMAT)
- picking_date_str = fields.datetime.context_timestamp(cr, uid, picking_datetime, context=context).strftime(DATETIME_FORMATS_MAP['%+'] + " (%Z)")
- self.message_append_note(cr, uid, [order.id], body=_("Delivery Order %sscheduled for %s.") % (picking.name, picking_date_str), context=context)
-
- def delivery_end_send_note(self, cr, uid, ids, context=None):
- self.message_append_note(cr, uid, ids, body=_("Order delivered."), context=context)
-
+
def invoice_paid_send_note(self, cr, uid, ids, context=None):
self.message_append_note(cr, uid, ids, body=_("Invoice paid."), context=context)
@@ -1062,9 +654,6 @@ class sale_order(osv.osv):
for invoice in (inv for inv in order.invoice_ids if inv.id == invoice_id):
self.message_append_note(cr, uid, [order.id], body=_("Draft Invoice of %s %s waiting for validation.") % (invoice.amount_total, invoice.currency_id.symbol), context=context)
- def action_cancel_draft_send_note(self, cr, uid, ids, context=None):
- return self.message_append_note(cr, uid, ids, body='Sale order has been set in draft.', context=context)
-
sale_order()
@@ -1086,14 +675,7 @@ class sale_order_line(osv.osv):
res[line.id] = cur_obj.round(cr, uid, cur, taxes['total'])
return res
- def _number_packages(self, cr, uid, ids, field_name, arg, context=None):
- res = {}
- for line in self.browse(cr, uid, ids, context=context):
- try:
- res[line.id] = int((line.product_uom_qty+line.product_packaging.qty-0.0001) / line.product_packaging.qty)
- except:
- res[line.id] = 1
- return res
+
def _get_uom_id(self, cr, uid, *args):
try:
@@ -1109,26 +691,18 @@ class sale_order_line(osv.osv):
'order_id': fields.many2one('sale.order', 'Order Reference', required=True, ondelete='cascade', select=True, readonly=True, states={'draft':[('readonly',False)]}),
'name': fields.text('Product Description', size=256, required=True, select=True, readonly=True, states={'draft': [('readonly', False)]}),
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of sales order lines."),
- 'delay': fields.float('Delivery Lead Time', required=True, help="Number of days between the order confirmation the shipping of the products to the customer", readonly=True, states={'draft': [('readonly', False)]}),
'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], change_default=True),
'invoice_lines': fields.many2many('account.invoice.line', 'sale_order_line_invoice_rel', 'order_line_id', 'invoice_id', 'Invoice Lines', readonly=True),
'invoiced': fields.boolean('Invoiced', readonly=True),
- 'procurement_id': fields.many2one('procurement.order', 'Procurement'),
'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Sale Price'), readonly=True, states={'draft': [('readonly', False)]}),
'price_subtotal': fields.function(_amount_line, string='Subtotal', digits_compute= dp.get_precision('Sale Price')),
'tax_id': fields.many2many('account.tax', 'sale_order_tax', 'order_line_id', 'tax_id', 'Taxes', readonly=True, states={'draft': [('readonly', False)]}),
- 'type': fields.selection([('make_to_stock', 'from stock'), ('make_to_order', 'on order')], 'Procurement Method', required=True, readonly=True, states={'draft': [('readonly', False)]},
- help="If 'on order', it triggers a procurement when the sale order is confirmed to create a task, purchase order or manufacturing order linked to this sale order line."),
- 'property_ids': fields.many2many('mrp.property', 'sale_order_line_property_rel', 'order_id', 'property_id', 'Properties', readonly=True, states={'draft': [('readonly', False)]}),
'address_allotment_id': fields.many2one('res.partner', 'Allotment Partner'),
'product_uom_qty': fields.float('Quantity', digits_compute= dp.get_precision('Product UoS'), required=True, readonly=True, states={'draft': [('readonly', False)]}),
'product_uom': fields.many2one('product.uom', 'Unit of Measure ', required=True, readonly=True, states={'draft': [('readonly', False)]}),
'product_uos_qty': fields.float('Quantity (UoS)' ,digits_compute= dp.get_precision('Product UoS'), readonly=True, states={'draft': [('readonly', False)]}),
'product_uos': fields.many2one('product.uom', 'Product UoS'),
- 'product_packaging': fields.many2one('product.packaging', 'Packaging'),
- 'move_ids': fields.one2many('stock.move', 'sale_line_id', 'Inventory Moves', readonly=True),
'discount': fields.float('Discount', digits=(16, 2), readonly=True, states={'draft': [('readonly', False)]}),
- 'number_packages': fields.function(_number_packages, type='integer', string='Number Packages'),
'th_weight': fields.float('Weight', readonly=True, states={'draft': [('readonly', False)]}),
'state': fields.selection([('cancel', 'Cancelled'),('draft', 'Draft'),('confirmed', 'Confirmed'),('exception', 'Exception'),('done', 'Done')], 'Status', required=True, readonly=True,
help='* The \'Draft\' state is set when the related sales order in draft state. \
@@ -1144,14 +718,11 @@ class sale_order_line(osv.osv):
_defaults = {
'product_uom' : _get_uom_id,
'discount': 0.0,
- 'delay': 0.0,
'product_uom_qty': 1,
'product_uos_qty': 1,
'sequence': 10,
'invoiced': 0,
'state': 'draft',
- 'type': 'make_to_stock',
- 'product_packaging': False,
'price_unit': 0.0,
}
@@ -1168,22 +739,16 @@ class sale_order_line(osv.osv):
"""
def _get_line_qty(line):
- if (line.order_id.invoice_quantity=='order') or not line.procurement_id:
+ if (line.order_id.invoice_quantity=='order'):
if line.product_uos:
return line.product_uos_qty or 0.0
return line.product_uom_qty
- else:
- return self.pool.get('procurement.order').quantity_get(cr, uid,
- line.procurement_id.id, context=context)
def _get_line_uom(line):
- if (line.order_id.invoice_quantity=='order') or not line.procurement_id:
+ if (line.order_id.invoice_quantity=='order'):
if line.product_uos:
return line.product_uos.id
return line.product_uom.id
- else:
- return self.pool.get('procurement.order').uom_get(cr, uid,
- line.procurement_id.id, context=context)
if not line.invoiced:
if not account_id:
@@ -1293,52 +858,6 @@ class sale_order_line(osv.osv):
default.update({'state': 'draft', 'move_ids': [], 'invoiced': False, 'invoice_lines': []})
return super(sale_order_line, self).copy_data(cr, uid, id, default, context=context)
- def product_packaging_change(self, cr, uid, ids, pricelist, product, qty=0, uom=False,
- partner_id=False, packaging=False, flag=False, context=None):
- if not product:
- return {'value': {'product_packaging': False}}
- product_obj = self.pool.get('product.product')
- product_uom_obj = self.pool.get('product.uom')
- pack_obj = self.pool.get('product.packaging')
- warning = {}
- result = {}
- warning_msgs = ''
- if flag:
- res = self.product_id_change(cr, uid, ids, pricelist=pricelist,
- product=product, qty=qty, uom=uom, partner_id=partner_id,
- packaging=packaging, flag=False, context=context)
- warning_msgs = res.get('warning') and res['warning']['message']
-
- products = product_obj.browse(cr, uid, product, context=context)
- if not products.packaging:
- packaging = result['product_packaging'] = False
- elif not packaging and products.packaging and not flag:
- packaging = products.packaging[0].id
- result['product_packaging'] = packaging
-
- if packaging:
- default_uom = products.uom_id and products.uom_id.id
- pack = pack_obj.browse(cr, uid, packaging, context=context)
- q = product_uom_obj._compute_qty(cr, uid, uom, pack.qty, default_uom)
-# qty = qty - qty % q + q
- if qty and (q and not (qty % q) == 0):
- ean = pack.ean or _('(n/a)')
- qty_pack = pack.qty
- type_ul = pack.ul
- if not warning_msgs:
- warn_msg = _("You selected a quantity of %d Units.\n"
- "But it's not compatible with the selected packaging.\n"
- "Here is a proposition of quantities according to the packaging:\n"
- "EAN: %s Quantity: %s Type of ul: %s") % \
- (qty, ean, qty_pack, type_ul.name)
- warning_msgs += _("Picking Information ! : ") + warn_msg + "\n\n"
- warning = {
- 'title': _('Configuration Error !'),
- 'message': warning_msgs
- }
- result['product_uom_qty'] = qty
-
- return {'value': result, 'warning': warning}
def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,
uom=False, qty_uos=0, uos=False, name='', partner_id=False,
diff --git a/addons/sale/sale_data.xml b/addons/sale/sale_data.xml
index c93651219af..e87669a4d1a 100644
--- a/addons/sale/sale_data.xml
+++ b/addons/sale/sale_data.xml
@@ -10,7 +10,6 @@
-
diff --git a/addons/sale/sale_demo.xml b/addons/sale/sale_demo.xml
index d9946c812c7..938dc545979 100644
--- a/addons/sale/sale_demo.xml
+++ b/addons/sale/sale_demo.xml
@@ -11,9 +11,6 @@
- picking
- procurement
- Invoice after delivery
@@ -24,7 +21,6 @@
123.20
- make_to_stock
@@ -35,7 +31,6 @@
450.5033
- make_to_stock
@@ -44,8 +39,6 @@
9005
- make_to_stock
- 1
@@ -55,7 +48,6 @@
8855
- make_to_stock
@@ -80,7 +72,6 @@
540
- make_to_order
@@ -90,7 +81,6 @@
8888
- make_to_order
@@ -111,8 +101,6 @@
3450
- make_to_order
- 2
@@ -121,8 +109,6 @@
7503
- make_to_order
- 7
@@ -142,8 +128,6 @@
2450
- make_to_order
- 8
@@ -152,10 +136,7 @@
9005
- make_to_order
- 1
-
@@ -174,8 +155,6 @@
4750
- make_to_order
- 15
@@ -185,9 +164,7 @@
7533
- make_to_stock
-
@@ -206,8 +183,6 @@
4250
- make_to_order
- 15
@@ -216,11 +191,7 @@
4500
- make_to_order
- 15
-
-
@@ -239,8 +210,6 @@
15250
- make_to_stock
- 15
@@ -249,12 +218,8 @@
5500
- make_to_stock
- 15
-
-
diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml
index ac665df7a6b..a9edd29b9e1 100644
--- a/addons/sale/sale_view.xml
+++ b/addons/sale/sale_view.xml
@@ -22,9 +22,7 @@
-
-
-
+
@@ -37,6 +35,7 @@
+
sale.shopsale.shop
@@ -44,7 +43,6 @@
-
@@ -61,8 +59,7 @@
If you have more than one shop reselling your company products, you can create and manage that from here. Whenever you will record a new quotation or sales order, it has to be linked to a shop. The shop also defines the warehouse from which the products will be delivered for each particular sales.
-
+
@@ -136,7 +133,6 @@
-
@@ -154,24 +150,17 @@
-
-
-
-
+ attrs="{'invisible': ['|','|',('state', '!=','progress'), ('invoiced', '=', True)]}"/>
-
-
+
diff --git a/addons/sale/sale_workflow.xml b/addons/sale/sale_workflow.xml
index c18e271d480..7db2b6dbcbe 100644
--- a/addons/sale/sale_workflow.xml
+++ b/addons/sale/sale_workflow.xml
@@ -30,10 +30,6 @@
wait_invoice
-
-
- wait_ship
-
@@ -83,6 +79,7 @@
functionaction_invoice_end()
+
invoice_cancel
@@ -90,31 +87,6 @@
stopallaction_cancel()
-
-
- ship
- function
- action_ship_create()
-
-
-
- ship_except
- function
- write({'state':'shipping_except'})
-
-
-
- ship_end
- function
- action_ship_end()
-
-
-
- ship_cancel
- True
- stopall
- action_cancel()
-
@@ -159,6 +131,7 @@
all_lines
+
@@ -170,10 +143,6 @@
-
-
-
-
@@ -181,17 +150,6 @@
cancel
-
-
-
- cancel
-
-
-
-
-
- (order_policy!='prepaid') or invoiced
-
@@ -199,17 +157,13 @@
(order_policy=='prepaid')
-
-
-
- manual_invoice
- subflow.paid
+
@@ -230,38 +184,6 @@
invoice_cancel
-
-
-
-
-
-
-
-
- procurement.order
- procurement_lines_get()
- test_state('finished')
-
-
-
-
- test_state('canceled')
-
-
-
-
- ship_recreate
-
-
-
-
- ship_corrected
-
-
-
-
- ship_cancel
-
-
+
diff --git a/addons/sale/security/ir.model.access.csv b/addons/sale/security/ir.model.access.csv
index 617678eccbe..4d00f8bb212 100644
--- a/addons/sale/security/ir.model.access.csv
+++ b/addons/sale/security/ir.model.access.csv
@@ -9,13 +9,6 @@ access_account_invoice_manager,account_invoice manager,account.model_account_inv
access_account_invoice_line_salesman,account_invoice.line salesman,account.model_account_invoice_line,base.group_sale_salesman,1,1,1,0
access_account_payment_term_salesman,account_payment_term salesman,account.model_account_payment_term,base.group_sale_salesman,1,0,0,0
access_account_analytic_account_salesman,account_analytic_account salesman,analytic.model_account_analytic_account,base.group_sale_salesman,1,1,1,0
-access_stock_picking_salesman,stock_picking salesman,stock.model_stock_picking,base.group_sale_salesman,1,1,1,0
-access_stock_move_salesman,stock_move salesman,stock.model_stock_move,base.group_sale_salesman,1,1,1,0
-access_stock_move_manager,stock_move manager,stock.model_stock_move,base.group_sale_manager,1,1,1,1
-access_procurement_salesman,procurement.order salesman,procurement.model_procurement_order,base.group_sale_salesman,1,1,1,0
-access_procurement_manager,procurement.order manager,procurement.model_procurement_order,base.group_sale_manager,1,1,1,1
-access_sale_order_stock_worker,sale.order stock worker,model_sale_order,stock.group_stock_user,1,1,0,0
-access_sale_order_line_stock_worker,sale.order.line stock worker,model_sale_order_line,stock.group_stock_user,1,1,0,0
access_sale_order_manager,sale.order.manager,model_sale_order,base.group_sale_manager,1,1,1,1
access_sale_order_accountant,sale.order.accountant,model_sale_order,account.group_account_user,1,1,0,0
access_sale_report_salesman,sale.report,model_sale_report,base.group_sale_salesman,1,1,1,0
@@ -24,23 +17,19 @@ access_ir_property_sales,ir.property.sales,base.model_ir_property,base.group_sal
access_sale_account_journal,account.journal sale order.user,account.model_account_journal,base.group_sale_salesman,1,0,0,0
access_res_partner_sale_user,res.partner.sale.user,base.model_res_partner,base.group_sale_salesman,1,0,0,0
access_res_partner_sale_manager,res.partner.sale.manager,base.model_res_partner,base.group_sale_manager,1,1,1,0
-access_report_stock_move_sales,report.stock.move.sale,stock.model_report_stock_move,base.group_sale_manager,1,1,1,1
-access_stock_picking_sales,stock.picking.sales,stock.model_stock_picking,base.group_sale_manager,1,1,1,1
+
access_product_template_sale_user,product.template sale use,product.model_product_template,base.group_sale_salesman,1,0,0,0
access_product_product_sale_user,product.product sale use,product.model_product_product,base.group_sale_salesman,1,0,0,0
access_sale_shop_manager,account.journal sale order.user,model_sale_shop,base.group_sale_manager,1,1,1,1
access_account_fiscalyear_user,account.fiscalyear.user,account.model_account_fiscalyear,base.group_sale_salesman,1,0,0,0
access_account_tax_user,account.tax.user,account.model_account_tax,base.group_sale_salesman,1,0,0,0
-access_product_packaging_user,product.packaging.user,product.model_product_packaging,base.group_sale_salesman,1,1,1,0
+
access_ir_attachment_sales,ir.attachment.sales,base.model_ir_attachment,base.group_sale_salesman,1,1,1,0
access_ir_attachment_manager,ir.attachment.manager,base.model_ir_attachment,base.group_sale_manager,1,1,1,1
-access_product_packaging_manager,product.packaging.manager,product.model_product_packaging,base.group_sale_manager,1,0,0,0
-access_stock_warehouse_user,stock.warehouse.user,stock.model_stock_warehouse,base.group_sale_salesman,1,0,0,0
+
access_res_partner_bank_type_user,res.partner.bank.type.user,base.model_res_partner_bank_type,base.group_sale_salesman,1,0,0,0
-access_stock_location_user,stock.location.user,stock.model_stock_location,base.group_sale_salesman,1,0,0,0
access_res_partner_bank_type_field_user,res.partner.bank.type.field.user,base.model_res_partner_bank_type_field,base.group_sale_salesman,1,0,0,0
access_product_uom_user,product.uom.user,product.model_product_uom,base.group_sale_salesman,1,0,0,0
-access_product_supplierinfo_user,product.supplierinfo.user,product.model_product_supplierinfo,base.group_sale_salesman,1,0,0,0
access_product_pricelist_sale_user,product.pricelist.sale.user,product.model_product_pricelist,base.group_sale_salesman,1,0,0,0
access_account_account_salesman,account_account salesman,account.model_account_account,base.group_sale_salesman,1,0,0,0
access_sale_shop_sale_user,sale.shop.sale.user,model_sale_shop,base.group_sale_salesman,1,0,0,0
@@ -49,7 +38,7 @@ access_product_uom_categ_sale_manager,product.uom.categ salemanager,product.mode
access_product_uom_sale_manager,product.uom salemanager,product.model_product_uom,base.group_sale_manager,1,1,1,1
access_product_ul_sale_manager,product.ul salemanager,product.model_product_ul,base.group_sale_manager,1,1,1,1
access_product_category_sale_manager,product.category salemanager,product.model_product_category,base.group_sale_manager,1,1,1,1
-access_product_packaging_sale_manager,product.packaging salemanager,product.model_product_packaging,base.group_sale_manager,1,1,1,1
+access_product_supplierinfo_user,product.supplierinfo.user,product.model_product_supplierinfo,base.group_sale_salesman,1,0,0,0
access_product_supplierinfo_sale_manager,product.supplierinfo salemanager,product.model_product_supplierinfo,base.group_sale_manager,1,1,1,1
access_pricelist_partnerinfo_sale_manager,pricelist.partnerinfo salemanager,product.model_pricelist_partnerinfo,base.group_sale_manager,1,1,1,1
access_product_price_type_sale_manager,product.price.type salemanager,product.model_product_price_type,base.group_sale_manager,1,1,1,1
@@ -58,5 +47,3 @@ access_product_pricelist_sale_manager,product.pricelist salemanager,product.mode
access_product_group_res_partner_sale_manager,res_partner group_sale_manager,base.model_res_partner,base.group_sale_manager,1,1,1,0
access_product_pricelist_version_sale_manager,product.pricelist.version sale_manager,product.model_product_pricelist_version,base.group_sale_manager,1,1,1,1
access_account_invoice_report_salesman,account.invoice.report salesman,account.model_account_invoice_report,base.group_sale_salesman,1,0,0,0
-access_stock_warehouse_orderpoint_sale_salesman,stock.warehouse.orderpoint,procurement.model_stock_warehouse_orderpoint,base.group_sale_salesman,1,0,0,0
-access_account_move_line_salesman,account.move.line invoice,account.model_account_move_line,base.group_sale_salesman,1,0,0,0
diff --git a/addons/sale/security/sale_security.xml b/addons/sale/security/sale_security.xml
index 47a577e77c3..8b64b360435 100644
--- a/addons/sale/security/sale_security.xml
+++ b/addons/sale/security/sale_security.xml
@@ -25,21 +25,12 @@
-
- Enable Invoicing Delivery orders
-
- Addresses in Sale Orders
-
- Properties on lines
-
-
-
Discount on lines
diff --git a/addons/sale/test/cancel_order.yml b/addons/sale/test/cancel_order.yml
index cfdd0c7f079..afc629306fe 100644
--- a/addons/sale/test/cancel_order.yml
+++ b/addons/sale/test/cancel_order.yml
@@ -1,67 +1,20 @@
-
In order to test the cancel sale order.
--
- Now I cancel Quotation.
--
- !python {model: sale.order}: |
- self.action_cancel(cr, uid, [ref("order7")])
--
- I check state of Quotation after cancelled.
--
- !assert {model: sale.order, id: order7, string: sale order should be in cancel state}:
- - state == 'cancel'
--
- I set cancelled quotation to draft.
--
- !python {model: sale.order}: |
- self.action_cancel_draft(cr, uid, [ref("order7")])
--
- I confirm order.
+
+ First I confirm order.
-
!workflow {model: sale.order, action: order_confirm, ref: order7}
-
- I send delivery in two shipments, so I am doing a partial delivery order.
--
- !python {model: stock.picking}: |
- delivery_orders = self.search(cr, uid, [('sale_id','=',ref("order7"))])
- first_picking = self.browse(cr, uid, delivery_orders[0], context=context)
- if first_picking.force_assign(cr, uid, first_picking):
- first_move = first_picking.move_lines[0]
- values = {'move%s'%(first_move.id): {'product_qty': 5, 'product_uom':ref('product.product_uom_unit')}}
- first_picking.do_partial(values, context=context)
--
- Now I cancel latest shipment.
--
- !python {model: stock.picking}: |
- import netsvc
- delivery_orders = self.search(cr, uid, [('sale_id','=',ref("order7"))])
- last_delivery_order_id = delivery_orders[0]
- wf_service = netsvc.LocalService("workflow")
- wf_service.trg_validate(uid, 'stock.picking', last_delivery_order_id, 'button_cancel', cr)
--
- I run the scheduler.
--
- !python {model: procurement.order}: |
-
- self.run_scheduler(cr, uid)
--
- I check order status in "Ship Exception".
--
- !assert {model: sale.order, id: order7, string: Sale order should be in shipping exception}:
- - state == "shipping_except"
--
- Now I regenerate shipment.
--
- !workflow {model: sale.order, action: ship_recreate, ref: order7}
--
- I check state of order in 'To Invoice'.
+ I check state of order in 'Sale Order'.
-
!assert {model: sale.order, id: order7, string: Sale order should be In Progress state}:
- - state == 'manual'
+ - state == 'progress'
+-
+ I check that Invoice should be created.
-
- I make invoice for order.
--
- !workflow {model: sale.order, action: manual_invoice, ref: order7}
+ !python {model: sale.order}: |
+ sale_order = self.browse(cr, uid, ref("order7"))
+ assert len(sale_order.invoice_ids) == True, "Invoice should be created."
-
To cancel the sale order from Invoice Exception, I have to cancel the invoice of sale order.
-
@@ -80,9 +33,3 @@
Then I click on the Ignore Exception button.
-
!workflow {model: sale.order, action: invoice_corrected, ref: order7}
-
--
- I check state of order in 'In Progress'.
--
- !assert {model: sale.order, id: order7, string: Sale order should be In progress state}:
- - state == 'progress'
diff --git a/addons/sale/test/delete_order.yml b/addons/sale/test/delete_order.yml
index 2bbfed9771d..a42d5c34867 100644
--- a/addons/sale/test/delete_order.yml
+++ b/addons/sale/test/delete_order.yml
@@ -10,5 +10,5 @@
I make duplicate order and delete.
-
!python {model: sale.order}: |
- id = self.copy(cr, uid, ref('order'))
+ id = self.copy(cr, uid, ref('order4'))
self.unlink(cr, uid, [id])
diff --git a/addons/sale/test/edi_sale_order.yml b/addons/sale/test/edi_sale_order.yml
index af9a9b3aad6..d9fdb7ad8da 100644
--- a/addons/sale/test/edi_sale_order.yml
+++ b/addons/sale/test/edi_sale_order.yml
@@ -108,12 +108,12 @@
assert len(order_new.order_line) == 2, "Sale order lines mismatch"
for sale_line in order_new.order_line:
if sale_line.name == 'Basic PC':
- assert sale_line.delay == 18 , "incorrect delay: got %s, expected 18"%(sale_line.delay,)
+ # assert sale_line.delay == 18 , "incorrect delay: got %s, expected 18"%(sale_line.delay,)
assert sale_line.product_uom.name == "Unit" , "uom is not same"
assert sale_line.price_unit == 150 , "unit price is not same, got %s, expected 150"%(sale_line.price_unit,)
assert sale_line.product_uom_qty == 1 , "product qty is not same"
elif sale_line.name == 'Medium PC':
- assert sale_line.delay == 3 , "incorrect delay: got %s, expected 3"%(sale_line.delay,)
+ # assert sale_line.delay == 3 , "incorrect delay: got %s, expected 3"%(sale_line.delay,)
assert sale_line.product_uom.name == "Unit" , "uom is not same"
assert sale_line.price_unit == 100 , "unit price is not same, got %s, expected 100"%(sale_line.price_unit,)
assert sale_line.product_uom_qty == 2 , "product qty is not same"
diff --git a/addons/sale/test/prepaid_order_policy.yml b/addons/sale/test/prepaid_order_policy.yml
index 4f45baa8823..07754c03dfe 100644
--- a/addons/sale/test/prepaid_order_policy.yml
+++ b/addons/sale/test/prepaid_order_policy.yml
@@ -7,5 +7,4 @@
-
!python {model: sale.order}: |
sale_order = self.browse(cr, uid, ref("order3"))
- assert len(sale_order.picking_ids) == False, "Delivery order should not created before invoice."
assert sale_order.invoice_ids, "Invoice should be created."
diff --git a/addons/sale/wizard/__init__.py b/addons/sale/wizard/__init__.py
index 6cf076164d8..f243b959526 100644
--- a/addons/sale/wizard/__init__.py
+++ b/addons/sale/wizard/__init__.py
@@ -18,9 +18,6 @@
# along with this program. If not, see .
#
##############################################################################
-
-import sale_make_invoice
import sale_line_invoice
-import sale_make_invoice_advance
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/sale_crm/__openerp__.py b/addons/sale_crm/__openerp__.py
index b56d866f98b..f4137047fff 100644
--- a/addons/sale_crm/__openerp__.py
+++ b/addons/sale_crm/__openerp__.py
@@ -37,7 +37,7 @@ modules.
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'images': ['images/crm_statistics_dashboard.jpeg', 'images/opportunity_to_quote.jpeg'],
- 'depends': ['sale', 'crm'],
+ 'depends': ['sale_stock', 'crm'],
'init_xml': [],
'update_xml': ['wizard/crm_make_sale_view.xml',
'sale_crm_view.xml',
diff --git a/addons/sale_journal/__openerp__.py b/addons/sale_journal/__openerp__.py
index 11408161bf4..6373cce1810 100644
--- a/addons/sale_journal/__openerp__.py
+++ b/addons/sale_journal/__openerp__.py
@@ -49,7 +49,7 @@ Some statistics by journals are provided.
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'images': ['images/invoice_type.jpeg'],
- 'depends': ['sale'],
+ 'depends': ['sale_stock'],
'init_xml': ['sale_journal_data.xml'],
'update_xml': [
'security/ir.model.access.csv',
diff --git a/addons/sale_margin/__openerp__.py b/addons/sale_margin/__openerp__.py
index 936f5a6b350..4e622e71b33 100644
--- a/addons/sale_margin/__openerp__.py
+++ b/addons/sale_margin/__openerp__.py
@@ -31,7 +31,7 @@ Price and Cost Price.
""",
"author":"OpenERP SA",
"images":["images/sale_margin.jpeg"],
- "depends":["sale"],
+ "depends":["sale_stock"],
"demo_xml":[],
'test': ['test/sale_margin.yml'],
"update_xml":["security/ir.model.access.csv","sale_margin_view.xml"],
diff --git a/addons/sale_mrp/__openerp__.py b/addons/sale_mrp/__openerp__.py
index d5b3d6b7849..b1aed2c67b5 100644
--- a/addons/sale_mrp/__openerp__.py
+++ b/addons/sale_mrp/__openerp__.py
@@ -34,7 +34,7 @@ from sales order. It adds sales name and sales Reference on production order.
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'images': ['images/SO_to_MO.jpeg'],
- 'depends': ['mrp', 'sale'],
+ 'depends': ['mrp', 'sale_stock'],
'init_xml': [],
'update_xml': [
'security/ir.model.access.csv',
diff --git a/addons/sale_stock/__init__.py b/addons/sale_stock/__init__.py
new file mode 100644
index 00000000000..1b63b8b2b8b
--- /dev/null
+++ b/addons/sale_stock/__init__.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 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 .
+#
+##############################################################################
+
+import sale_stock
+import stock
+import wizard
+import report
+import company
+import res_config
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/sale_stock/__openerp__.py b/addons/sale_stock/__openerp__.py
new file mode 100644
index 00000000000..268e641cf41
--- /dev/null
+++ b/addons/sale_stock/__openerp__.py
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 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 .
+#
+##############################################################################
+
+{
+ 'name': 'Sale To Stock',
+ 'version': '1.0',
+ 'category': 'Hidden',
+ 'description': """
+This Module manage quotations and sales orders.
+===========================================================================
+
+Workflow with validation steps:
+-------------------------------
+ * Quotation -> Sales order -> Invoice
+
+Create Invoice:
+---------------
+ * Invoice on Demand
+ * Invoice on Delivery Order
+ * Invoice Before Delivery
+
+Partners preferences:
+---------------------
+ * Incoterm
+ * Shipping
+ * Invoicing
+
+Products stocks and prices:
+--------------------------
+
+Delivery method:
+-----------------
+ * The Poste
+ * Free Delivery Charges
+ * Normal Delivery Charges
+ * Based on the Delivery Order(if not Add to sale order)
+
+Dashboard for Sales Manager that includes:
+------------------------------------------
+ * My Quotations
+ * Monthly Turnover (Graph)
+ """,
+ 'author': 'OpenERP SA',
+ 'website': 'http://www.openerp.com',
+ 'images': [],
+ 'depends': ['sale', 'procurement'],
+ 'init_xml': [],
+ 'update_xml': ['wizard/sale_make_invoice_advance.xml',
+ 'wizard/sale_make_invoice.xml',
+ 'security/sale_stock_security.xml',
+ 'security/ir.model.access.csv',
+ 'company_view.xml',
+ 'sale_stock_view.xml',
+ 'sale_stock_workflow.xml',
+ 'res_config_view.xml',
+ 'report/sale_report_view.xml',
+ 'process/sale_stock_process.xml',
+ ],
+ 'data': ['sale_stock_data.xml'],
+ 'demo_xml': ['sale_stock_demo.xml'],
+ 'test': ['test/cancel_order_sale_stock.yml',
+ 'test/picking_order_policy.yml',
+ 'test/manual_order_policy.yml'
+ ],
+ 'installable': True,
+ 'auto_install': True,
+
+}
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/sale/company.py b/addons/sale_stock/company.py
similarity index 100%
rename from addons/sale/company.py
rename to addons/sale_stock/company.py
diff --git a/addons/sale/company_view.xml b/addons/sale_stock/company_view.xml
similarity index 100%
rename from addons/sale/company_view.xml
rename to addons/sale_stock/company_view.xml
diff --git a/addons/sale_stock/process/sale_stock_process.xml b/addons/sale_stock/process/sale_stock_process.xml
new file mode 100644
index 00000000000..cee587dca9b
--- /dev/null
+++ b/addons/sale_stock/process/sale_stock_process.xml
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/sale_stock/report/__init__.py b/addons/sale_stock/report/__init__.py
new file mode 100644
index 00000000000..418927acc78
--- /dev/null
+++ b/addons/sale_stock/report/__init__.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 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 .
+#
+##############################################################################
+import sale_report
\ No newline at end of file
diff --git a/addons/sale_stock/report/sale_report.py b/addons/sale_stock/report/sale_report.py
new file mode 100644
index 00000000000..5e9b74386b3
--- /dev/null
+++ b/addons/sale_stock/report/sale_report.py
@@ -0,0 +1,93 @@
+ # -*- coding: utf-8 -*-
+ ##############################################################################
+ #
+ # OpenERP, Open Source Management Solution
+ # Copyright (C) 2004-2010 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
+import tools
+class sale_report(osv.osv):
+ _inherit = "sale.report"
+ _columns = {
+ 'shipped': fields.boolean('Shipped', readonly=True),
+ 'shipped_qty_1': fields.integer('Shipped', readonly=True),
+ 'state': fields.selection([
+ ('draft', 'Quotation'),
+ ('waiting_date', 'Waiting Schedule'),
+ ('manual', 'Manual In Progress'),
+ ('progress', 'In Progress'),
+ ('shipping_except', 'Shipping Exception'),
+ ('invoice_except', 'Invoice Exception'),
+ ('done', 'Done'),
+ ('cancel', 'Cancelled')
+ ], 'Order State', readonly=True),
+ }
+
+ def init(self, cr):
+ tools.drop_view_if_exists(cr, 'sale_report')
+ cr.execute("""
+ create or replace view sale_report as (
+ select
+ min(l.id) as id,
+ l.product_id as product_id,
+ t.uom_id as product_uom,
+ sum(l.product_uom_qty / u.factor * u2.factor) as product_uom_qty,
+ sum(l.product_uom_qty * l.price_unit * (100.0-l.discount) / 100.0) as price_total,
+ 1 as nbr,
+ s.date_order as date,
+ s.date_confirm as date_confirm,
+ to_char(s.date_order, 'YYYY') as year,
+ to_char(s.date_order, 'MM') as month,
+ to_char(s.date_order, 'YYYY-MM-DD') as day,
+ s.partner_id as partner_id,
+ s.user_id as user_id,
+ s.shop_id as shop_id,
+ s.company_id as company_id,
+ extract(epoch from avg(date_trunc('day',s.date_confirm)-date_trunc('day',s.create_date)))/(24*60*60)::decimal(16,2) as delay,
+ s.state,
+ t.categ_id as categ_id,
+ s.shipped,
+ s.shipped::integer as shipped_qty_1,
+ s.pricelist_id as pricelist_id,
+ s.project_id as analytic_account_id
+ from
+ sale_order s
+ left join sale_order_line l on (s.id=l.order_id)
+ left join product_product p on (l.product_id=p.id)
+ left join product_template t on (p.product_tmpl_id=t.id)
+ left join product_uom u on (u.id=l.product_uom)
+ left join product_uom u2 on (u2.id=t.uom_id)
+ group by
+ l.product_id,
+ l.product_uom_qty,
+ l.order_id,
+ t.uom_id,
+ t.categ_id,
+ s.date_order,
+ s.date_confirm,
+ s.partner_id,
+ s.user_id,
+ s.shop_id,
+ s.company_id,
+ s.state,
+ s.shipped,
+ s.pricelist_id,
+ s.project_id
+ )
+ """)
+sale_report()
diff --git a/addons/sale_stock/report/sale_report_view.xml b/addons/sale_stock/report/sale_report_view.xml
new file mode 100644
index 00000000000..99aefa7e66f
--- /dev/null
+++ b/addons/sale_stock/report/sale_report_view.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ sale.report.tree.sale.stock
+ sale.report
+
+ tree
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/addons/sale_stock/res_config.py b/addons/sale_stock/res_config.py
new file mode 100644
index 00000000000..30ee56753fe
--- /dev/null
+++ b/addons/sale_stock/res_config.py
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Business Applications
+# Copyright (C) 2004-2012 OpenERP S.A. ().
+#
+# 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
+import pooler
+from tools.translate import _
+
+class sale_configuration(osv.osv_memory):
+ _inherit = 'sale.config.settings'
+ _columns = {
+ 'group_invoice_deli_orders': fields.boolean('Based on Delivery Orders',
+ implied_group='group_invoice_deli_orders',
+ help="To allow your salesman to make invoices for Delivery Orders using the menu 'Deliveries to Invoice'."),
+ 'task_work': fields.boolean('Based on Task Activities',
+ help="""Lets you transfer the entries under tasks defined for Project Management to
+ the Timesheet line entries for particular date and particular user with the effect of creating, editing and deleting either ways
+ and to automatically creates project tasks from procurement lines.
+ This installs the modules project_timesheet and project_mrp."""),
+ 'default_order_policy': fields.selection(
+ [('manual', 'Invoice Based on Sales Orders'), ('picking', 'Invoice Based on Deliveries')],
+ 'Default Method', default_model='sale.order',
+ help="You can generate invoices based on sales orders or based on shippings."),
+ 'module_delivery': fields.boolean('Allow Charging Shipping Costs',
+ help ="""Allows you to add delivery methods in sale orders and delivery orders.
+ You can define your own carrier and delivery grids for prices.
+ This installs the module delivery."""),
+ 'default_picking_policy' : fields.boolean("Configurable Shipping Policy",
+ help = "You will be able to configure, per sale order, if you deliver all products at once or if you deliver each product when it is available. This may have an impact on the shipping price."),
+ 'group_mrp_properties': fields.boolean('Properties on Lines',
+ implied_group='sale.group_mrp_properties',
+ help="Allows you to tag sale order lines with properties."),
+ 'group_multiple_shops': fields.boolean("Manage Multiple Shops",
+ implied_group='stock.group_locations',
+ help="This allows to configure and use multiple shops."),
+ 'module_project_timesheet': fields.boolean("Project Timesheet"),
+ 'module_project_mrp': fields.boolean("Project MRP"),
+
+ }
+
+ def default_get(self, cr, uid, fields, context=None):
+ res = super(sale_configuration, self).default_get(cr, uid, fields, context)
+ # task_work, time_unit depend on other fields
+ res['task_work'] = res.get('module_project_mrp') and res.get('module_project_timesheet')
+ return res
+
+ def get_default_sale_config(self, cr, uid, ids, context=None):
+ ir_values = self.pool.get('ir.values')
+ default_picking_policy = ir_values.get_default(cr, uid, 'sale.order', 'picking_policy')
+ return {
+ 'default_picking_policy': default_picking_policy == 'one',
+ }
+
+ def set_sale_defaults(self, cr, uid, ids, context=None):
+ ir_values = self.pool.get('ir.values')
+ ir_model_data = self.pool.get('ir.model.data')
+ wizard = self.browse(cr, uid, ids)[0]
+
+ default_picking_policy = 'one' if wizard.default_picking_policy else 'direct'
+ ir_values.set_default(cr, uid, 'sale.order', 'picking_policy', default_picking_policy)
+ res = super(sale_configuration, self).set_sale_defaults(cr, uid, ids, context)
+ return res
+
+ def onchange_invoice_methods(self, cr, uid, ids, group_invoice_so_lines, group_invoice_deli_orders, context=None):
+ if not group_invoice_deli_orders:
+ return {'value': {'default_order_policy': 'manual'}}
+ if not group_invoice_so_lines:
+ return {'value': {'default_order_policy': 'picking'}}
+ return {}
diff --git a/addons/sale_stock/res_config_view.xml b/addons/sale_stock/res_config_view.xml
new file mode 100644
index 00000000000..e68aa3b5662
--- /dev/null
+++ b/addons/sale_stock/res_config_view.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+ sale settings
+ sale.config.settings
+ form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py
new file mode 100644
index 00000000000..3c43587a199
--- /dev/null
+++ b/addons/sale_stock/sale_stock.py
@@ -0,0 +1,639 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 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 datetime import datetime, timedelta
+from tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, DATETIME_FORMATS_MAP, float_compare
+from dateutil.relativedelta import relativedelta
+from osv import fields, osv
+import netsvc
+from tools.translate import _
+
+class sale_shop(osv.osv):
+ _inherit = "sale.shop"
+ _columns = {
+ 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'),
+ }
+
+class sale_order(osv.osv):
+ _inherit = "sale.order"
+
+ def copy(self, cr, uid, id, default=None, context=None):
+ if not default:
+ default = {}
+ default.update({
+ 'shipped': False,
+ 'picking_ids': [],
+ })
+ return super(sale_order, self).copy(cr, uid, id, default, context=context)
+
+ def shipping_policy_change(self, cr, uid, ids, policy, context=None):
+ if not policy:
+ return {}
+ inv_qty = 'order'
+ if policy == 'prepaid':
+ inv_qty = 'order'
+ elif policy == 'picking':
+ inv_qty = 'procurement'
+ return {'value': {'invoice_quantity': inv_qty}}
+
+ def write(self, cr, uid, ids, vals, context=None):
+ if vals.get('order_policy', False):
+ if vals['order_policy'] == 'prepaid':
+ vals.update({'invoice_quantity': 'order'})
+ elif vals['order_policy'] == 'picking':
+ vals.update({'invoice_quantity': 'procurement'})
+ return super(sale_order, self).write(cr, uid, ids, vals, context=context)
+
+ def create(self, cr, uid, vals, context=None):
+ if vals.get('order_policy', False):
+ if vals['order_policy'] == 'prepaid':
+ vals.update({'invoice_quantity': 'order'})
+ if vals['order_policy'] == 'picking':
+ vals.update({'invoice_quantity': 'procurement'})
+ order = super(sale_order, self).create(cr, uid, vals, context=context)
+ return order
+
+ # This is False
+ def _picked_rate(self, cr, uid, ids, name, arg, context=None):
+ if not ids:
+ return {}
+ res = {}
+ tmp = {}
+ for id in ids:
+ tmp[id] = {'picked': 0.0, 'total': 0.0}
+ cr.execute('''SELECT
+ p.sale_id as sale_order_id, sum(m.product_qty) as nbr, mp.state as procurement_state, m.state as move_state, p.type as picking_type
+ FROM
+ stock_move m
+ LEFT JOIN
+ stock_picking p on (p.id=m.picking_id)
+ LEFT JOIN
+ procurement_order mp on (mp.move_id=m.id)
+ WHERE
+ p.sale_id IN %s GROUP BY m.state, mp.state, p.sale_id, p.type''', (tuple(ids),))
+
+ for item in cr.dictfetchall():
+ if item['move_state'] == 'cancel':
+ continue
+
+ if item['picking_type'] == 'in':#this is a returned picking
+ tmp[item['sale_order_id']]['total'] -= item['nbr'] or 0.0 # Deducting the return picking qty
+ if item['procurement_state'] == 'done' or item['move_state'] == 'done':
+ tmp[item['sale_order_id']]['picked'] -= item['nbr'] or 0.0
+ else:
+ tmp[item['sale_order_id']]['total'] += item['nbr'] or 0.0
+ if item['procurement_state'] == 'done' or item['move_state'] == 'done':
+ tmp[item['sale_order_id']]['picked'] += item['nbr'] or 0.0
+
+ for order in self.browse(cr, uid, ids, context=context):
+ if order.shipped:
+ res[order.id] = 100.0
+ else:
+ res[order.id] = tmp[order.id]['total'] and (100.0 * tmp[order.id]['picked'] / tmp[order.id]['total']) or 0.0
+ return res
+
+ _columns = {
+ 'state': fields.selection([
+ ('draft', 'Draft Quotation'),
+ ('sent', 'Quotation Sent'),
+ ('cancel', 'Cancelled'),
+ ('waiting_date', 'Waiting Schedule'),
+ ('progress', 'Sale Order'),
+ ('manual', 'Sale to Invoice'),
+ ('shipping_except', 'Shipping Exception'),
+ ('invoice_except', 'Invoice Exception'),
+ ('done', 'Done'),
+ ], 'Status', readonly=True,help="Gives the state of the quotation or sales order.\
+ \nThe exception state is automatically set when a cancel operation occurs \
+ in the invoice validation (Invoice Exception) or in the picking list process (Shipping Exception).\nThe 'Waiting Schedule' state is set when the invoice is confirmed\
+ but waiting for the scheduler to run on the order date.", select=True),
+ 'incoterm': fields.many2one('stock.incoterms', 'Incoterm', help="Incoterm which stands for 'International Commercial terms' implies its a series of sales terms which are used in the commercial transaction."),
+ 'picking_policy': fields.selection([('direct', 'Deliver each product when available'), ('one', 'Deliver all products at once')],
+ 'Shipping Policy', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
+ help="""If you don't have enough stock available to deliver all at once, do you accept partial shipments or not?"""),
+ 'order_policy': fields.selection([
+ ('manual', 'On Demand'),
+ ('picking', 'On Delivery Order'),
+ ('prepaid', 'Before Delivery'),
+ ], 'Create Invoice', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
+ help="""This field controls how invoice and delivery operations are synchronized.
+ - With 'On Demand', the invoice is created manually when needed.
+ - With 'On Delivery Order', a draft invoice is generated after all pickings have been processed.
+ - With 'Before Delivery', a draft invoice is created, and it must be paid before delivery."""),
+ 'picking_ids': fields.one2many('stock.picking.out', 'sale_id', 'Related Picking', readonly=True, help="This is a list of delivery orders that has been generated for this sales order."),
+ 'shipped': fields.boolean('Delivered', readonly=True, help="It indicates that the sales order has been delivered. This field is updated only after the scheduler(s) have been launched."),
+ 'picked_rate': fields.function(_picked_rate, string='Picked', type='float'),
+ 'invoice_quantity': fields.selection([('order', 'Ordered Quantities'), ('procurement', 'Shipped Quantities')], 'Invoice on',
+ help="The sale order will automatically create the invoice proposition (draft invoice).\
+ You have to choose if you want your invoice based on ordered ", required=True, readonly=True, states={'draft': [('readonly', False)]}),
+ }
+ _defaults = {
+ 'picking_policy': 'direct',
+ 'order_policy': 'manual',
+ 'invoice_quantity': 'order',
+ }
+
+ # Form filling
+ def unlink(self, cr, uid, ids, context=None):
+ sale_orders = self.read(cr, uid, ids, ['state'], context=context)
+ unlink_ids = []
+ for s in sale_orders:
+ if s['state'] in ['draft', 'cancel']:
+ unlink_ids.append(s['id'])
+ else:
+ raise osv.except_osv(_('Invalid action !'), _('In order to delete a confirmed sale order, you must cancel it before ! To cancel a sale order, you must first cancel related picking or delivery orders.'))
+
+ return osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
+
+
+
+ def action_view_delivery(self, cr, uid, ids, context=None):
+ '''
+ This function returns an action that display existing delivery orders of given sale order ids. It can either be a in a list or in a form view, if there is only one delivery order to show.
+ '''
+ mod_obj = self.pool.get('ir.model.data')
+ result = {
+ 'name': _('Delivery Order'),
+ 'view_type': 'form',
+ 'res_model': 'stock.picking',
+ 'context': "{'type':'out'}",
+ 'type': 'ir.actions.act_window',
+ 'nodestroy': True,
+ 'target': 'current',
+ }
+ #compute the number of delivery orders to display
+ pick_ids = []
+ for so in self.browse(cr, uid, ids, context=context):
+ pick_ids += [picking.id for picking in so.picking_ids]
+ #choose the view_mode accordingly
+ if len(pick_ids) > 1:
+ res = mod_obj.get_object_reference(cr, uid, 'stock', 'view_picking_out_tree')
+ result.update({
+ 'view_mode': 'tree,form',
+ 'res_id': pick_ids or False
+ })
+ else:
+ res = mod_obj.get_object_reference(cr, uid, 'stock', 'view_picking_out_form')
+ result.update({
+ 'view_mode': 'form',
+ 'res_id': pick_ids and pick_ids[0] or False,
+ })
+ result.update(view_id = res and res[1] or False)
+ return result
+
+ def action_wait(self, cr, uid, ids, context=None):
+ 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.'))
+ if (o.order_policy == 'manual'):
+ self.write(cr, uid, [o.id], {'state': 'manual', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)})
+ else:
+ self.write(cr, uid, [o.id], {'state': 'progress', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)})
+ self.pool.get('sale.order.line').button_confirm(cr, uid, [x.id for x in o.order_line])
+ self.confirm_send_note(cr, uid, ids, context)
+ return True
+
+ def action_invoice_create(self, cr, uid, ids, grouped=False, states=['confirmed', 'done', 'exception'], date_inv = False, context=None):
+ res = False
+ invoices = {}
+ invoice_ids = []
+ picking_obj = self.pool.get('stock.picking')
+ invoice = self.pool.get('account.invoice')
+ obj_sale_order_line = self.pool.get('sale.order.line')
+ partner_currency = {}
+ if context is None:
+ context = {}
+ # If date was specified, use it as date invoiced, usefull when invoices are generated this month and put the
+ # last day of the last month as invoice date
+ if date_inv:
+ context['date_inv'] = date_inv
+ for o in self.browse(cr, uid, ids, context=context):
+ currency_id = o.pricelist_id.currency_id.id
+ if (o.partner_id.id in partner_currency) and (partner_currency[o.partner_id.id] <> currency_id):
+ raise osv.except_osv(
+ _('Error !'),
+ _('You cannot group sales having different currencies for the same partner.'))
+
+ partner_currency[o.partner_id.id] = currency_id
+ lines = []
+ for line in o.order_line:
+ if line.invoiced:
+ continue
+ elif (line.state in states):
+ lines.append(line.id)
+ created_lines = obj_sale_order_line.invoice_line_create(cr, uid, lines)
+ if created_lines:
+ invoices.setdefault(o.partner_id.id, []).append((o, created_lines))
+ if not invoices:
+ for o in self.browse(cr, uid, ids, context=context):
+ for i in o.invoice_ids:
+ if i.state == 'draft':
+ return i.id
+ for val in invoices.values():
+ if grouped:
+ res = self._make_invoice(cr, uid, val[0][0], reduce(lambda x, y: x + y, [l for o, l in val], []), context=context)
+ invoice_ref = ''
+ for o, l in val:
+ invoice_ref += o.name + '|'
+ self.write(cr, uid, [o.id], {'state': 'progress'})
+ if o.order_policy == 'picking':
+ picking_obj.write(cr, uid, map(lambda x: x.id, o.picking_ids), {'invoice_state': 'invoiced'})
+ cr.execute('insert into sale_order_invoice_rel (order_id,invoice_id) values (%s,%s)', (o.id, res))
+ invoice.write(cr, uid, [res], {'origin': invoice_ref, 'name': invoice_ref})
+ else:
+ for order, il in val:
+ res = self._make_invoice(cr, uid, order, il, context=context)
+ invoice_ids.append(res)
+ self.write(cr, uid, [order.id], {'state': 'progress'})
+ if order.order_policy == 'picking':
+ picking_obj.write(cr, uid, map(lambda x: x.id, order.picking_ids), {'invoice_state': 'invoiced'})
+ cr.execute('insert into sale_order_invoice_rel (order_id,invoice_id) values (%s,%s)', (order.id, res))
+ if res:
+ self.invoice_send_note(cr, uid, ids, res, context)
+ return res
+
+ def action_cancel(self, cr, uid, ids, context=None):
+ wf_service = netsvc.LocalService("workflow")
+ if context is None:
+ context = {}
+ sale_order_line_obj = self.pool.get('sale.order.line')
+ proc_obj = self.pool.get('procurement.order')
+ for sale in self.browse(cr, uid, ids, context=context):
+ for pick in sale.picking_ids:
+ if pick.state not in ('draft', 'cancel'):
+ raise osv.except_osv(
+ _('Could not cancel sales order !'),
+ _('You must first cancel all picking attached to this sales order.'))
+ if pick.state == 'cancel':
+ for mov in pick.move_lines:
+ proc_ids = proc_obj.search(cr, uid, [('move_id', '=', mov.id)])
+ if proc_ids:
+ for proc in proc_ids:
+ wf_service.trg_validate(uid, 'procurement.order', proc, 'button_check', cr)
+ for r in self.read(cr, uid, ids, ['picking_ids']):
+ for pick in r['picking_ids']:
+ wf_service.trg_validate(uid, 'stock.picking', pick, 'button_cancel', cr)
+ return super(sale_order, self).action_cancel(cr, uid, ids, context=context)
+
+ def procurement_lines_get(self, cr, uid, ids, *args):
+ res = []
+ for order in self.browse(cr, uid, ids, context={}):
+ for line in order.order_line:
+ if line.procurement_id:
+ res.append(line.procurement_id.id)
+ return res
+
+ # if mode == 'finished':
+ # returns True if all lines are done, False otherwise
+ # if mode == 'canceled':
+ # returns True if there is at least one canceled line, False otherwise
+ def test_state(self, cr, uid, ids, mode, *args):
+ assert mode in ('finished', 'canceled'), _("invalid mode for test_state")
+ finished = True
+ canceled = False
+ notcanceled = False
+ write_done_ids = []
+ write_cancel_ids = []
+ for order in self.browse(cr, uid, ids, context={}):
+ for line in order.order_line:
+ if (not line.procurement_id) or (line.procurement_id.state=='done'):
+ if line.state != 'done':
+ write_done_ids.append(line.id)
+ else:
+ finished = False
+ if line.procurement_id:
+ if (line.procurement_id.state == 'cancel'):
+ canceled = True
+ if line.state != 'exception':
+ write_cancel_ids.append(line.id)
+ else:
+ notcanceled = True
+ if write_done_ids:
+ self.pool.get('sale.order.line').write(cr, uid, write_done_ids, {'state': 'done'})
+ if write_cancel_ids:
+ self.pool.get('sale.order.line').write(cr, uid, write_cancel_ids, {'state': 'exception'})
+
+ if mode == 'finished':
+ return finished
+ elif mode == 'canceled':
+ return canceled
+ if notcanceled:
+ return False
+ return canceled
+
+ def _prepare_order_line_procurement(self, cr, uid, order, line, move_id, date_planned, context=None):
+ return {
+ 'name': line.name.split('\n')[0],
+ 'origin': order.name,
+ 'date_planned': date_planned,
+ 'product_id': line.product_id.id,
+ 'product_qty': line.product_uom_qty,
+ 'product_uom': line.product_uom.id,
+ 'product_uos_qty': (line.product_uos and line.product_uos_qty)\
+ or line.product_uom_qty,
+ 'product_uos': (line.product_uos and line.product_uos.id)\
+ or line.product_uom.id,
+ 'location_id': order.shop_id.warehouse_id.lot_stock_id.id,
+ 'procure_method': line.type,
+ 'move_id': move_id,
+ 'company_id': order.company_id.id,
+ 'note': '\n'.join(line.name.split('\n')[1:]),
+ 'property_ids': [(6, 0, [x.id for x in line.property_ids])]
+ }
+
+ def _prepare_order_line_move(self, cr, uid, order, line, picking_id, date_planned, context=None):
+ location_id = order.shop_id.warehouse_id.lot_stock_id.id
+ output_id = order.shop_id.warehouse_id.lot_output_id.id
+ return {
+ 'name': line.name.split('\n')[0][:250],
+ 'picking_id': picking_id,
+ 'product_id': line.product_id.id,
+ 'date': date_planned,
+ 'date_expected': date_planned,
+ 'product_qty': line.product_uom_qty,
+ 'product_uom': line.product_uom.id,
+ 'product_uos_qty': (line.product_uos and line.product_uos_qty) or line.product_uom_qty,
+ 'product_uos': (line.product_uos and line.product_uos.id)\
+ or line.product_uom.id,
+ 'product_packaging': line.product_packaging.id,
+ 'partner_id': line.address_allotment_id.id or order.partner_shipping_id.id,
+ 'location_id': location_id,
+ 'location_dest_id': output_id,
+ 'sale_line_id': line.id,
+ 'tracking_id': False,
+ 'state': 'draft',
+ #'state': 'waiting',
+ 'note': '\n'.join(line.name.split('\n')[1:]),
+ 'company_id': order.company_id.id,
+ 'price_unit': line.product_id.standard_price or 0.0
+ }
+
+ def _prepare_order_picking(self, cr, uid, order, context=None):
+ pick_name = self.pool.get('ir.sequence').get(cr, uid, 'stock.picking.out')
+ return {
+ 'name': pick_name,
+ 'origin': order.name,
+ 'date': order.date_order,
+ 'type': 'out',
+ 'state': 'auto',
+ 'move_type': order.picking_policy,
+ 'sale_id': order.id,
+ 'partner_id': order.partner_shipping_id.id,
+ 'note': order.note,
+ 'invoice_state': (order.order_policy=='picking' and '2binvoiced') or 'none',
+ 'company_id': order.company_id.id,
+ }
+
+ def ship_recreate(self, cr, uid, order, line, move_id, proc_id):
+ # FIXME: deals with potentially cancelled shipments, seems broken (specially if shipment has production lot)
+ """
+ Define ship_recreate for process after shipping exception
+ param order: sale order to which the order lines belong
+ param line: sale order line records to procure
+ param move_id: the ID of stock move
+ param proc_id: the ID of procurement
+ """
+ move_obj = self.pool.get('stock.move')
+ if order.state == 'shipping_except':
+ for pick in order.picking_ids:
+ for move in pick.move_lines:
+ if move.state == 'cancel':
+ mov_ids = move_obj.search(cr, uid, [('state', '=', 'cancel'),('sale_line_id', '=', line.id),('picking_id', '=', pick.id)])
+ if mov_ids:
+ for mov in move_obj.browse(cr, uid, mov_ids):
+ # FIXME: the following seems broken: what if move_id doesn't exist? What if there are several mov_ids? Shouldn't that be a sum?
+ move_obj.write(cr, uid, [move_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty})
+ self.pool.get('procurement.order').write(cr, uid, [proc_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty})
+ return True
+
+ def _get_date_planned(self, cr, uid, order, line, start_date, context=None):
+ date_planned = datetime.strptime(start_date, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(days=line.delay or 0.0)
+ date_planned = (date_planned - timedelta(days=order.company_id.security_lead)).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
+ return date_planned
+
+ def _create_pickings_and_procurements(self, cr, uid, order, order_lines, picking_id=False, context=None):
+ """Create the required procurements to supply sale order lines, also connecting
+ the procurements to appropriate stock moves in order to bring the goods to the
+ sale order's requested location.
+
+ If ``picking_id`` is provided, the stock moves will be added to it, otherwise
+ a standard outgoing picking will be created to wrap the stock moves, as returned
+ by :meth:`~._prepare_order_picking`.
+
+ Modules that wish to customize the procurements or partition the stock moves over
+ multiple stock pickings may override this method and call ``super()`` with
+ different subsets of ``order_lines`` and/or preset ``picking_id`` values.
+
+ :param browse_record order: sale order to which the order lines belong
+ :param list(browse_record) order_lines: sale order line records to procure
+ :param int picking_id: optional ID of a stock picking to which the created stock moves
+ will be added. A new picking will be created if ommitted.
+ :return: True
+ """
+ move_obj = self.pool.get('stock.move')
+ picking_obj = self.pool.get('stock.picking')
+ procurement_obj = self.pool.get('procurement.order')
+ proc_ids = []
+
+ for line in order_lines:
+ if line.state == 'done':
+ continue
+
+ date_planned = self._get_date_planned(cr, uid, order, line, order.date_order, context=context)
+
+ if line.product_id:
+ if line.product_id.product_tmpl_id.type in ('product', 'consu'):
+ if not picking_id:
+ picking_id = picking_obj.create(cr, uid, self._prepare_order_picking(cr, uid, order, context=context))
+ move_id = move_obj.create(cr, uid, self._prepare_order_line_move(cr, uid, order, line, picking_id, date_planned, context=context))
+ else:
+ # a service has no stock move
+ move_id = False
+
+ proc_id = procurement_obj.create(cr, uid, self._prepare_order_line_procurement(cr, uid, order, line, move_id, date_planned, context=context))
+ proc_ids.append(proc_id)
+ line.write({'procurement_id': proc_id})
+ self.ship_recreate(cr, uid, order, line, move_id, proc_id)
+
+ wf_service = netsvc.LocalService("workflow")
+ if picking_id:
+ wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr)
+ self.delivery_send_note(cr, uid, [order.id], picking_id, context)
+
+
+ for proc_id in proc_ids:
+ wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_confirm', cr)
+
+ val = {}
+ if order.state == 'shipping_except':
+ val['state'] = 'progress'
+ val['shipped'] = False
+
+ if (order.order_policy == 'manual'):
+ for line in order.order_line:
+ if (not line.invoiced) and (line.state not in ('cancel', 'draft')):
+ val['state'] = 'manual'
+ break
+ order.write(val)
+ return True
+
+ def action_ship_create(self, cr, uid, ids, context=None):
+ for order in self.browse(cr, uid, ids, context=context):
+ self._create_pickings_and_procurements(cr, uid, order, order.order_line, None, context=context)
+ return True
+
+ def action_ship_end(self, cr, uid, ids, context=None):
+ for order in self.browse(cr, uid, ids, context=context):
+ val = {'shipped': True}
+ if order.state == 'shipping_except':
+ val['state'] = 'progress'
+ if (order.order_policy == 'manual'):
+ for line in order.order_line:
+ if (not line.invoiced) and (line.state not in ('cancel', 'draft')):
+ val['state'] = 'manual'
+ break
+ for line in order.order_line:
+ towrite = []
+ if line.state == 'exception':
+ towrite.append(line.id)
+ if towrite:
+ self.pool.get('sale.order.line').write(cr, uid, towrite, {'state': 'done'}, context=context)
+ res = self.write(cr, uid, [order.id], val)
+ if res:
+ self.delivery_end_send_note(cr, uid, [order.id], context=context)
+ return True
+
+ def has_stockable_products(self, cr, uid, ids, *args):
+ for order in self.browse(cr, uid, ids):
+ for order_line in order.order_line:
+ if order_line.product_id and order_line.product_id.product_tmpl_id.type in ('product', 'consu'):
+ return True
+ return False
+ # ------------------------------------------------
+ # OpenChatter methods and notifications
+ # ------------------------------------------------
+
+ def get_needaction_user_ids(self, cr, uid, ids, context=None):
+ result = super(sale_order, self).get_needaction_user_ids(cr, uid, ids, context=context)
+ for obj in self.browse(cr, uid, ids, context=context):
+ if (obj.state == 'manual' or obj.state == 'progress'):
+ result[obj.id].append(obj.user_id.id)
+ return result
+
+ def delivery_send_note(self, cr, uid, ids, picking_id, context=None):
+ for order in self.browse(cr, uid, ids, context=context):
+ for picking in (pck for pck in order.picking_ids if pck.id == picking_id):
+ # convert datetime field to a datetime, using server format, then
+ # convert it to the user TZ and re-render it with %Z to add the timezone
+ picking_datetime = fields.DT.datetime.strptime(picking.min_date, DEFAULT_SERVER_DATETIME_FORMAT)
+ picking_date_str = fields.datetime.context_timestamp(cr, uid, picking_datetime, context=context).strftime(DATETIME_FORMATS_MAP['%+'] + " (%Z)")
+ self.message_append_note(cr, uid, [order.id], body=_("Delivery Order %sscheduled for %s.") % (picking.name, picking_date_str), context=context)
+
+ def delivery_end_send_note(self, cr, uid, ids, context=None):
+ self.message_append_note(cr, uid, ids, body=_("Order delivered."), context=context)
+
+
+class sale_order_line(osv.osv):
+
+ def _number_packages(self, cr, uid, ids, field_name, arg, context=None):
+ res = {}
+ for line in self.browse(cr, uid, ids, context=context):
+ try:
+ res[line.id] = int((line.product_uom_qty+line.product_packaging.qty-0.0001) / line.product_packaging.qty)
+ except:
+ res[line.id] = 1
+ return res
+
+ _inherit = 'sale.order.line'
+ _columns = {
+ 'delay': fields.float('Delivery Lead Time', required=True, help="Number of days between the order confirmation the shipping of the products to the customer", readonly=True, states={'draft': [('readonly', False)]}),
+ 'procurement_id': fields.many2one('procurement.order', 'Procurement'),
+ 'type': fields.selection([('make_to_stock', 'from stock'), ('make_to_order', 'on order')], 'Procurement Method', required=True, readonly=True, states={'draft': [('readonly', False)]},
+ help="If 'on order', it triggers a procurement when the sale order is confirmed to create a task, purchase order or manufacturing order linked to this sale order line."),
+ 'property_ids': fields.many2many('mrp.property', 'sale_order_line_property_rel', 'order_id', 'property_id', 'Properties', readonly=True, states={'draft': [('readonly', False)]}),
+ 'product_packaging': fields.many2one('product.packaging', 'Packaging'),
+ 'move_ids': fields.one2many('stock.move', 'sale_line_id', 'Inventory Moves', readonly=True),
+ 'number_packages': fields.function(_number_packages, type='integer', string='Number Packages'),
+
+ }
+ _defaults = {
+ 'delay': 0.0,
+ 'type': 'make_to_stock',
+ 'product_packaging': False,
+ }
+
+ def _prepare_order_line_invoice_line(self, cr, uid, line, account_id=False, context=None):
+ def _get_line_qty(line):
+ if not (line.order_id.invoice_quantity=='order') or line.procurement_id:
+ return self.pool.get('procurement.order').quantity_get(cr, uid, line.procurement_id.id, context=context)
+
+ def _get_line_uom(line):
+ if not (line.order_id.invoice_quantity=='order') or line.procurement_id:
+ return self.pool.get('procurement.order').uom_get(cr, uid, line.procurement_id.id, context=context)
+
+ return super(sale_order_line, self)._prepare_order_line_invoice_line(cr, uid, line, account_id=account_id, context=context)
+
+ def product_packaging_change(self, cr, uid, ids, pricelist, product, qty=0, uom=False,
+ partner_id=False, packaging=False, flag=False, context=None):
+ if not product:
+ return {'value': {'product_packaging': False}}
+ product_obj = self.pool.get('product.product')
+ product_uom_obj = self.pool.get('product.uom')
+ pack_obj = self.pool.get('product.packaging')
+ warning = {}
+ result = {}
+ warning_msgs = ''
+ if flag:
+ res = self.product_id_change(cr, uid, ids, pricelist=pricelist,
+ product=product, qty=qty, uom=uom, partner_id=partner_id,
+ packaging=packaging, flag=False, context=context)
+ warning_msgs = res.get('warning') and res['warning']['message']
+
+ products = product_obj.browse(cr, uid, product, context=context)
+ if not products.packaging:
+ packaging = result['product_packaging'] = False
+ elif not packaging and products.packaging and not flag:
+ packaging = products.packaging[0].id
+ result['product_packaging'] = packaging
+
+ if packaging:
+ default_uom = products.uom_id and products.uom_id.id
+ pack = pack_obj.browse(cr, uid, packaging, context=context)
+ q = product_uom_obj._compute_qty(cr, uid, uom, pack.qty, default_uom)
+# qty = qty - qty % q + q
+ if qty and (q and not (qty % q) == 0):
+ ean = pack.ean or _('(n/a)')
+ qty_pack = pack.qty
+ type_ul = pack.ul
+ if not warning_msgs:
+ warn_msg = _("You selected a quantity of %d Units.\n"
+ "But it's not compatible with the selected packaging.\n"
+ "Here is a proposition of quantities according to the packaging:\n"
+ "EAN: %s Quantity: %s Type of ul: %s") % \
+ (qty, ean, qty_pack, type_ul.name)
+ warning_msgs += _("Picking Information ! : ") + warn_msg + "\n\n"
+ warning = {
+ 'title': _('Configuration Error !'),
+ 'message': warning_msgs
+ }
+ result['product_uom_qty'] = qty
+
+ return {'value': result, 'warning': warning}
+
\ No newline at end of file
diff --git a/addons/sale_stock/sale_stock_data.xml b/addons/sale_stock/sale_stock_data.xml
new file mode 100644
index 00000000000..2957f4556fa
--- /dev/null
+++ b/addons/sale_stock/sale_stock_data.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/addons/sale_stock/sale_stock_demo.xml b/addons/sale_stock/sale_stock_demo.xml
new file mode 100644
index 00000000000..d336cd0c37e
--- /dev/null
+++ b/addons/sale_stock/sale_stock_demo.xml
@@ -0,0 +1,109 @@
+
+
+
+
+
+ manual
+
+
+
+
+
+ manual
+
+
+
+ manual
+
+
+
+ manual
+
+
+
+
+
+ picking
+ procurement
+ Invoice after delivery
+
+
+
+ make_to_stock
+
+
+
+ make_to_stock
+
+
+
+ make_to_order
+
+
+
+ make_to_order
+
+
+
+ 2
+
+
+
+ 7
+ make_to_order
+
+
+
+ 8
+ make_to_order
+
+
+
+ make_to_order
+ 1
+
+
+
+ make_to_order
+ 15
+
+
+
+ make_to_stock
+
+
+
+ 1
+ make_to_stock
+
+
+
+
+ make_to_stock
+
+
+
+ make_to_order
+ 15
+
+
+
+ make_to_order
+ 15
+
+
+
+ make_to_stock
+ 15
+
+
+
+ make_to_stock
+ 15
+
+
+
+
+
+
+
diff --git a/addons/sale_stock/sale_stock_view.xml b/addons/sale_stock/sale_stock_view.xml
new file mode 100644
index 00000000000..47a33ea0179
--- /dev/null
+++ b/addons/sale_stock/sale_stock_view.xml
@@ -0,0 +1,150 @@
+
+
+
+
+
+
+
+ sale.shop.sale.stock
+ sale.shop
+
+ tree
+
+
+
+
+
+
+
+
+
+ sale.order.tree.sale.stock
+ sale.order
+
+ tree
+
+
+
+
+
+
+
+
+ sale.order.form.sale.stock
+ sale.order
+
+ form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ days
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/sale_stock/sale_stock_workflow.xml b/addons/sale_stock/sale_stock_workflow.xml
new file mode 100644
index 00000000000..0bea307292c
--- /dev/null
+++ b/addons/sale_stock/sale_stock_workflow.xml
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+ wait_ship
+
+
+
+
+ cancel3
+ True
+ stopall
+ action_cancel()
+
+
+
+
+ ship
+ function
+ action_ship_create()
+
+
+
+
+ ship_except
+ function
+ write({'state':'shipping_except'})
+
+
+
+
+ ship_end
+ function
+ action_ship_end()
+
+
+
+
+ ship_cancel
+ True
+ stopall
+ action_cancel()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (order_policy=='picking')
+
+
+
+
+
+ cancel
+
+
+
+
+
+ (order_policy!='prepaid') or invoiced
+
+
+
+
+
+ manual_invoice
+
+
+
+
+
+
+
+
+
+
+ procurement.order
+ procurement_lines_get()
+ test_state('finished')
+
+
+
+
+
+ test_state('canceled')
+
+
+
+
+
+
+ ship_recreate
+
+
+
+
+
+ ship_corrected
+
+
+
+
+
+ ship_cancel
+
+
+
+
diff --git a/addons/sale_stock/security/ir.model.access.csv b/addons/sale_stock/security/ir.model.access.csv
new file mode 100644
index 00000000000..c8e6f2b7342
--- /dev/null
+++ b/addons/sale_stock/security/ir.model.access.csv
@@ -0,0 +1,17 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_stock_picking_salesman,stock_picking salesman,stock.model_stock_picking,base.group_sale_salesman,1,1,1,0
+access_stock_move_salesman,stock_move salesman,stock.model_stock_move,base.group_sale_salesman,1,1,1,0
+access_stock_move_manager,stock_move manager,stock.model_stock_move,base.group_sale_manager,1,1,1,1
+access_procurement_salesman,procurement.order salesman,procurement.model_procurement_order,base.group_sale_salesman,1,1,1,0
+access_procurement_manager,procurement.order manager,procurement.model_procurement_order,base.group_sale_manager,1,1,1,1
+access_sale_order_stock_worker,sale.order stock worker,model_sale_order,stock.group_stock_user,1,1,0,0
+access_sale_order_line_stock_worker,sale.order.line stock worker,model_sale_order_line,stock.group_stock_user,1,1,0,0
+access_report_stock_move_sales,report.stock.move.sale,stock.model_report_stock_move,base.group_sale_manager,1,1,1,1
+access_stock_picking_sales,stock.picking.sales,stock.model_stock_picking,base.group_sale_manager,1,1,1,1
+access_product_packaging_user,product.packaging.user,product.model_product_packaging,base.group_sale_salesman,1,1,1,0
+access_product_packaging_manager,product.packaging.manager,product.model_product_packaging,base.group_sale_manager,1,0,0,0
+access_stock_warehouse_user,stock.warehouse.user,stock.model_stock_warehouse,base.group_sale_salesman,1,0,0,0
+access_stock_location_user,stock.location.user,stock.model_stock_location,base.group_sale_salesman,1,0,0,0
+access_product_packaging_sale_manager,product.packaging salemanager,product.model_product_packaging,base.group_sale_manager,1,1,1,1
+access_stock_warehouse_orderpoint_sale_salesman,stock.warehouse.orderpoint,procurement.model_stock_warehouse_orderpoint,base.group_sale_salesman,1,0,0,0
+access_account_move_line_salesman,account.move.line invoice,account.model_account_move_line,base.group_sale_salesman,1,0,0,0
\ No newline at end of file
diff --git a/addons/sale_stock/security/sale_stock_security.xml b/addons/sale_stock/security/sale_stock_security.xml
new file mode 100644
index 00000000000..83db390a2c4
--- /dev/null
+++ b/addons/sale_stock/security/sale_stock_security.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+ Enable Invoicing Delivery orders
+
+
+
+
+ Properties on lines
+
+
+
+
+
+
diff --git a/addons/sale/stock.py b/addons/sale_stock/stock.py
similarity index 100%
rename from addons/sale/stock.py
rename to addons/sale_stock/stock.py
diff --git a/addons/sale/stock_view.xml b/addons/sale_stock/stock_view.xml
similarity index 98%
rename from addons/sale/stock_view.xml
rename to addons/sale_stock/stock_view.xml
index 40de6872be0..6399658c392 100644
--- a/addons/sale/stock_view.xml
+++ b/addons/sale_stock/stock_view.xml
@@ -77,7 +77,7 @@
{'default_type': 'out', 'contact_display': 'partner_address', 'search_default_to_invoice': 1, 'search_default_done': 1, 'default_invoice_state': '2binvoiced'}
-
+
diff --git a/addons/sale_stock/test/cancel_order_sale_stock.yml b/addons/sale_stock/test/cancel_order_sale_stock.yml
new file mode 100644
index 00000000000..edac19ccb02
--- /dev/null
+++ b/addons/sale_stock/test/cancel_order_sale_stock.yml
@@ -0,0 +1,42 @@
+-
+ In order to test the cancel sale order.
+ First I confirm order.
+-
+ !workflow {model: sale.order, action: order_confirm, ref: sale.order5}
+-
+ Now I regenerate shipment.
+-
+ !workflow {model: sale.order, action: ship_recreate, ref: sale.order5}
+-
+ I check state of order in 'To Invoice'.
+-
+ !assert {model: sale.order, id: sale.order5, string: Sale order should be In Progress state}:
+ - state == 'manual'
+-
+ I make invoice for order.
+-
+ !workflow {model: sale.order, action: manual_invoice, ref: sale.order5}
+-
+ To cancel the sale order from Invoice Exception, I have to cancel the invoice of sale order.
+-
+ !python {model: sale.order}: |
+ import netsvc
+ invoice_ids = self.browse(cr, uid, ref("sale.order5")).invoice_ids
+ wf_service = netsvc.LocalService("workflow")
+ first_invoice_id = invoice_ids[0]
+ wf_service.trg_validate(uid, 'account.invoice', first_invoice_id.id, 'invoice_cancel', cr)
+-
+ I check order status in "Invoice Exception" and related invoice is in cancel state.
+-
+ !assert {model: sale.order, id: sale.order5, string: Sale order should be in Invoice Exception state}:
+ - state == "invoice_except", "Order should be in Invoice Exception state after cancel Invoice"
+-
+ Then I click on the Ignore Exception button.
+-
+ !workflow {model: sale.order, action: invoice_corrected, ref: sale.order5}
+
+-
+ I check state of order in 'In Progress'.
+-
+ !assert {model: sale.order, id: sale.order5, string: Sale order should be In progress state}:
+ - state == 'progress'
\ No newline at end of file
diff --git a/addons/sale/test/manual_order_policy.yml b/addons/sale_stock/test/manual_order_policy.yml
similarity index 83%
rename from addons/sale/test/manual_order_policy.yml
rename to addons/sale_stock/test/manual_order_policy.yml
index 505ab0933d0..e640a08e8bb 100644
--- a/addons/sale/test/manual_order_policy.yml
+++ b/addons/sale_stock/test/manual_order_policy.yml
@@ -1,12 +1,12 @@
-
I confirm the Quotation with "Deliver & invoice on demand".
-
- !workflow {model: sale.order, action: order_confirm, ref: order4}
+ !workflow {model: sale.order, action: order_confirm, ref: sale.order4}
-
I check that Invoice should not created.
-
!python {model: sale.order}: |
- sale_order = self.browse(cr, uid, ref("order4"))
+ sale_order = self.browse(cr, uid, ref("sale.order4"))
assert len(sale_order.invoice_ids) == False, "Invoice should not created."
assert sale_order.picking_ids, "Delivery order should be created."
-
@@ -14,28 +14,28 @@
-
!python {model: sale.advance.payment.inv}: |
ctx = context.copy()
- ctx.update({"active_model": 'sale.order', "active_ids": [ref("order4")], "active_id":ref("order4")})
- order_line = self.pool.get('sale.order.line').browse(cr, uid, ref("line7"), context=context)
+ ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale.order4")], "active_id":ref("sale.order4")})
+ order_line = self.pool.get('sale.order.line').browse(cr, uid, ref("sale.line7"), context=context)
pay_id = self.create(cr, uid, {'advance_payment_method': 'fixed', 'product_id': order_line.product_id.id, 'amount': order_line.price_subtotal, 'qtty': order_line.product_uom_qty})
self.create_invoices(cr, uid, [pay_id], context=ctx)
-
I check Invoice which made advance
-
!python {model: sale.order}: |
- order = self.browse(cr, uid, ref('order4'))
+ order = self.browse(cr, uid, ref('sale.order4'))
assert order.invoice_ids, "Invoice should be created after make advance invoice."
-
I create Invoice from sale order line.
-
!python {model: sale.order.line.make.invoice}: |
ctx = context.copy()
- ctx.update({"active_model": 'sale.order.line', "active_ids": [ref("line8")], "active_id":ref("line8")})
+ ctx.update({"active_model": 'sale.order.line', "active_ids": [ref("sale.line8")], "active_id":ref("sale.line8")})
self.make_invoices(cr, uid, [], context=ctx)
-
I check Invoice which made from sale order line.
-
!python {model: sale.order.line}: |
- line = self.browse(cr, uid, ref('line8'))
+ line = self.browse(cr, uid, ref('sale.line8'))
assert line.invoiced, "Line is not invoiced."
assert line.invoice_lines, "Invoice line should be created."
-
@@ -46,7 +46,7 @@
-
!python {model: sale.make.invoice}: |
ctx = context.copy()
- ctx = ctx.update({"active_model": 'sale.order', "active_ids": [ref("order4")], "active_id":ref("order4")})
+ ctx = ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale.order4")], "active_id":ref("sale.order4")})
self.make_invoices(cr, uid, [ref("sale_make_invoice_1")], context)
-
I open the Invoice.
@@ -54,7 +54,7 @@
!python {model: sale.order}: |
import netsvc
wf_service = netsvc.LocalService("workflow")
- so = self.browse(cr, uid, ref("order4"))
+ so = self.browse(cr, uid, ref("sale.order4"))
for invoice in so.invoice_ids:
wf_service.trg_validate(uid, 'account.invoice', invoice.id, 'invoice_open', cr)
-
@@ -62,7 +62,7 @@
-
!python {model: account.invoice}: |
sale_order = self.pool.get('sale.order')
- order = sale_order.browse(cr, uid, ref("order4"))
+ order = sale_order.browse(cr, uid, ref("sale.order4"))
journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', order.company_id.id)], limit=1)
for invoice in order.invoice_ids:
invoice.pay_and_reconcile(
@@ -74,7 +74,7 @@
I check Invoice after do manual.
-
!python {model: sale.order}: |
- sale_order = self.browse(cr, uid, ref("order4"))
+ sale_order = self.browse(cr, uid, ref("sale.order4"))
assert sale_order.invoice_ids, "Invoice should be created."
assert sale_order.invoiced, "Order is not invoiced."
assert sale_order.state == 'manual', 'Order should be in Manual.'
diff --git a/addons/sale/test/picking_order_policy.yml b/addons/sale_stock/test/picking_order_policy.yml
similarity index 91%
rename from addons/sale/test/picking_order_policy.yml
rename to addons/sale_stock/test/picking_order_policy.yml
index 16caefddf1b..73d392c1b23 100644
--- a/addons/sale/test/picking_order_policy.yml
+++ b/addons/sale_stock/test/picking_order_policy.yml
@@ -3,17 +3,17 @@
-
First I check the total amount of the Quotation before Approved.
-
- !assert {model: sale.order, id: order, string: The amount of the Quotation is not correctly computed}:
+ !assert {model: sale.order, id: sale.order, string: The amount of the Quotation is not correctly computed}:
- sum([l.price_subtotal for l in order_line]) == amount_untaxed
-
I confirm the quotation with "Invoice based on deliveries" policy.
-
- !workflow {model: sale.order, action: order_confirm, ref: order}
+ !workflow {model: sale.order, action: order_confirm, ref: sale.order}
-
I check that invoice should not created before dispatch delivery.
-
!python {model: sale.order}: |
- order = self.pool.get('sale.order').browse(cr, uid, ref("order"))
+ order = self.pool.get('sale.order').browse(cr, uid, ref("sale.order"))
assert order.state == 'progress', 'Order should be in inprogress.'
assert len(order.invoice_ids) == False, "Invoice should not created."
-
@@ -23,7 +23,7 @@
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
- order = self.browse(cr, uid, ref("order"))
+ order = self.browse(cr, uid, ref("sale.order"))
for order_line in order.order_line:
procurement = order_line.procurement_id
date_planned = datetime.strptime(order.date_order, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(days=order_line.delay or 0.0)
@@ -45,7 +45,7 @@
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
- sale_order = self.browse(cr, uid, ref("order"))
+ sale_order = self.browse(cr, uid, ref("sale.order"))
assert sale_order.picking_ids, "Delivery order is not created."
for picking in sale_order.picking_ids:
assert picking.state == "auto" or "confirmed", "Delivery order should be in 'Waitting Availability' state."
@@ -77,7 +77,7 @@
Now, I dispatch delivery order.
-
!python {model: stock.partial.picking}: |
- order = self.pool.get('sale.order').browse(cr, uid, ref("order"))
+ order = self.pool.get('sale.order').browse(cr, uid, ref("sale.order"))
for pick in order.picking_ids:
data = pick.force_assign()
if data == True:
@@ -87,7 +87,7 @@
I check sale order to verify shipment.
-
!python {model: sale.order}: |
- order = self.pool.get('sale.order').browse(cr, uid, ref("order"))
+ order = self.pool.get('sale.order').browse(cr, uid, ref("sale.order"))
assert order.shipped == True, "Sale order is not Delivered."
assert order.picked_rate == 100, "Shipment progress is not 100%."
#assert order.state == 'progress', 'Order should be in inprogress.'
@@ -97,7 +97,7 @@
-
!python {model: stock.invoice.onshipping}: |
sale = self.pool.get('sale.order')
- sale_order = sale.browse(cr, uid, ref("order"))
+ sale_order = sale.browse(cr, uid, ref("sale.order"))
ship_ids = [x.id for x in sale_order.picking_ids]
wiz_id = self.create(cr, uid, {'journal_id': ref('account.sales_journal')},
{'active_ids': ship_ids, 'active_model': 'stock.picking'})
@@ -106,7 +106,7 @@
I check the invoice details after dispatched delivery.
-
!python {model: sale.order}: |
- order = self.browse(cr, uid, ref("order"))
+ order = self.browse(cr, uid, ref("sale.order"))
assert order.invoice_ids, "Invoice is not created."
ac = order.partner_id.property_account_receivable.id
journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'sale'), ('company_id', '=', order.company_id.id)])
@@ -134,7 +134,7 @@
!python {model: sale.order}: |
import netsvc
wf_service = netsvc.LocalService("workflow")
- so = self.browse(cr, uid, ref("order"))
+ so = self.browse(cr, uid, ref("sale.order"))
for invoice in so.invoice_ids:
wf_service.trg_validate(uid, 'account.invoice', invoice.id, 'invoice_open', cr)
-
@@ -142,7 +142,7 @@
-
!python {model: account.invoice}: |
sale_order = self.pool.get('sale.order')
- order = sale_order.browse(cr, uid, ref("order"))
+ order = sale_order.browse(cr, uid, ref("sale.order"))
journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', order.company_id.id)], limit=1)
for invoice in order.invoice_ids:
invoice.pay_and_reconcile(
@@ -154,7 +154,7 @@
I check the order after paid invoice.
-
!python {model: sale.order}: |
- order = self.browse(cr, uid, ref("order"))
+ order = self.browse(cr, uid, ref("sale.order"))
assert order.invoiced == True, "Sale order is not invoiced."
assert order.invoiced_rate == 100, "Invoiced progress is not 100%."
assert order.state == 'done', 'Order should be in closed.'
@@ -163,7 +163,7 @@
-
!python {model: sale.order}: |
import netsvc, tools, os
- (data, format) = netsvc.LocalService('report.sale.order').create(cr, uid, [ref('order')], {}, {})
+ (data, format) = netsvc.LocalService('report.sale.order').create(cr, uid, [ref('sale.order')], {}, {})
if tools.config['test_report_directory']:
file(os.path.join(tools.config['test_report_directory'], 'sale-sale_order.'+format), 'wb+').write(data)
diff --git a/addons/sale_stock/wizard/__init__.py b/addons/sale_stock/wizard/__init__.py
new file mode 100644
index 00000000000..504e6eddbc0
--- /dev/null
+++ b/addons/sale_stock/wizard/__init__.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 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 .
+#
+##############################################################################
+
+import sale_make_invoice
+import sale_make_invoice_advance
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/sale/wizard/sale_make_invoice.py b/addons/sale_stock/wizard/sale_make_invoice.py
similarity index 100%
rename from addons/sale/wizard/sale_make_invoice.py
rename to addons/sale_stock/wizard/sale_make_invoice.py
diff --git a/addons/sale/wizard/sale_make_invoice.xml b/addons/sale_stock/wizard/sale_make_invoice.xml
similarity index 100%
rename from addons/sale/wizard/sale_make_invoice.xml
rename to addons/sale_stock/wizard/sale_make_invoice.xml
diff --git a/addons/sale/wizard/sale_make_invoice_advance.py b/addons/sale_stock/wizard/sale_make_invoice_advance.py
similarity index 100%
rename from addons/sale/wizard/sale_make_invoice_advance.py
rename to addons/sale_stock/wizard/sale_make_invoice_advance.py
diff --git a/addons/sale/wizard/sale_make_invoice_advance.xml b/addons/sale_stock/wizard/sale_make_invoice_advance.xml
similarity index 100%
rename from addons/sale/wizard/sale_make_invoice_advance.xml
rename to addons/sale_stock/wizard/sale_make_invoice_advance.xml
From bab2f1959f948b83fc42919aaee6a4da6bdf95da Mon Sep 17 00:00:00 2001
From: "Atul Patel (OpenERP)"
Date: Fri, 27 Jul 2012 11:58:41 +0530
Subject: [PATCH 060/408] [FIX]: Fix menu and workflow problem
bzr revid: atp@tinyerp.com-20120727062841-cg5qtd34nnll8n5r
---
addons/sale/sale_demo.xml | 4 +---
addons/sale/security/sale_security.xml | 6 ------
addons/sale_stock/res_config.py | 4 ++--
addons/sale_stock/sale_stock_demo.xml | 5 ++++-
addons/sale_stock/sale_stock_view.xml | 5 +----
addons/sale_stock/security/sale_stock_security.xml | 4 ++++
addons/sale_stock/stock_view.xml | 2 +-
7 files changed, 13 insertions(+), 17 deletions(-)
diff --git a/addons/sale/sale_demo.xml b/addons/sale/sale_demo.xml
index 4d0e8914c3e..a04eca80871 100644
--- a/addons/sale/sale_demo.xml
+++ b/addons/sale/sale_demo.xml
@@ -111,8 +111,6 @@
3
-
-
@@ -195,7 +193,7 @@
4500
-
+
diff --git a/addons/sale/security/sale_security.xml b/addons/sale/security/sale_security.xml
index 4e23a45436e..8b64b360435 100644
--- a/addons/sale/security/sale_security.xml
+++ b/addons/sale/security/sale_security.xml
@@ -42,12 +42,6 @@
-
- Enable Invoicing Delivery orders
-
-
-
-
diff --git a/addons/sale_stock/res_config.py b/addons/sale_stock/res_config.py
index c7d3d970b67..b337fe5e794 100644
--- a/addons/sale_stock/res_config.py
+++ b/addons/sale_stock/res_config.py
@@ -27,7 +27,7 @@ class sale_configuration(osv.osv_memory):
_inherit = 'sale.config.settings'
_columns = {
'group_invoice_deli_orders': fields.boolean('Based on Delivery Orders',
- implied_group='sale.group_invoice_deli_orders',
+ implied_group='group_invoice_deli_orders',
help="To allow your salesman to make invoices for Delivery Orders using the menu 'Deliveries to Invoice'."),
'task_work': fields.boolean('Based on Task Activities',
help="""Lets you transfer the entries under tasks defined for Project Management to
@@ -45,7 +45,7 @@ class sale_configuration(osv.osv_memory):
'default_picking_policy' : fields.boolean("Configurable Shipping Policy",
help = "You will be able to configure, per sale order, if you deliver all products at once or if you deliver each product when it is available. This may have an impact on the shipping price."),
'group_mrp_properties': fields.boolean('Properties on Lines',
- implied_group='sale.group_mrp_properties',
+ implied_group='group_mrp_properties',
help="Allows you to tag sale order lines with properties."),
'group_multiple_shops': fields.boolean("Manage Multiple Shops",
implied_group='stock.group_locations',
diff --git a/addons/sale_stock/sale_stock_demo.xml b/addons/sale_stock/sale_stock_demo.xml
index d336cd0c37e..9e4a1f60632 100644
--- a/addons/sale_stock/sale_stock_demo.xml
+++ b/addons/sale_stock/sale_stock_demo.xml
@@ -12,15 +12,18 @@
manual
+
+
manual
+
+ manual
- picking
diff --git a/addons/sale_stock/sale_stock_view.xml b/addons/sale_stock/sale_stock_view.xml
index 96128e40000..e15bc023462 100644
--- a/addons/sale_stock/sale_stock_view.xml
+++ b/addons/sale_stock/sale_stock_view.xml
@@ -133,13 +133,10 @@
-
+
-
-
-
diff --git a/addons/sale_stock/security/sale_stock_security.xml b/addons/sale_stock/security/sale_stock_security.xml
index 54d04f08e11..73badf9ad0e 100644
--- a/addons/sale_stock/security/sale_stock_security.xml
+++ b/addons/sale_stock/security/sale_stock_security.xml
@@ -7,6 +7,10 @@
+
+ Enable Invoicing Delivery orders
+
+
diff --git a/addons/sale_stock/stock_view.xml b/addons/sale_stock/stock_view.xml
index 40de6872be0..6399658c392 100644
--- a/addons/sale_stock/stock_view.xml
+++ b/addons/sale_stock/stock_view.xml
@@ -77,7 +77,7 @@
{'default_type': 'out', 'contact_display': 'partner_address', 'search_default_to_invoice': 1, 'search_default_done': 1, 'default_invoice_state': '2binvoiced'}
-
+
From 692357c872b9798330cb81b718388389e942abf0 Mon Sep 17 00:00:00 2001
From: "Atul Patel (OpenERP)"
Date: Fri, 27 Jul 2012 12:47:08 +0530
Subject: [PATCH 061/408] [FIX]: Fix product_id onchange problem
bzr revid: atp@tinyerp.com-20120727071708-gx51ajrt2zfdtgzy
---
addons/sale/res_config_view.xml | 2 +-
addons/sale/sale.py | 22 ++-----
addons/sale/sale_workflow.xml | 77 ++++++++++-------------
addons/sale_stock/res_config_view.xml | 6 +-
addons/sale_stock/sale_stock_view.xml | 24 +++----
addons/sale_stock/sale_stock_workflow.xml | 13 ++--
6 files changed, 56 insertions(+), 88 deletions(-)
diff --git a/addons/sale/res_config_view.xml b/addons/sale/res_config_view.xml
index 023da1b37eb..d482a681563 100644
--- a/addons/sale/res_config_view.xml
+++ b/addons/sale/res_config_view.xml
@@ -25,7 +25,7 @@
+ attrs="{'invisible': [('module_account_analytic_analysis','=',False)],'required': [('module_account_analytic_analysis','=',True)]}"/>
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index a5316ce10fa..fca3fa992de 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -815,11 +815,6 @@ class sale_order_line(osv.osv):
for line in self.browse(cr, uid, ids, context=context):
if line.invoiced:
raise osv.except_osv(_('Invalid action !'), _('You cannot cancel a sale order line that has already been invoiced!'))
- for move_line in line.move_ids:
- if move_line.state != 'cancel':
- raise osv.except_osv(
- _('Could not cancel sales order line!'),
- _('You must first cancel stock moves attached to this sales order line.'))
return self.write(cr, uid, ids, {'state': 'cancel'})
def button_confirm(self, cr, uid, ids, context=None):
@@ -855,7 +850,7 @@ class sale_order_line(osv.osv):
def copy_data(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
- default.update({'state': 'draft', 'move_ids': [], 'invoiced': False, 'invoice_lines': []})
+ default.update({'state': 'draft', 'invoiced': False, 'invoice_lines': []})
return super(sale_order_line, self).copy_data(cr, uid, id, default, context=context)
@@ -876,14 +871,14 @@ class sale_order_line(osv.osv):
context_partner = {'lang': lang, 'partner_id': partner_id}
if not product:
- return {'value': {'th_weight': 0, 'product_packaging': False,
+ return {'value': {'th_weight': 0,
'product_uos_qty': qty}, 'domain': {'product_uom': [],
'product_uos': []}}
if not date_order:
date_order = time.strftime(DEFAULT_SERVER_DATE_FORMAT)
- res = self.product_packaging_change(cr, uid, ids, pricelist, product, qty, uom, partner_id, packaging, context=context)
- result = res.get('value', {})
+ res = {}
+ result = res
warning_msgs = res.get('warning') and res['warning']['message'] or ''
product_obj = product_obj.browse(cr, uid, product, context=context)
@@ -901,7 +896,6 @@ class sale_order_line(osv.osv):
uos = False
fpos = fiscal_position and self.pool.get('account.fiscal.position').browse(cr, uid, fiscal_position) or False
if update_tax: #The quantity only have changed
- result['delay'] = (product_obj.sale_delay or 0.0)
result['tax_id'] = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, product_obj.taxes_id)
result.update({'type': product_obj.procure_method})
@@ -943,14 +937,6 @@ class sale_order_line(osv.osv):
if not uom2:
uom2 = product_obj.uom_id
- compare_qty = float_compare(product_obj.virtual_available * uom2.factor, qty * product_obj.uom_id.factor, precision_rounding=product_obj.uom_id.rounding)
- if (product_obj.type=='product') and int(compare_qty) == -1 \
- and (product_obj.procure_method=='make_to_stock'):
- warn_msg = _('You plan to sell %.2f %s but you only have %.2f %s available !\nThe real stock is %.2f %s. (without reservations)') % \
- (qty, uom2 and uom2.name or product_obj.uom_id.name,
- max(0,product_obj.virtual_available), product_obj.uom_id.name,
- max(0,product_obj.qty_available), product_obj.uom_id.name)
- warning_msgs += _("Not enough stock ! : ") + warn_msg + "\n\n"
# get unit price
if not pricelist:
diff --git a/addons/sale/sale_workflow.xml b/addons/sale/sale_workflow.xml
index 7db2b6dbcbe..5e032eab8c6 100644
--- a/addons/sale/sale_workflow.xml
+++ b/addons/sale/sale_workflow.xml
@@ -13,12 +13,14 @@
Truedraft
+
sentfunctionwrite({'state':'sent'})
-
+
+
router
@@ -26,6 +28,7 @@
action_wait()OR
+
wait_invoice
@@ -39,6 +42,7 @@
write({'state':'done'})AND
+
cancel
@@ -46,6 +50,7 @@
stopallaction_cancel()
+
cancel2
@@ -53,13 +58,7 @@
stopallaction_cancel()
-
-
- cancel3
- True
- stopall
- action_cancel()
-
+
invoice
@@ -79,7 +78,6 @@
functionaction_invoice_end()
-
invoice_cancel
@@ -89,26 +87,21 @@
-
-
-
-
-
-
-
-
-
- order_confirm
-
-
+
quotation_sent
-
-
-
+
+
+
+
+ order_confirm
+
+
+
+ cancel
@@ -118,52 +111,41 @@
order_confirm
-
-
-
+
+
+ cancel
-
+
+
+
+
+
+
all_lines
-
-
-
-
- (order_policy=='picking')
-
-
-
-
-
-
-
-
cancel
-
(order_policy=='prepaid')
-
subflow.paid
-
@@ -184,6 +166,11 @@
invoice_cancel
-
+
+
+
+
+
+
diff --git a/addons/sale_stock/res_config_view.xml b/addons/sale_stock/res_config_view.xml
index e68aa3b5662..481b4da6d3c 100644
--- a/addons/sale_stock/res_config_view.xml
+++ b/addons/sale_stock/res_config_view.xml
@@ -15,7 +15,7 @@
-
+
@@ -37,6 +37,10 @@
+
+
+
diff --git a/addons/sale_stock/sale_stock_view.xml b/addons/sale_stock/sale_stock_view.xml
index e15bc023462..488e948a7ef 100644
--- a/addons/sale_stock/sale_stock_view.xml
+++ b/addons/sale_stock/sale_stock_view.xml
@@ -83,13 +83,6 @@
-
-
-
-
-
-
-
@@ -105,27 +98,26 @@
-
+
days
-
-
+
+
-
-
+
+
-
-
+
+
-
+
-
diff --git a/addons/sale_stock/sale_stock_workflow.xml b/addons/sale_stock/sale_stock_workflow.xml
index 0bea307292c..db2e64e4b6f 100644
--- a/addons/sale_stock/sale_stock_workflow.xml
+++ b/addons/sale_stock/sale_stock_workflow.xml
@@ -53,7 +53,6 @@
-
@@ -64,6 +63,12 @@
(order_policy=='picking')
+
+
+
+
+ manual_invoice
+
@@ -77,12 +82,6 @@
(order_policy!='prepaid') or invoiced
-
-
-
- manual_invoice
-
-
From 9d5336923fb73bd9f50f14c8381eea9e8010a1cf Mon Sep 17 00:00:00 2001
From: "Atul Patel (OpenERP)"
Date: Fri, 27 Jul 2012 13:03:21 +0530
Subject: [PATCH 062/408] [FIX]: Fix dependency problem
bzr revid: atp@tinyerp.com-20120727073321-9i655wdu63tdvf8n
---
addons/sale_order_dates/__openerp__.py | 2 +-
addons/sale_stock/sale_stock_workflow.xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/sale_order_dates/__openerp__.py b/addons/sale_order_dates/__openerp__.py
index f5ccef7ffe5..f67c7034821 100644
--- a/addons/sale_order_dates/__openerp__.py
+++ b/addons/sale_order_dates/__openerp__.py
@@ -36,7 +36,7 @@ You can add the following additional dates to a sale order:
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'images': ["images/sale_order_dates.jpeg"],
- 'depends': ["sale"],
+ 'depends': ["sale_stock"],
'init_xml': [
],
diff --git a/addons/sale_stock/sale_stock_workflow.xml b/addons/sale_stock/sale_stock_workflow.xml
index db2e64e4b6f..5177ab37720 100644
--- a/addons/sale_stock/sale_stock_workflow.xml
+++ b/addons/sale_stock/sale_stock_workflow.xml
@@ -68,7 +68,7 @@
manual_invoice
-
+
From bbbbe7c46b7a119fcb1daf1be844b306bea93d1c Mon Sep 17 00:00:00 2001
From: "Atul Patel (OpenERP)"
Date: Fri, 27 Jul 2012 14:36:07 +0530
Subject: [PATCH 063/408] [FIX]: Chance manual_invoice method into sale_stock
module.
bzr revid: atp@tinyerp.com-20120727090607-w3y8jiy459z0iuok
---
addons/sale/sale.py | 30 -------------------
addons/sale_stock/sale_stock.py | 35 ++++++++++++++++++++++-
addons/sale_stock/sale_stock_workflow.xml | 4 ---
3 files changed, 34 insertions(+), 35 deletions(-)
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index fca3fa992de..f458eb9e651 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -378,36 +378,6 @@ class sale_order(osv.osv):
}
return {'type': 'ir.actions.report.xml', 'report_name': 'sale.order', 'datas': datas, 'nodestroy': True}
- def manual_invoice(self, cr, uid, ids, context=None):
- """ create invoices for the given sale orders (ids), and open the form
- view of one of the newly created invoices
- """
- mod_obj = self.pool.get('ir.model.data')
- wf_service = netsvc.LocalService("workflow")
-
- # create invoices through the sale orders' workflow
- inv_ids0 = set(inv.id for sale in self.browse(cr, uid, ids, context) for inv in sale.invoice_ids)
- for id in ids:
- wf_service.trg_validate(uid, 'sale.order', id, 'manual_invoice', cr)
- inv_ids1 = set(inv.id for sale in self.browse(cr, uid, ids, context) for inv in sale.invoice_ids)
- # determine newly created invoices
- new_inv_ids = list(inv_ids1 - inv_ids0)
-
- res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_form')
- res_id = res and res[1] or False,
-
- return {
- 'name': _('Customer Invoices'),
- 'view_type': 'form',
- 'view_mode': 'form',
- 'view_id': [res_id],
- 'res_model': 'account.invoice',
- 'context': "{'type':'out_invoice'}",
- 'type': 'ir.actions.act_window',
- 'nodestroy': True,
- 'target': 'current',
- 'res_id': new_inv_ids and new_inv_ids[0] or False,
- }
def action_view_invoice(self, cr, uid, ids, context=None):
'''
diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py
index 3c43587a199..9f1ce3e590c 100644
--- a/addons/sale_stock/sale_stock.py
+++ b/addons/sale_stock/sale_stock.py
@@ -208,7 +208,40 @@ class sale_order(osv.osv):
self.write(cr, uid, [o.id], {'state': 'progress', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)})
self.pool.get('sale.order.line').button_confirm(cr, uid, [x.id for x in o.order_line])
self.confirm_send_note(cr, uid, ids, context)
- return True
+ return True
+
+ def manual_invoice(self, cr, uid, ids, context=None):
+ """ create invoices for the given sale orders (ids), and open the form
+ view of one of the newly created invoices
+ """
+ mod_obj = self.pool.get('ir.model.data')
+ wf_service = netsvc.LocalService("workflow")
+
+ # create invoices through the sale orders' workflow
+ inv_ids0 = set(inv.id for sale in self.browse(cr, uid, ids, context) for inv in sale.invoice_ids)
+ for id in ids:
+ wf_service.trg_validate(uid, 'sale.order', id, 'manual_invoice', cr)
+ inv_ids1 = set(inv.id for sale in self.browse(cr, uid, ids, context) for inv in sale.invoice_ids)
+ # determine newly created invoices
+ new_inv_ids = list(inv_ids1 - inv_ids0)
+
+ res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_form')
+ res_id = res and res[1] or False,
+
+ return {
+ 'name': _('Customer Invoices'),
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'view_id': [res_id],
+ 'res_model': 'account.invoice',
+ 'context': "{'type':'out_invoice'}",
+ 'type': 'ir.actions.act_window',
+ 'nodestroy': True,
+ 'target': 'current',
+ 'res_id': new_inv_ids and new_inv_ids[0] or False,
+ }
+
+
def action_invoice_create(self, cr, uid, ids, grouped=False, states=['confirmed', 'done', 'exception'], date_inv = False, context=None):
res = False
diff --git a/addons/sale_stock/sale_stock_workflow.xml b/addons/sale_stock/sale_stock_workflow.xml
index 5177ab37720..7b757501e48 100644
--- a/addons/sale_stock/sale_stock_workflow.xml
+++ b/addons/sale_stock/sale_stock_workflow.xml
@@ -53,10 +53,6 @@
-
-
-
-
From cc4a66732b044189dc1c8be1f4bd144c5e3bebde Mon Sep 17 00:00:00 2001
From: "Atul Patel (OpenERP)"
Date: Fri, 27 Jul 2012 14:58:39 +0530
Subject: [PATCH 064/408] [ADD]: Add dependency
bzr revid: atp@tinyerp.com-20120727092839-xgnolhsz2aetnxre
---
addons/delivery/__openerp__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/delivery/__openerp__.py b/addons/delivery/__openerp__.py
index 092258f5e91..24f0b8f4bd9 100644
--- a/addons/delivery/__openerp__.py
+++ b/addons/delivery/__openerp__.py
@@ -32,7 +32,7 @@ You can define your own carrier and delivery grids for prices. When creating
invoices from picking, OpenERP is able to add and compute the shipping line.
""",
'author': 'OpenERP SA',
- 'depends': ['sale', 'purchase', 'stock'],
+ 'depends': ['sale_stock', 'purchase', 'stock'],
'init_xml': ['delivery_data.xml'],
'update_xml': [
'security/ir.model.access.csv',
From f2df648741614fa94cc83cbbcabf87b72740d270 Mon Sep 17 00:00:00 2001
From: "Atul Patel (OpenERP)"
Date: Fri, 27 Jul 2012 15:06:15 +0530
Subject: [PATCH 065/408] [FIX]: Fix group unpack problem
bzr revid: atp@tinyerp.com-20120727093615-9f53wu6z6f7j931b
---
addons/sale_stock/res_config.py | 4 ++--
addons/sale_stock/sale_stock_view.xml | 2 +-
addons/sale_stock/stock_view.xml | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/addons/sale_stock/res_config.py b/addons/sale_stock/res_config.py
index b337fe5e794..dfb93190d0a 100644
--- a/addons/sale_stock/res_config.py
+++ b/addons/sale_stock/res_config.py
@@ -27,7 +27,7 @@ class sale_configuration(osv.osv_memory):
_inherit = 'sale.config.settings'
_columns = {
'group_invoice_deli_orders': fields.boolean('Based on Delivery Orders',
- implied_group='group_invoice_deli_orders',
+ implied_group='sale_stock.group_invoice_deli_orders',
help="To allow your salesman to make invoices for Delivery Orders using the menu 'Deliveries to Invoice'."),
'task_work': fields.boolean('Based on Task Activities',
help="""Lets you transfer the entries under tasks defined for Project Management to
@@ -45,7 +45,7 @@ class sale_configuration(osv.osv_memory):
'default_picking_policy' : fields.boolean("Configurable Shipping Policy",
help = "You will be able to configure, per sale order, if you deliver all products at once or if you deliver each product when it is available. This may have an impact on the shipping price."),
'group_mrp_properties': fields.boolean('Properties on Lines',
- implied_group='group_mrp_properties',
+ implied_group='sale_stock.group_mrp_properties',
help="Allows you to tag sale order lines with properties."),
'group_multiple_shops': fields.boolean("Manage Multiple Shops",
implied_group='stock.group_locations',
diff --git a/addons/sale_stock/sale_stock_view.xml b/addons/sale_stock/sale_stock_view.xml
index 488e948a7ef..d850ce16ada 100644
--- a/addons/sale_stock/sale_stock_view.xml
+++ b/addons/sale_stock/sale_stock_view.xml
@@ -107,7 +107,7 @@
+ groups="sale_stock.group_mrp_properties"/>
diff --git a/addons/sale_stock/stock_view.xml b/addons/sale_stock/stock_view.xml
index 6399658c392..0990cbc9914 100644
--- a/addons/sale_stock/stock_view.xml
+++ b/addons/sale_stock/stock_view.xml
@@ -77,7 +77,7 @@
{'default_type': 'out', 'contact_display': 'partner_address', 'search_default_to_invoice': 1, 'search_default_done': 1, 'default_invoice_state': '2binvoiced'}
-
+
From fee255cfcb12a61b8f3317b2351adcbd92a9848c Mon Sep 17 00:00:00 2001
From: "Atul Patel (OpenERP)"
Date: Sat, 28 Jul 2012 00:06:33 +0530
Subject: [PATCH 066/408] [ADD]: Add dependency sale_stock into point_of_sale
bzr revid: atp@tinyerp.com-20120727183633-jq3se5avp2k0hpeb
---
addons/point_of_sale/__openerp__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/point_of_sale/__openerp__.py b/addons/point_of_sale/__openerp__.py
index 9a39871f0c0..903b2d47c3a 100644
--- a/addons/point_of_sale/__openerp__.py
+++ b/addons/point_of_sale/__openerp__.py
@@ -41,7 +41,7 @@ Main features:
""",
'author': 'OpenERP SA',
'images': ['images/cash_registers.jpeg', 'images/pos_analysis.jpeg','images/register_analysis.jpeg','images/sale_order_pos.jpeg','images/product_pos.jpeg'],
- 'depends': ['sale'],
+ 'depends': ['sale_stock'],
'init_xml': [],
'update_xml': [
From cb6ade257746bacf40f9e50427dd2d429105a7c8 Mon Sep 17 00:00:00 2001
From: "Atul Patel (OpenERP)"
Date: Sat, 28 Jul 2012 22:54:52 +0530
Subject: [PATCH 067/408] [FIX]: remove depency from delivery. remove duplicate
process from sale form.
bzr revid: atp@tinyerp.com-20120728172452-falievqp8ve97dti
---
addons/delivery/__openerp__.py | 2 +-
addons/sale/process/sale_process.xml | 22 ----------------
.../sale_stock/process/sale_stock_process.xml | 26 +++++++++++++++++++
3 files changed, 27 insertions(+), 23 deletions(-)
diff --git a/addons/delivery/__openerp__.py b/addons/delivery/__openerp__.py
index 24f0b8f4bd9..092258f5e91 100644
--- a/addons/delivery/__openerp__.py
+++ b/addons/delivery/__openerp__.py
@@ -32,7 +32,7 @@ You can define your own carrier and delivery grids for prices. When creating
invoices from picking, OpenERP is able to add and compute the shipping line.
""",
'author': 'OpenERP SA',
- 'depends': ['sale_stock', 'purchase', 'stock'],
+ 'depends': ['sale', 'purchase', 'stock'],
'init_xml': ['delivery_data.xml'],
'update_xml': [
'security/ir.model.access.csv',
diff --git a/addons/sale/process/sale_process.xml b/addons/sale/process/sale_process.xml
index 05999ff6fb8..836c6fddc04 100644
--- a/addons/sale/process/sale_process.xml
+++ b/addons/sale/process/sale_process.xml
@@ -62,28 +62,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
From eb902136ba58bc23722f32c3c123c706862e9465 Mon Sep 17 00:00:00 2001
From: "Atul Patel (OpenERP)"
Date: Sat, 28 Jul 2012 23:35:05 +0530
Subject: [PATCH 068/408] [IMP]: ADD onchange of order policy
bzr revid: atp@tinyerp.com-20120728180505-lu2warmnrzto55xw
---
addons/sale_stock/sale_stock_view.xml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/addons/sale_stock/sale_stock_view.xml b/addons/sale_stock/sale_stock_view.xml
index d850ce16ada..ce24e3f3903 100644
--- a/addons/sale_stock/sale_stock_view.xml
+++ b/addons/sale_stock/sale_stock_view.xml
@@ -125,6 +125,9 @@
+
+
+
From 49f6e45b02443e17cd87f574f7b097dcb2a45c48 Mon Sep 17 00:00:00 2001
From: "Atul Patel (OpenERP)"
Date: Sat, 28 Jul 2012 23:40:05 +0530
Subject: [PATCH 069/408] [ADD]: Add oe_highlight in create invoice button.
bzr revid: atp@tinyerp.com-20120728181005-2ucqag0pihgrhcct
---
addons/sale_stock/sale_stock_view.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/sale_stock/sale_stock_view.xml b/addons/sale_stock/sale_stock_view.xml
index ce24e3f3903..40c44d0e2d1 100644
--- a/addons/sale_stock/sale_stock_view.xml
+++ b/addons/sale_stock/sale_stock_view.xml
@@ -64,7 +64,7 @@
-
+
From 3a9da0c95dd13a3033ac6bea44d401b18024f502 Mon Sep 17 00:00:00 2001
From: "Atul Patel (OpenERP)"
Date: Sun, 29 Jul 2012 21:37:56 +0530
Subject: [PATCH 070/408] [FIX]: Fix action_invoice_create() method
bzr revid: atp@tinyerp.com-20120729160756-quwy0nhmlc4fmrsh
---
addons/sale_stock/sale_stock.py | 74 ++++++++-------------------------
1 file changed, 18 insertions(+), 56 deletions(-)
diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py
index 9f1ce3e590c..754657ae70a 100644
--- a/addons/sale_stock/sale_stock.py
+++ b/addons/sale_stock/sale_stock.py
@@ -244,62 +244,15 @@ class sale_order(osv.osv):
def action_invoice_create(self, cr, uid, ids, grouped=False, states=['confirmed', 'done', 'exception'], date_inv = False, context=None):
- res = False
- invoices = {}
- invoice_ids = []
+ res = super(sale_order,self).action_invoice_create( cr, uid, ids, grouped=grouped, states=states, date_inv = date_inv, context=context)
picking_obj = self.pool.get('stock.picking')
- invoice = self.pool.get('account.invoice')
- obj_sale_order_line = self.pool.get('sale.order.line')
- partner_currency = {}
if context is None:
context = {}
# If date was specified, use it as date invoiced, usefull when invoices are generated this month and put the
# last day of the last month as invoice date
- if date_inv:
- context['date_inv'] = date_inv
- for o in self.browse(cr, uid, ids, context=context):
- currency_id = o.pricelist_id.currency_id.id
- if (o.partner_id.id in partner_currency) and (partner_currency[o.partner_id.id] <> currency_id):
- raise osv.except_osv(
- _('Error !'),
- _('You cannot group sales having different currencies for the same partner.'))
-
- partner_currency[o.partner_id.id] = currency_id
- lines = []
- for line in o.order_line:
- if line.invoiced:
- continue
- elif (line.state in states):
- lines.append(line.id)
- created_lines = obj_sale_order_line.invoice_line_create(cr, uid, lines)
- if created_lines:
- invoices.setdefault(o.partner_id.id, []).append((o, created_lines))
- if not invoices:
- for o in self.browse(cr, uid, ids, context=context):
- for i in o.invoice_ids:
- if i.state == 'draft':
- return i.id
- for val in invoices.values():
- if grouped:
- res = self._make_invoice(cr, uid, val[0][0], reduce(lambda x, y: x + y, [l for o, l in val], []), context=context)
- invoice_ref = ''
- for o, l in val:
- invoice_ref += o.name + '|'
- self.write(cr, uid, [o.id], {'state': 'progress'})
- if o.order_policy == 'picking':
- picking_obj.write(cr, uid, map(lambda x: x.id, o.picking_ids), {'invoice_state': 'invoiced'})
- cr.execute('insert into sale_order_invoice_rel (order_id,invoice_id) values (%s,%s)', (o.id, res))
- invoice.write(cr, uid, [res], {'origin': invoice_ref, 'name': invoice_ref})
- else:
- for order, il in val:
- res = self._make_invoice(cr, uid, order, il, context=context)
- invoice_ids.append(res)
- self.write(cr, uid, [order.id], {'state': 'progress'})
- if order.order_policy == 'picking':
- picking_obj.write(cr, uid, map(lambda x: x.id, order.picking_ids), {'invoice_state': 'invoiced'})
- cr.execute('insert into sale_order_invoice_rel (order_id,invoice_id) values (%s,%s)', (order.id, res))
- if res:
- self.invoice_send_note(cr, uid, ids, res, context)
+ for order in self.browse(cr, uid, ids, context=context):
+ if order.order_policy == 'picking':
+ picking_obj.write(cr, uid, map(lambda x: x.id, order.picking_ids), {'invoice_state': 'invoiced'})
return res
def action_cancel(self, cr, uid, ids, context=None):
@@ -613,15 +566,24 @@ class sale_order_line(osv.osv):
}
def _prepare_order_line_invoice_line(self, cr, uid, line, account_id=False, context=None):
+ res = super(sale_order_line, self)._prepare_order_line_invoice_line(cr, uid, line, account_id=account_id, context=context)
+
def _get_line_qty(line):
if not (line.order_id.invoice_quantity=='order') or line.procurement_id:
- return self.pool.get('procurement.order').quantity_get(cr, uid, line.procurement_id.id, context=context)
+ return self.pool.get('procurement.order').quantity_get(cr, uid,
+ line.procurement_id.id, context=context)
def _get_line_uom(line):
- if not (line.order_id.invoice_quantity=='order') or line.procurement_id:
- return self.pool.get('procurement.order').uom_get(cr, uid, line.procurement_id.id, context=context)
-
- return super(sale_order_line, self)._prepare_order_line_invoice_line(cr, uid, line, account_id=account_id, context=context)
+ if not (line.order_id.invoice_quantity=='order') or line.procurement_id:
+ return self.pool.get('procurement.order').uom_get(cr, uid,
+ line.procurement_id.id, context=context)
+ uosqty = _get_line_qty(line)
+ uos_id = _get_line_uom(line)
+ if uosqty:
+ pu = round(line.price_unit * line.product_uom_qty / uosqty,
+ self.pool.get('decimal.precision').precision_get(cr, uid, 'Sale Price'))
+ res.update({'price_unit': pu, 'quantity': uosqty,'uos_id': uos_id})
+ return res
def product_packaging_change(self, cr, uid, ids, pricelist, product, qty=0, uom=False,
partner_id=False, packaging=False, flag=False, context=None):
From 9b0e798446407a517c4647f027362d09d9a51bc9 Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Wed, 1 Aug 2012 17:46:40 +0530
Subject: [PATCH 071/408] [ADD] payment wizard on bank statement line
bzr revid: rgaopenerp-20120801121640-r81nvodxv9kwjizz
---
addons/account_voucher/__openerp__.py | 2 +-
addons/account_voucher/account_voucher.py | 26 +++++++++++++++++++
.../account_voucher/account_voucher_view.xml | 1 +
.../voucher_payment_receipt_view.xml | 2 ++
4 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/addons/account_voucher/__openerp__.py b/addons/account_voucher/__openerp__.py
index 0b37bdbd4a2..c8f18281cf4 100644
--- a/addons/account_voucher/__openerp__.py
+++ b/addons/account_voucher/__openerp__.py
@@ -51,8 +51,8 @@ eInvoicing & Payments module manage all Voucher Entries such as "Reconciliation
"account_voucher_report.xml",
"wizard/account_voucher_unreconcile_view.xml",
"wizard/account_statement_from_invoice_view.xml",
- "account_voucher_view.xml",
"voucher_payment_receipt_view.xml",
+ "account_voucher_view.xml",
"voucher_sales_purchase_view.xml",
"account_voucher_wizard.xml",
"account_voucher_pay_invoice.xml",
diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py
index 2cefaf15f0e..14e25c1a453 100644
--- a/addons/account_voucher/account_voucher.py
+++ b/addons/account_voucher/account_voucher.py
@@ -1495,7 +1495,33 @@ account_bank_statement()
class account_bank_statement_line(osv.osv):
_inherit = 'account.bank.statement.line'
+
+ def bank_st_payment(self, cr, uid, ids, context):
+ record = record_id = False
+ for rec in self.browse(cr, uid, ids, context=context):
+ record_id = rec.voucher_id and rec.voucher_id .id or False
+ record = rec
+ mod_obj = self.pool.get('ir.model.data')
+ if record and record.type == 'customer':
+ res = mod_obj.get_object_reference(cr, uid, 'account_voucher', 'view_vendor_receipt_form')
+ else:
+ res = mod_obj.get_object_reference(cr, uid, 'account_voucher', 'view_vendor_payment_form')
+ view_id = res and res[1] or False
+ context.update({'partner_id':record.partner_id.id, 'amount':record.amount})
+
+ return {
+ 'name': _('Payment Entry'),
+ 'res_model': 'account.voucher',
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'target':'new',
+ 'view_id':view_id,
+ 'context': context,
+ 'res_id':record_id,
+ 'type': 'ir.actions.act_window'
+ }
+
def _amount_reconciled(self, cursor, user, ids, name, args, context=None):
if not ids:
return {}
diff --git a/addons/account_voucher/account_voucher_view.xml b/addons/account_voucher/account_voucher_view.xml
index d1912a58d1c..1cfa8488d7e 100644
--- a/addons/account_voucher/account_voucher_view.xml
+++ b/addons/account_voucher/account_voucher_view.xml
@@ -226,6 +226,7 @@
+
diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml
index 372d8aa1937..7eca832089a 100644
--- a/addons/account_voucher/voucher_payment_receipt_view.xml
+++ b/addons/account_voucher/voucher_payment_receipt_view.xml
@@ -72,6 +72,8 @@
+
+
Date: Mon, 6 Aug 2012 10:52:07 +0530
Subject: [PATCH 072/408] [IMP] record should be selected(checked) by default
bzr revid: rgaopenerp-20120806052207-4cpwu4zpi6p30wgd
---
addons/account/account_view.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index d7026217dc4..91ff57c2e71 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -1928,7 +1928,7 @@
tree
-
+
From 65ae69521b267b529e486329406d7e0cb9828243 Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Mon, 6 Aug 2012 15:00:59 +0530
Subject: [PATCH 073/408] [IMP] code clean up
bzr revid: rgaopenerp-20120806093059-3xk320oduvb5ceo0
---
addons/account/account_move_line.py | 32 ++------------------
addons/account/account_move_line_extended.py | 14 +++++++++
2 files changed, 17 insertions(+), 29 deletions(-)
diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py
index d697444c446..5eb56bfa645 100644
--- a/addons/account/account_move_line.py
+++ b/addons/account/account_move_line.py
@@ -107,15 +107,7 @@ class account_move_line(osv.osv):
query += company_clause
return query
-
- def get_selection_ids(self, cr, uid, ids, context=None):
- records = self.read(cr, uid, ids, ['reconcile_id'])
- res = []
- for record in records:
- if not record.get('reconcile_id'):
- res.append(record['id'])
- return res
-
+
def _amount_residual(self, cr, uid, ids, field_names, args, context=None):
"""
This function returns the residual amount on a receivable or payable account.move.line.
@@ -526,7 +518,7 @@ class account_move_line(osv.osv):
type='many2one', relation='account.invoice', fnct_search=_invoice_search),
'account_tax_id':fields.many2one('account.tax', 'Tax'),
'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account'),
- 'company_id': fields.related('account_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True),
+ 'company_id': fields.related('account_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True)
}
def _get_date(self, cr, uid, context=None):
@@ -717,26 +709,8 @@ class account_move_line(osv.osv):
if not partner:
return []
args.append(('partner_id', '=', partner[0]))
- ids = super(account_move_line, self).search(cr, uid, args, offset, limit, order, context, count)
- if context.get('extended_from'):
- return self.get_move_by_unique_partner(cr, uid, offset, context)
- return ids
+ return super(account_move_line, self).search(cr, uid, args, offset, limit, order, context, count)
- def get_move_by_unique_partner(self, cr, uid, offset=0, context=None):
- cr.execute(
- """
- SELECT l.id ,l.partner_id AS partner_id
- FROM account_move_line l
- LEFT JOIN account_account a ON (a.id = l.account_id)
-
- WHERE a.reconcile IS TRUE
- AND l.reconcile_id IS NULL
-
- AND l.state <> 'draft'
- GROUP BY l.id, l.partner_id OFFSET %s""", (offset, )
- )
- return dict(cr.fetchall()).keys()
-
def get_next_partner_only(self, cr, uid, offset=0, context=None):
cr.execute(
"""
diff --git a/addons/account/account_move_line_extended.py b/addons/account/account_move_line_extended.py
index 441cbda7ae1..8b2ede0b697 100644
--- a/addons/account/account_move_line_extended.py
+++ b/addons/account/account_move_line_extended.py
@@ -29,6 +29,20 @@ class res_partner(osv.osv):
}
res_partner()
+class account_move_line(osv.osv):
+ _inherit = "account.move.line"
+
+ def get_selection_ids(self, cr, uid, ids, context=None):
+ records = self.read(cr, uid, ids, ['reconcile_id'])
+ res = []
+ for record in records:
+ if not record.get('reconcile_id'):
+ res.append(record['id'])
+ return res
+
+account_move_line();
+
+
class account_move_partner_info(osv.osv):
_name = "account.move.partner.info"
_description = "All partner info related account move line"
From abe9798b4abcfb69f2b89c4e66598867c77717f5 Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Mon, 6 Aug 2012 16:14:20 +0530
Subject: [PATCH 074/408] [IMP] Change method name
bzr revid: rgaopenerp-20120806104420-vs7yh16adq2lafpq
---
addons/account/account_move_line_extended.py | 2 +-
addons/account/account_view.xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/account/account_move_line_extended.py b/addons/account/account_move_line_extended.py
index 8b2ede0b697..5c474d5ca52 100644
--- a/addons/account/account_move_line_extended.py
+++ b/addons/account/account_move_line_extended.py
@@ -32,7 +32,7 @@ res_partner()
class account_move_line(osv.osv):
_inherit = "account.move.line"
- def get_selection_ids(self, cr, uid, ids, context=None):
+ def get_unreconcile_entry(self, cr, uid, ids, context=None):
records = self.read(cr, uid, ids, ['reconcile_id'])
res = []
for record in records:
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index cad59f82783..c1a966db8cb 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -2049,7 +2049,7 @@
tree
-
+
From d3ff658fe2b3cca0572c5de9be25bcd08be50325 Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Mon, 6 Aug 2012 16:16:31 +0530
Subject: [PATCH 075/408] [REM] remove default selection from addons it should
be added in web
bzr revid: rgaopenerp-20120806104631-woy75igiysygblad
---
addons/account/static/src/js/account.js | 26 +------------------------
1 file changed, 1 insertion(+), 25 deletions(-)
diff --git a/addons/account/static/src/js/account.js b/addons/account/static/src/js/account.js
index 15ef397aa1a..5a6245e395d 100644
--- a/addons/account/static/src/js/account.js
+++ b/addons/account/static/src/js/account.js
@@ -208,29 +208,5 @@ instance.account.list_button = instance.web.form.WidgetButton.extend({
});
}
})
-instance.account.set_selection = instance.web.ListView.include({
- default_selection: function(){
- var self = this
- selection_method = this.fields_view.arch.attrs.default_selection;
- if(selection_method){
- this.dataset.call(selection_method, [this.dataset.ids], this.context).then(_.bind(self.set_selection, self));
- }
- },
-
- set_selection : function(ids){
- this.$element.find('th.oe_list_record_selector input')
- .closest('tr').each(function () {
- if(_.include(ids, $(this).data('id'))){
- $(this).find('th.oe_list_record_selector input').prop('checked', true)
- }
- }
- );
- },
- reload_content: function() {
- var reloaded =this._super()
- var self = this
- reloaded.done(_.bind(self.default_selection, self))
- },
-})
-
+
}
From 80dd5bdfbc76fbdc514dac584178c72ec8c103c5 Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Mon, 6 Aug 2012 16:51:23 +0530
Subject: [PATCH 076/408] [IMP] Added field to act windows
bzr revid: rgaopenerp-20120806112123-7eusxdvd6gweyqaf
---
addons/account/account_move_line_extended.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/addons/account/account_move_line_extended.py b/addons/account/account_move_line_extended.py
index 5c474d5ca52..9820f33ef15 100644
--- a/addons/account/account_move_line_extended.py
+++ b/addons/account/account_move_line_extended.py
@@ -22,6 +22,13 @@
import tools
from osv import fields,osv
+class act_window(osv.osv):
+ _inherit = 'ir.actions.act_window'
+ _columns = {
+ 'extended_form_view_id': fields.many2one('ir.ui.view', 'Account form view ref.'),
+ }
+act_window()
+
class res_partner(osv.osv):
_inherit = 'res.partner'
_columns = {
From 08fd6917b5ae77de801f3d78e6c872423103cac5 Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Mon, 6 Aug 2012 17:02:48 +0530
Subject: [PATCH 077/408] [IMP] change file name
bzr revid: rgaopenerp-20120806113248-urvz0z1bqje57t0h
---
addons/account/__openerp__.py | 6 +++---
.../css/{account.css => account_move_reconciliation.css} | 0
.../src/js/{account.js => account_move_reconciliation.js} | 0
.../xml/{account.xml => account_move_reconciliation.xml} | 0
4 files changed, 3 insertions(+), 3 deletions(-)
rename addons/account/static/src/css/{account.css => account_move_reconciliation.css} (100%)
rename addons/account/static/src/js/{account.js => account_move_reconciliation.js} (100%)
rename addons/account/static/src/xml/{account.xml => account_move_reconciliation.xml} (100%)
diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py
index c10823ef6fb..e136c75f9c4 100644
--- a/addons/account/__openerp__.py
+++ b/addons/account/__openerp__.py
@@ -129,12 +129,12 @@ financial year and for preparation of vouchers there is a module named account_v
"account_pre_install.yml"
],
'js': [
- 'static/src/js/account.js',
+ 'static/src/js/account_move_reconciliation.js',
],
'qweb' : [
- "static/src/xml/account.xml",
+ "static/src/xml/account_move_reconciliation.xml",
],
- 'css':['static/src/css/account.css'
+ 'css':['static/src/css/account_move_reconciliation.css'
],
'demo_xml': [
'demo/account_demo.xml',
diff --git a/addons/account/static/src/css/account.css b/addons/account/static/src/css/account_move_reconciliation.css
similarity index 100%
rename from addons/account/static/src/css/account.css
rename to addons/account/static/src/css/account_move_reconciliation.css
diff --git a/addons/account/static/src/js/account.js b/addons/account/static/src/js/account_move_reconciliation.js
similarity index 100%
rename from addons/account/static/src/js/account.js
rename to addons/account/static/src/js/account_move_reconciliation.js
diff --git a/addons/account/static/src/xml/account.xml b/addons/account/static/src/xml/account_move_reconciliation.xml
similarity index 100%
rename from addons/account/static/src/xml/account.xml
rename to addons/account/static/src/xml/account_move_reconciliation.xml
From 89328b74ab831cfac8bdeecd6e19660e3426fdf2 Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Mon, 6 Aug 2012 18:23:32 +0530
Subject: [PATCH 078/408] [IMP] change model name + clean up
bzr revid: rgaopenerp-20120806125332-y0bp5ojab6d72ksq
---
addons/account/__init__.py | 2 +-
addons/account/__openerp__.py | 2 +-
...nded.py => account_move_reconciliation.py} | 22 ++++++++--------
...ed.xml => account_move_reconciliation.xml} | 6 ++---
addons/account/account_view.xml | 8 +++---
.../src/js/account_move_reconciliation.js | 2 +-
addons/account_followup/__init__.py | 1 +
addons/account_followup/__openerp__.py | 1 +
addons/account_followup/account_followup.py | 25 -------------------
.../account_followup_view.xml | 13 ----------
10 files changed, 23 insertions(+), 59 deletions(-)
rename addons/account/{account_move_line_extended.py => account_move_reconciliation.py} (86%)
rename addons/account/{account_move_line_extended.xml => account_move_reconciliation.xml} (84%)
diff --git a/addons/account/__init__.py b/addons/account/__init__.py
index 3a2273379da..c5a3a154740 100644
--- a/addons/account/__init__.py
+++ b/addons/account/__init__.py
@@ -38,6 +38,6 @@ import company
import res_currency
import edi
import res_config
-import account_move_line_extended
+import account_move_reconciliation
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py
index e136c75f9c4..0542c9fa79e 100644
--- a/addons/account/__openerp__.py
+++ b/addons/account/__openerp__.py
@@ -66,7 +66,7 @@ financial year and for preparation of vouchers there is a module named account_v
'wizard/account_period_close_view.xml',
'wizard/account_reconcile_view.xml',
'wizard/account_unreconcile_view.xml',
- 'account_move_line_extended.xml',
+ 'account_move_reconciliation.xml',
'account_view.xml',
'account_report.xml',
'account_financial_report_data.xml',
diff --git a/addons/account/account_move_line_extended.py b/addons/account/account_move_reconciliation.py
similarity index 86%
rename from addons/account/account_move_line_extended.py
rename to addons/account/account_move_reconciliation.py
index 9820f33ef15..f30fe9cb040 100644
--- a/addons/account/account_move_line_extended.py
+++ b/addons/account/account_move_reconciliation.py
@@ -50,8 +50,8 @@ class account_move_line(osv.osv):
account_move_line();
-class account_move_partner_info(osv.osv):
- _name = "account.move.partner.info"
+class account_move_reconciliation(osv.osv):
+ _name = "account.move.reconciliation"
_description = "All partner info related account move line"
_auto = False
@@ -72,7 +72,7 @@ class account_move_partner_info(osv.osv):
return res_all
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
- ids = super(account_move_partner_info, self).search(cr, uid, args, offset, limit, order, context, count)
+ ids = super(account_move_reconciliation, self).search(cr, uid, args, offset, limit, order, context, count)
res = []
for l in self.browse(cr, uid, ids, context=context):
if (not l.partner_move_count) or (l.move_lines_count >l.partner_move_count):
@@ -93,17 +93,17 @@ class account_move_partner_info(osv.osv):
res_partner.write(cr, uid, [line.id] ,{'partner_move_count':line.move_lines_count})
def init(self, cr):
- tools.drop_view_if_exists(cr, 'account_move_partner_info')
+ tools.drop_view_if_exists(cr, 'account_move_reconciliation')
cr.execute("""
- create or replace view account_move_partner_info as (
+ CREATE or REPLACE VIEW account_move_reconciliation as (
SELECT p.id, p.id as partner_id,
- max(p.last_reconciliation_date) as last_reconciliation_date,
- max(l.date) as latest_date,
- count(l.id) as move_lines_count,
- max(p.partner_move_count) as partner_move_count
+ MAX(p.last_reconciliation_date) as last_reconciliation_date,
+ MAX(l.date) as latest_date,
+ COUNT(l.id) as move_lines_count,
+ MAX(p.partner_move_count) as partner_move_count
FROM account_move_line as l INNER JOIN res_partner AS p ON (l.partner_id = p.id)
- group by p.id
+ GROUP by p.id
)
""")
-account_move_partner_info()
+account_move_reconciliation()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/account/account_move_line_extended.xml b/addons/account/account_move_reconciliation.xml
similarity index 84%
rename from addons/account/account_move_line_extended.xml
rename to addons/account/account_move_reconciliation.xml
index 8fcf518fc4c..162ddb6ce32 100644
--- a/addons/account/account_move_line_extended.xml
+++ b/addons/account/account_move_reconciliation.xml
@@ -1,9 +1,9 @@
-
- account.move.partner.info.form
- account.move.partner.info
+
+ account.move.reconciliation.form
+ account.move.reconciliationform
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index c1a966db8cb..2356dbf2ac5 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -1087,7 +1087,7 @@
tree
-
+
@@ -1589,7 +1589,7 @@
tree,form
-
+ {'view_mode':True}
@@ -1599,7 +1599,7 @@
formtree,form
-
+ [('partner_id.customer','=',True)]{'view_mode':True}
@@ -1610,7 +1610,7 @@
formtree,form
-
+ [('partner_id.supplier','=',True)]{'view_mode':True}
diff --git a/addons/account/static/src/js/account_move_reconciliation.js b/addons/account/static/src/js/account_move_reconciliation.js
index 5a6245e395d..646f187914b 100644
--- a/addons/account/static/src/js/account_move_reconciliation.js
+++ b/addons/account/static/src/js/account_move_reconciliation.js
@@ -55,7 +55,7 @@ instance.account.extend_viewmanager = instance.web.ViewManagerAction.extend({
init: function(parent, action) {
this._super.apply(this, arguments);
//Fix me: pass hard coded model name, find the way to fetch it from server
- this.dataset_form = new instance.web.DataSetSearch(this, 'account.move.partner.info', action.context, action.domain);
+ this.dataset_form = new instance.web.DataSetSearch(this, 'account.move.reconciliation', action.context, action.domain);
},
start : function(){
this._super()
diff --git a/addons/account_followup/__init__.py b/addons/account_followup/__init__.py
index 4bfe3186298..395ce5475c8 100644
--- a/addons/account_followup/__init__.py
+++ b/addons/account_followup/__init__.py
@@ -22,5 +22,6 @@
import account_followup
import wizard
import report
+import account_move_reconciliation
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/account_followup/__openerp__.py b/addons/account_followup/__openerp__.py
index e8724b01b4e..cfc8c39908f 100644
--- a/addons/account_followup/__openerp__.py
+++ b/addons/account_followup/__openerp__.py
@@ -58,6 +58,7 @@ entry, you can do from in the menu:
'report/account_followup_report.xml',
'account_followup_demo.xml', # Defined by default
'account_followup_view.xml',
+ 'account_move_reconciliation.xml',
'account_followup_data.xml',
],
'demo_xml': [],
diff --git a/addons/account_followup/account_followup.py b/addons/account_followup/account_followup.py
index 4497a254c50..ad419736c57 100644
--- a/addons/account_followup/account_followup.py
+++ b/addons/account_followup/account_followup.py
@@ -76,31 +76,6 @@ class account_move_line(osv.osv):
account_move_line()
-class account_move_partner_info(osv.osv):
- _inherit = 'account.move.partner.info'
- _columns = {
- 'followup_date': fields.date('Latest Follow-up'),
- 'max_followup_id':fields.many2one('account_followup.followup.line',
- 'Max Follow Up Level' )
- }
-
- def init(self, cr):
- tools.drop_view_if_exists(cr, 'account_move_partner_info')
- cr.execute("""
- create or replace view account_move_partner_info as (
- SELECT p.id, p.id as partner_id,
- max(p.last_reconciliation_date) as last_reconciliation_date,
- max(l.date) as latest_date,
- count(l.id) as move_lines_count,
- max(p.partner_move_count) as partner_move_count,
- max(l.followup_date) as followup_date,
- max(l.followup_line_id) as max_followup_id
- FROM account_move_line as l INNER JOIN res_partner AS p ON (l.partner_id = p.id)
- group by p.id
- )
- """)
-account_move_partner_info()
-
class res_company(osv.osv):
_inherit = "res.company"
_columns = {
diff --git a/addons/account_followup/account_followup_view.xml b/addons/account_followup/account_followup_view.xml
index 315f1ea5c0a..3d1d4333bbb 100644
--- a/addons/account_followup/account_followup_view.xml
+++ b/addons/account_followup/account_followup_view.xml
@@ -132,19 +132,6 @@
-
-
- account.move.partner.info.followup
- account.move.partner.info
-
-
-
-
-
-
-
-
- account.move.line.tree.followup
From 7da51cd8bb3787f9a14da7a577d4c62992010a36 Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Mon, 6 Aug 2012 18:27:45 +0530
Subject: [PATCH 079/408] [ADD] inherit view of account reconciliation
bzr revid: rgaopenerp-20120806125745-w0s1k2lw6x7587sq
---
.../account_move_reconciliation.py | 27 +++++++++++++++++++
.../account_move_reconciliation.xml | 17 ++++++++++++
2 files changed, 44 insertions(+)
create mode 100644 addons/account_followup/account_move_reconciliation.py
create mode 100644 addons/account_followup/account_move_reconciliation.xml
diff --git a/addons/account_followup/account_move_reconciliation.py b/addons/account_followup/account_move_reconciliation.py
new file mode 100644
index 00000000000..b185b9a7347
--- /dev/null
+++ b/addons/account_followup/account_move_reconciliation.py
@@ -0,0 +1,27 @@
+from osv import fields, osv
+import tools
+
+class account_move_reconciliation(osv.osv):
+ _inherit = 'account.move.reconciliation'
+ _columns = {
+ 'followup_date': fields.date('Latest Follow-up'),
+ 'max_followup_id':fields.many2one('account_followup.followup.line',
+ 'Max Follow Up Level' )
+ }
+
+ def init(self, cr):
+ tools.drop_view_if_exists(cr, 'account_move_reconciliation')
+ cr.execute("""
+ CREATE or REPLACE VIEW account_move_reconciliation as (
+ SELECT p.id, p.id as partner_id,
+ MAX(p.last_reconciliation_date) as last_reconciliation_date,
+ MAX(l.date) as latest_date,
+ COUNT(l.id) as move_lines_count,
+ MAX(p.partner_move_count) as partner_move_count,
+ MAX(l.followup_date) as followup_date,
+ MAX(l.followup_line_id) as max_followup_id
+ FROM account_move_line as l INNER JOIN res_partner AS p ON (l.partner_id = p.id)
+ GROUP by p.id
+ )
+ """)
+account_move_reconciliation()
\ No newline at end of file
diff --git a/addons/account_followup/account_move_reconciliation.xml b/addons/account_followup/account_move_reconciliation.xml
new file mode 100644
index 00000000000..9759acc0c47
--- /dev/null
+++ b/addons/account_followup/account_move_reconciliation.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ account.move.reconciliation.followup
+ account.move.reconciliation
+
+
+
+
+
+
+
+
+
+
+
From ce3973795d4054bd9ca6860ec4fab36bd0ee13cf Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Mon, 6 Aug 2012 18:50:34 +0530
Subject: [PATCH 080/408] Clean up remove unused code
bzr revid: rgaopenerp-20120806132034-sgt4vd0omm8ito1o
---
.../src/js/account_move_reconciliation.js | 39 +++++--------------
1 file changed, 9 insertions(+), 30 deletions(-)
diff --git a/addons/account/static/src/js/account_move_reconciliation.js b/addons/account/static/src/js/account_move_reconciliation.js
index 646f187914b..6f0e105366b 100644
--- a/addons/account/static/src/js/account_move_reconciliation.js
+++ b/addons/account/static/src/js/account_move_reconciliation.js
@@ -155,27 +155,6 @@ instance.account.btn_extend = instance.web.form.WidgetButton.extend({
viewmanager = this.view.getParent().getParent()
viewmanager.inner_widget.list_view.controller.reload_content();
},
- on_confirmed: function() {
- var self = this;
-
- var context = this.node.attrs.context;
- if (context && context.__ref) {
- context = new instance.web.CompoundContext(context);
- context.set_eval_context(this._build_eval_context());
- }
-
- return this.view.do_execute_action(
- _.extend({}, this.node.attrs, {context: context}),
- this.view.dataset, this.view.datarecord.id, function () {
- $.when(self.view.dataset.read_slice()).then(function() {
- if (!_.isEmpty(self.view.dataset.ids)){
- self.view.reload();
- //reload list view
- self.view.on_pager_action()
- }
- })
- });
- },
})
instance.account.list_button = instance.web.form.WidgetButton.extend({
@@ -195,15 +174,15 @@ instance.account.list_button = instance.web.form.WidgetButton.extend({
self.rpc("/web/action/load", {
action_id: py.eval(this.node.attrs.name),
context: additional_context
- }, function(result) {
- result.result.context = _.extend(result.result.context || {},
- additional_context);
- result.result.flags = result.result.flags || {};
- result.result.flags.new_window = true;
- self.do_action(result.result, function () {
- // reload view
- list_view.reload();
- self.getParent().reload()
+ }, function(result) {
+ result.result.context = _.extend(result.result.context || {},
+ additional_context);
+ result.result.flags = result.result.flags || {};
+ result.result.flags.new_window = true;
+ self.do_action(result.result, function () {
+ // reload view
+ list_view.reload();
+ self.getParent().reload()
});
});
}
From 0caaa1687b57e4419da9ae59d47160a4a2d11f37 Mon Sep 17 00:00:00 2001
From: Ferdinand <>
Date: Tue, 7 Aug 2012 11:40:11 +0530
Subject: [PATCH 081/408] [FIX] stock : Fix the usebility improvement on check
location constraint
lp bug: https://launchpad.net/bugs/1033687 fixed
bzr revid: amp@tinyerp.com-20120807061011-txpon5iw3y73rsa3
---
addons/stock/stock.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index fd45274352b..6cb865ce14b 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -1656,7 +1656,10 @@ class stock_move(osv.osv):
}
def _check_location(self, cr, uid, ids, context=None):
for record in self.browse(cr, uid, ids, context=context):
- if (record.state=='done') and (record.location_dest_id.usage == 'view' or record.location_id.usage == 'view'):
+ if (record.state=='done') and (record.location_id.usage == 'view'):
+ raise osv.except_osv(_('Error'), _('You can not move product %s from location of type view %s ')% (record.product_id.name, record.location_id.name))
+ if (record.state=='done') and (record.location_dest_id.usage == 'view' ):
+ raise osv.except_osv(_('Error'), _('You can not move product %s to location of type view %s ')% (record.product_id.name, record.location_dest_id.name))
return False
return True
From 7cf4fb877960ce5c3316daa14aeb220f7abc3fc0 Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Tue, 7 Aug 2012 14:14:10 +0530
Subject: [PATCH 082/408] [IMP] remove addition field from act_window, pass it
through context of action
bzr revid: rgaopenerp-20120807084410-1w2jycfedlgg80f0
---
addons/account/__openerp__.py | 2 +-
addons/account/account_move_reconciliation.py | 7 ---
addons/account/account_view.xml | 5 +-
.../src/js/account_move_reconciliation.js | 63 +++----------------
4 files changed, 11 insertions(+), 66 deletions(-)
diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py
index 0542c9fa79e..950ee2da895 100644
--- a/addons/account/__openerp__.py
+++ b/addons/account/__openerp__.py
@@ -66,8 +66,8 @@ financial year and for preparation of vouchers there is a module named account_v
'wizard/account_period_close_view.xml',
'wizard/account_reconcile_view.xml',
'wizard/account_unreconcile_view.xml',
- 'account_move_reconciliation.xml',
'account_view.xml',
+ 'account_move_reconciliation.xml',
'account_report.xml',
'account_financial_report_data.xml',
'wizard/account_report_common_view.xml',
diff --git a/addons/account/account_move_reconciliation.py b/addons/account/account_move_reconciliation.py
index f30fe9cb040..8dee6e98b22 100644
--- a/addons/account/account_move_reconciliation.py
+++ b/addons/account/account_move_reconciliation.py
@@ -22,13 +22,6 @@
import tools
from osv import fields,osv
-class act_window(osv.osv):
- _inherit = 'ir.actions.act_window'
- _columns = {
- 'extended_form_view_id': fields.many2one('ir.ui.view', 'Account form view ref.'),
- }
-act_window()
-
class res_partner(osv.osv):
_inherit = 'res.partner'
_columns = {
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index 2356dbf2ac5..3e1f2ac01cd 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -1601,7 +1601,7 @@
[('partner_id.customer','=',True)]
- {'view_mode':True}
+
@@ -1610,9 +1610,8 @@
formtree,form
- [('partner_id.supplier','=',True)]
- {'view_mode':True}
+ if any
- this.dialog = new instance.web.Dialog(this, {
- buttons: { "Close": function() { $(this).dialog("close"); }},
- dialogClass: 'oe_act_window'
- });
- if(on_close)
- this.dialog.on_close.add(on_close);
- } else {
- this.dialog_widget.destroy();
- }
- this.dialog.dialog_title = action.name;
- this.dialog_widget = new instance.web.ViewManagerAction(this, action);
- this.dialog_widget.appendTo(this.dialog.$element);
- this.dialog.open();
- } else {
- this.dialog_stop();
- if(action.menu_id) {
- return this.getParent().do_action(action, function () {
- instance.webclient.menu.open_menu(action.menu_id);
- });
- }
- this.inner_action = action;
- if (action.extended_form_view_id){
- var inner_widget = this.inner_widget = new instance.account.extend_viewmanager(this, action);
- }else{
- var inner_widget = this.inner_widget = new instance.web.ViewManagerAction(this, action);
- }
- inner_widget.add_breadcrumb();
- this.inner_widget.appendTo(this.$element);
- }
- }
- })
-
-
-instance.account.extend_viewmanager = instance.web.ViewManagerAction.extend({
- init: function(parent, action) {
- this._super.apply(this, arguments);
- //Fix me: pass hard coded model name, find the way to fetch it from server
- this.dataset_form = new instance.web.DataSetSearch(this, 'account.move.reconciliation', action.context, action.domain);
- },
+
+instance.account.extend_viewmanager = instance.web.ViewManagerAction.include({
start : function(){
this._super()
- this.setup_exended_form_view(this)
+ if(this.action.context && this.action.context.extended_form_view_id)
+ this.setup_exended_form_view(this)
},
on_mode_switch: function (view_type, no_store, options) {
self = this
self.list_loaded = $.when(this._super.apply(this, arguments)).then(function () {
- self.list_view = self.views['list']
+ if(self.action.context && self.action.context.extended_form_view_id)
+ self.list_view = self.views['list']
})
},
setup_exended_form_view: function(parent){
var self = this,
from_view,
obj_from_view;
- view_id = this.action.extended_form_view_id[0]
+ view_id = this.action.context.extended_form_view_id
from_view = this.registry.get_object('form_clone');
+ this.dataset_form = new instance.web.DataSetSearch(this, 'account.move.reconciliation', this.action.context, this.action.domain);
this.dataset_loaded = this.dataset_form.read_slice()
obj_from_view = new from_view(self, this.dataset_form, view_id, options={});
obj_from_view.template = 'ExtendedFormView'
From 1d0beb57791b339e6e8302e27036b7c574eb60c7 Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Tue, 7 Aug 2012 15:51:23 +0530
Subject: [PATCH 083/408] [IMP] improve view reduce css depencency
bzr revid: rgaopenerp-20120807102123-c9fq33cz7r2pjked
---
.../account/account_move_reconciliation.xml | 37 ++++++++++------
.../src/js/account_move_reconciliation.js | 25 +----------
.../src/xml/account_move_reconciliation.xml | 43 +------------------
.../account_move_reconciliation.xml | 4 +-
4 files changed, 30 insertions(+), 79 deletions(-)
diff --git a/addons/account/account_move_reconciliation.xml b/addons/account/account_move_reconciliation.xml
index 162ddb6ce32..bc0f1145594 100644
--- a/addons/account/account_move_reconciliation.xml
+++ b/addons/account/account_move_reconciliation.xml
@@ -8,20 +8,33 @@
diff --git a/addons/account/static/src/css/account_move_reconciliation.css b/addons/account/static/src/css/account_move_reconciliation.css
index 0cedec95f09..f4136a79ef4 100644
--- a/addons/account/static/src/css/account_move_reconciliation.css
+++ b/addons/account/static/src/css/account_move_reconciliation.css
@@ -73,7 +73,9 @@
.openerp .oe_extended_form_view .oe_form_field_progressbar.ui-progressbar {
width: 200px !important;
}
-
+.openerp .oe_extended_form_view div.oe_reconcile_row{
+ margin-top:7px;
+}
.openerp .oe_list_content > tbody > tr > td > button.reconcile_btn {
color: white;
background-color: #8a89ba;
diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py
index 9a3af14f665..d91c6158d18 100644
--- a/addons/account_voucher/account_voucher.py
+++ b/addons/account_voucher/account_voucher.py
@@ -1499,8 +1499,6 @@ class account_bank_statement_line(osv.osv):
statement_id = ids[0]
statement = self.browse(cr, uid, statement_id, context=context)
voucher = statement.voucher_id or False
- if voucher and voucher.state == 'posted':
- return voucher.cancel_voucher(context=context)
mod_obj = self.pool.get('ir.model.data')
if voucher and voucher.type == 'customer':
res = mod_obj.get_object_reference(cr, uid, 'account_voucher', 'view_vendor_receipt_form')
@@ -1529,7 +1527,16 @@ class account_bank_statement_line(osv.osv):
else:
res[line.id] = 0.0
return res
-
+
+ def _is_reconciled(self, cr, uid, ids, name, args, context=None):
+ res = {}
+ for line in self.browse(cr, uid, ids, context=context):
+ if line.voucher_id and line.voucher_id.state == 'posted':
+ res[line.id] = True
+ else:
+ res[line.id] = False
+ return res
+
def _check_amount(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context):
if obj.voucher_id:
@@ -1543,6 +1550,8 @@ class account_bank_statement_line(osv.osv):
]
_columns = {
+ 'is_reconciled': fields.function(_is_reconciled,
+ string='Statement is reconciled?', type='boolean'),
'amount_reconciled': fields.function(_amount_reconciled,
string='Amount reconciled', type='float'),
'voucher_id': fields.many2one('account.voucher', 'Payment'),
diff --git a/addons/account_voucher/account_voucher_view.xml b/addons/account_voucher/account_voucher_view.xml
index ddeba22d905..30dfe527d3b 100644
--- a/addons/account_voucher/account_voucher_view.xml
+++ b/addons/account_voucher/account_voucher_view.xml
@@ -217,7 +217,8 @@
ReconcileUnreconcile
-->
-
+
+
From c9a718b98af8744030ab4d7d9509d0a4a6a6e5cb Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Wed, 22 Aug 2012 11:47:24 +0530
Subject: [PATCH 110/408] [IMP] if bank line has no voucher then create it on
reconcile
bzr revid: rgaopenerp-20120822061724-kcudfqtqghpdp97b
---
addons/account_voucher/account_voucher.py | 30 +++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py
index d91c6158d18..821ad9f379e 100644
--- a/addons/account_voucher/account_voucher.py
+++ b/addons/account_voucher/account_voucher.py
@@ -1499,11 +1499,37 @@ class account_bank_statement_line(osv.osv):
statement_id = ids[0]
statement = self.browse(cr, uid, statement_id, context=context)
voucher = statement.voucher_id or False
+ voucher_id = voucher and voucher.id or False
+ if not voucher:
+ voucher_obj = self.pool.get('account.voucher')
+ sign = 1
+ type = 'general'
+ ttype = statement.amount < 0 and 'payment' or 'receipt'
+ if statement.journal_id.type in ('sale', 'sale_refund'):
+ type = 'customer'
+ ttype = 'receipt'
+ elif statement.journal_id.type in ('purchase', 'purhcase_refund'):
+ type = 'supplier'
+ ttype = 'payment'
+ sign = -1
+
+ result = voucher_obj.onchange_partner_id(cr, uid, [], partner_id=statement.partner_id.id, journal_id=statement.journal_id.id, amount=sign*statement.amount, currency_id= False, ttype=ttype, date=statement.date, context=context)
+ voucher_res = { 'type': ttype,
+ 'name': statement.name,
+ 'partner_id': statement.partner_id.id,
+ 'journal_id': statement.journal_id.id,
+ 'account_id': result.get('account_id', statement.journal_id.default_credit_account_id.id),
+ 'company_id': statement.company_id.id,
+ 'date': statement.date,
+ 'amount': sign*statement.amount,
+ }
+ voucher_id = voucher_obj.create(cr, uid, voucher_res, context=context)
+ self.write(cr, uid, statement_id, {'voucher_id':voucher_id}, context=context)
mod_obj = self.pool.get('ir.model.data')
if voucher and voucher.type == 'customer':
res = mod_obj.get_object_reference(cr, uid, 'account_voucher', 'view_vendor_receipt_form')
else:
- res = mod_obj.get_object_reference(cr, uid, 'account_voucher', 'view_vendor_payment_form')
+ res = mod_obj.get_object_reference(cr, uid, 'account_voucher', 'view_vendor_payment_form')
view_id = res and res[1] or False
return {
'name': _('Payment Entry'),
@@ -1513,7 +1539,7 @@ class account_bank_statement_line(osv.osv):
'target':'new',
'view_id':view_id,
'context': context,
- 'res_id':voucher and voucher.id or False,
+ 'res_id':voucher_id,
'type': 'ir.actions.act_window'
}
From b4a38f16ace679f5c84b80ea9fe0edca7e96ae78 Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Wed, 22 Aug 2012 18:26:16 +0530
Subject: [PATCH 111/408] [FIX] last_reconciliation_date should write on
reconcilation and change according to get correct partner based on last
reconciliation date
bzr revid: rgaopenerp-20120822125616-bxkrh4le71yg2dod
---
addons/account/account_move_reconciliation.py | 4 ++--
addons/account/wizard/account_reconcile.py | 3 ++-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/addons/account/account_move_reconciliation.py b/addons/account/account_move_reconciliation.py
index 0590440b861..a6675825ce8 100644
--- a/addons/account/account_move_reconciliation.py
+++ b/addons/account/account_move_reconciliation.py
@@ -68,7 +68,7 @@ class account_move_reconciliation(osv.osv):
if not last_reconciliation_date:
res_ids.append(id)
else:
- move_ids = obj_move_line.search(cr, uid, [('partner_id','=', id),('create_date','>', last_reconciliation_date)])
+ move_ids = obj_move_line.search(cr, uid, [('partner_id','=', id),('date','>', last_reconciliation_date)])
if move_ids:
res_ids.append(id)
return res_ids
@@ -76,7 +76,7 @@ class account_move_reconciliation(osv.osv):
def skip_partner(self, cr, uid, ids, context):
res_partner = self.pool.get('res.partner')
for partner in self.browse(cr, uid, ids, context=context):
- res_partner.write(cr, uid, [partner.id] ,{'last_reconciliation_date':time.strftime("%Y-%m-%d %H:%M:%S")})
+ res_partner.write(cr, uid, [partner.id] ,{'last_reconciliation_date':time.strftime("%Y-%m-%d")})
_columns = {
diff --git a/addons/account/wizard/account_reconcile.py b/addons/account/wizard/account_reconcile.py
index 729792e2222..ceed4c267df 100644
--- a/addons/account/wizard/account_reconcile.py
+++ b/addons/account/wizard/account_reconcile.py
@@ -92,12 +92,13 @@ class account_move_line_reconcile(osv.osv_memory):
partner_id = tmp_ml_id.partner_id and tmp_ml_id.partner_id.id or False
debit_ml_ids = account_move_line_obj.search(cr, uid, [('partner_id', '=', partner_id), ('account_id.reconcile', '=', True), ('reconcile_id', '=', False), ('debit', '>', 0)], context=context)
credit_ml_ids = account_move_line_obj.search(cr, uid, [('partner_id', '=', partner_id), ('account_id.reconcile', '=', True), ('reconcile_id', '=', False), ('credit', '>', 0)], context=context)
+ print 'REREWREW',credit_ml_ids, debit_ml_ids, context
for ml_id in context['active_ids']:
if ml_id in debit_ml_ids:
debit_ml_ids.remove(ml_id)
if ml_id in credit_ml_ids:
credit_ml_ids.remove(ml_id)
- if not debit_ml_ids and credit_ml_ids:
+ if not debit_ml_ids and not credit_ml_ids:
context.update({'stop_reconcile': True})
account_move_line_obj.reconcile(cr, uid, context['active_ids'], 'manual', account_id,
period_id, journal_id, context=context)
From b246b1955a41524dc8eb8612a14b09c9120f5cd2 Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Wed, 22 Aug 2012 19:29:04 +0530
Subject: [PATCH 112/408] [IMP] remove function field from account voucher and
set search default on move line entry
bzr revid: rgaopenerp-20120822135904-y03fti3q0yooxnxu
---
addons/account/account_view.xml | 4 ++--
addons/account_voucher/account_voucher.py | 18 ++++++------------
.../account_voucher/account_voucher_view.xml | 4 ++--
3 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index e80219e3c64..3c27d3cfec1 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -1545,7 +1545,7 @@
tree,form[('partner_id.customer','=',True)]
-
+
@@ -1555,7 +1555,7 @@
tree,form[('partner_id.supplier','=',True)]
-
+ Reconcile
Unreconcile
-->
-
-
+
+
From c1437ba1b4306f05595a5310f51d7b61b6d4775a Mon Sep 17 00:00:00 2001
From: "RGA(OpenERP)" <>
Date: Thu, 23 Aug 2012 17:25:23 +0530
Subject: [PATCH 113/408] [IMP] Added old wizrad algo to computer prgoress of
reconcilation process, costomer and supplier should display respective
recivalbe and payable entry
bzr revid: rgaopenerp-20120823115523-44m8ydyc33az4tjc
---
addons/account/account_move_line.py | 2 +
addons/account/account_move_reconciliation.py | 111 ++++++++++++------
.../account/account_move_reconciliation.xml | 2 +-
addons/account/account_view.xml | 6 +-
.../account_move_reconciliation.py | 25 +++-
5 files changed, 100 insertions(+), 46 deletions(-)
diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py
index 18ab1a779a3..ccea4e1c1a8 100644
--- a/addons/account/account_move_line.py
+++ b/addons/account/account_move_line.py
@@ -701,6 +701,8 @@ class account_move_line(osv.osv):
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
if context is None:
context = {}
+ if context and context.get('account_type', False):
+ args.append(('account_id.type', '=', context.get('account_type', False)))
if context and context.get('next_partner_only', False):
if not context.get('partner_id', False):
partner = self.get_next_partner_only(cr, uid, offset, context)
diff --git a/addons/account/account_move_reconciliation.py b/addons/account/account_move_reconciliation.py
index a6675825ce8..232a0ae9aa7 100644
--- a/addons/account/account_move_reconciliation.py
+++ b/addons/account/account_move_reconciliation.py
@@ -23,18 +23,11 @@ import time
import tools
from osv import fields,osv
-#4 remove get_unreconcile_entry method mange it with domain
-
class account_move_line(osv.osv):
_inherit = "account.move.line"
def get_unreconcile_entry(self, cr, uid, ids, context=None):
- records = self.read(cr, uid, ids, ['reconcile_id'])
- res = []
- for record in records:
- if not record.get('reconcile_id'):
- res.append(record['id'])
- return res
+ return self.search(cr, uid, [('id', 'in', ids), ('reconcile_id', '=', False)], context=context)
account_move_line();
@@ -43,59 +36,101 @@ class account_move_reconciliation(osv.osv):
_name = "account.move.reconciliation"
_description = "All partner info related account move line"
_auto = False
+
+ def _get_to_reconcile(self, cr, uid, context=None):
+ query= ''
+ if context and context.get('account_type', False) == 'payable':
+ query = 'AND p.supplier = True'
+
+ cr.execute("""
+ SELECT p_id FROM (SELECT l.partner_id as p_id, SUM(l.debit) AS debit, SUM(l.credit) AS credit
+ FROM account_move_line AS l LEFT JOIN account_account a ON (l.account_id = a.id)
+ LEFT JOIN res_partner p ON (p.id = l.partner_id)
+ WHERE a.reconcile = 't'
+ AND l.reconcile_id IS NULL
+ AND (%s > to_char(p.last_reconciliation_date, 'YYYY-MM-DD') OR p.last_reconciliation_date IS NULL )
+ AND l.state <> 'draft' """ +query + """
+ GROUP BY l.partner_id) AS tmp
+ WHERE debit >= 0
+ AND credit >= 0
+ """,(time.strftime('%Y-%m-%d'),)
+ )
+ return len(map(lambda x: x[0], cr.fetchall())) - 1
+
+ def _get_today_reconciled(self, cr, uid, context=None):
+ query= ''
+ if context and context.get('account_type', False) == 'payable':
+ query = 'AND p.supplier = True'
+
+ cr.execute(
+ """SELECT l.partner_id
+ FROM account_move_line AS l LEFT JOIN res_partner p ON (p.id = l.partner_id)
+ WHERE l.reconcile_id IS NULL
+ AND %s = to_char(p.last_reconciliation_date, 'YYYY-MM-DD')
+ AND l.state <> 'draft' """ +query + """
+ GROUP BY l.partner_id """,(time.strftime('%Y-%m-%d'),)
+ )
+ return len(map(lambda x: x[0], cr.fetchall())) + 1
def _rec_progress(self, cr, uid, ids, prop, unknow_none, context=None):
- active_ids = context.get('active_ids', [])
- res = 0
- if active_ids:
- total_records = self.search(cr, uid, [('id','in',active_ids)])
- total_unreconcile = 0
- for record in self.read(cr, uid, total_records, ['unreconcile_count'], context=context):
- if record['unreconcile_count'] > 0:
- total_unreconcile += 1
- res = float(len(total_records) - total_unreconcile)/len(total_records) * 100
- res_all = {}
+ res = {}
+ to_reconcile = self._get_to_reconcile(cr, uid, context)
+ today_reconcile = self._get_today_reconciled(cr, uid, context)
+ if to_reconcile < 0:
+ reconciliation_progress = 100
+ else:
+ reconciliation_progress = (100 / (float( to_reconcile + today_reconcile) or 1.0)) * today_reconcile
for id in ids:
- res_all[id] = res
- return res_all
+ res[id] = reconciliation_progress
+ return res
+#
+ def get_partners(self, cr, uid, context=None):
+ query= ''
+ if context and context.get('account_type', False) == 'payable':
+ query = 'AND p.supplier = True'
+ cr.execute(
+ """
+ SELECT p.id
+ FROM res_partner p
+ RIGHT JOIN (
+ SELECT l.partner_id AS partner_id, SUM(l.debit) AS debit, SUM(l.credit) AS credit
+ FROM account_move_line l
+ LEFT JOIN account_account a ON (a.id = l.account_id)
+ LEFT JOIN res_partner p ON (l.partner_id = p.id)
+ WHERE a.reconcile IS TRUE
+ AND l.reconcile_id IS NULL
+ AND (p.last_reconciliation_date IS NULL OR l.date > p.last_reconciliation_date)
+ AND l.state <> 'draft' """ +query + """
+ GROUP BY l.partner_id
+ ) AS s ON (p.id = s.partner_id)
+ ORDER BY p.last_reconciliation_date""")
+ return cr.fetchall()
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
- obj_move_line = self.pool.get('account.move.line')
ids = super(account_move_reconciliation, self).search(cr, uid, args, offset, limit, order, context, count)
- res_ids = []
- for id in ids:
- last_reconciliation_date = self.browse(cr, uid, id, context=context).last_reconciliation_date
- if not last_reconciliation_date:
- res_ids.append(id)
- else:
- move_ids = obj_move_line.search(cr, uid, [('partner_id','=', id),('date','>', last_reconciliation_date)])
- if move_ids:
- res_ids.append(id)
- return res_ids
+ res = self.get_partners(cr, uid, context=context)
+ return map(lambda x: x[0], res)
def skip_partner(self, cr, uid, ids, context):
- res_partner = self.pool.get('res.partner')
- for partner in self.browse(cr, uid, ids, context=context):
- res_partner.write(cr, uid, [partner.id] ,{'last_reconciliation_date':time.strftime("%Y-%m-%d")})
-
+ self.pool.get('res.partner').write(cr, uid, ids ,{'last_reconciliation_date':time.strftime("%Y-%m-%d")}, context)
_columns = {
'partner_id':fields.many2one('res.partner', 'Partner'),
'last_reconciliation_date':fields.related('partner_id', 'last_reconciliation_date' ,type='datetime', relation='res.partner', string='Last Reconciliation'),
'latest_date' :fields.date('Latest Entry'),
'reconciliation_progress': fields.function(_rec_progress, string='Progress (%)', type='float'),
- 'unreconcile_count':fields.integer('Unreconcile Count'),
}
+
def init(self, cr):
tools.drop_view_if_exists(cr, 'account_move_reconciliation')
cr.execute("""
CREATE or REPLACE VIEW account_move_reconciliation as (
SELECT move_line.partner_id as id, move_line.partner_id,
- MAX(move_line.date) as latest_date,
- (select count(unreconcile.id) from account_move_line as unreconcile where unreconcile.reconcile_id is null and unreconcile.partner_id = move_line.partner_id) as unreconcile_count
+ MAX(move_line.date) as latest_date
FROM account_move_line as move_line where move_line.state <> 'draft'
GROUP by move_line.partner_id
)
""")
account_move_reconciliation()
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/account/account_move_reconciliation.xml b/addons/account/account_move_reconciliation.xml
index 5e26b9c0bec..256492bfa48 100644
--- a/addons/account/account_move_reconciliation.xml
+++ b/addons/account/account_move_reconciliation.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index 3c27d3cfec1..2093b548044 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -1544,8 +1544,7 @@
formtree,form
- [('partner_id.customer','=',True)]
-
+
@@ -1554,8 +1553,7 @@
formtree,form
- [('partner_id.supplier','=',True)]
-
+ ).
+#
+# 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
import tools
@@ -12,12 +32,11 @@ class account_move_reconciliation(osv.osv):
def init(self, cr):
tools.drop_view_if_exists(cr, 'account_move_reconciliation')
cr.execute("""
- CREATE or REPLACE VIEW account_move_reconciliation as (
+ CREATE or REPLACE VIEW account_move_reconciliation as (
SELECT move_line.partner_id as id, move_line.partner_id,
- MAX(move_line.date) as latest_date,
MAX(move_line.followup_date) as followup_date,
MAX(move_line.followup_line_id) as max_followup_id,
- (select count(unreconcile.id) from account_move_line as unreconcile where unreconcile.reconcile_id is null and unreconcile.partner_id = move_line.partner_id) as unreconcile_count
+ MAX(move_line.date) as latest_date
FROM account_move_line as move_line where move_line.state <> 'draft'
GROUP by move_line.partner_id
)
From 12d69b3488816d5c5680599a79500a2f616a29c3 Mon Sep 17 00:00:00 2001
From: "Divyesh Makwana (Open ERP)"
Date: Fri, 24 Aug 2012 12:34:44 +0530
Subject: [PATCH 114/408] [FIX] sale : Traceback on clicking 'View Invoice'
button.
lp bug: https://launchpad.net/bugs/1038918 fixed
bzr revid: mdi@tinyerp.com-20120824070444-o43u79mvcg8ga99p
---
addons/sale/sale.py | 28 ++++++++--------------------
1 file changed, 8 insertions(+), 20 deletions(-)
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index c525ba04df1..cbf7778d126 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -518,36 +518,24 @@ class sale_order(osv.osv):
This function returns an action that display existing invoices of given sale order ids. It can either be a in a list or in a form view, if there is only one invoice to show.
'''
mod_obj = self.pool.get('ir.model.data')
- result = {
- 'name': _('Cutomer Invoice'),
- 'view_type': 'form',
- 'res_model': 'account.invoice',
- 'context': "{'type':'out_invoice', 'journal_type': 'sale'}",
- 'type': 'ir.actions.act_window',
- 'nodestroy': True,
- 'target': 'current',
- }
+ act_obj = self.pool.get('ir.actions.act_window')
+
+ result = mod_obj.get_object_reference(cr, uid, 'account', 'action_invoice_tree1')
+ id = result and result[1] or False
+ result = act_obj.read(cr, uid, [id], context=context)[0]
#compute the number of invoices to display
inv_ids = []
for so in self.browse(cr, uid, ids, context=context):
inv_ids += [invoice.id for invoice in so.invoice_ids]
#choose the view_mode accordingly
if len(inv_ids)>1:
- res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_tree')
- result.update({
- 'view_mode': 'tree,form',
- 'res_id': inv_ids or False
- })
+ result['domain'] = "[('id','in',["+','.join(map(str, inv_ids))+"])]"
else:
res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_form')
- result.update({
- 'view_mode': 'form',
- 'res_id': inv_ids and inv_ids[0] or False,
- })
- result.update(view_id = res and res[1] or False)
+ result['views'] = [(res and res[1] or False, 'form')]
+ result['res_id'] = inv_ids and inv_ids[0] or False
return result
-
def action_view_delivery(self, cr, uid, ids, context=None):
'''
This function returns an action that display existing delivery orders of given sale order ids. It can either be a in a list or in a form view, if there is only one delivery order to show.
From fb08d41118e59835ccec326e7991bc11ba27535c Mon Sep 17 00:00:00 2001
From: "Pinakin Nayi (OpenERP)"
Date: Mon, 27 Aug 2012 11:00:40 +0530
Subject: [PATCH 115/408] [IMP]project issue5
bzr revid: pna@tinyerp.com-20120827053040-xq743y0ivvtrfwzc
---
.../analytic_contract_project_view.xml | 2 +-
addons/project/i18n/project.pot | 2 +-
addons/project/project.py | 3 +-
addons/project/project_view.xml | 37 +++++++++----------
addons/project/res_config.py | 14 ++++++-
addons/project/res_config_view.xml | 4 +-
addons/project/security/project_security.xml | 5 +++
addons/project_issue/project_issue_view.xml | 11 +++---
.../project_long_term_view.xml | 4 +-
addons/project_mrp/project_procurement.py | 1 +
10 files changed, 51 insertions(+), 32 deletions(-)
diff --git a/addons/analytic_contract_project/analytic_contract_project_view.xml b/addons/analytic_contract_project/analytic_contract_project_view.xml
index 84f01e19643..eb8638a9de7 100644
--- a/addons/analytic_contract_project/analytic_contract_project_view.xml
+++ b/addons/analytic_contract_project/analytic_contract_project_view.xml
@@ -106,7 +106,7 @@
Projects are used to organize your activities; plan
tasks, track issues, invoice timesheets. You can define
internal projects (R&D, Improve Sales Process),
private projects (My Todos) or customer ones.
-
-
+
You will be able collaborate with internal users on
projects or invite customers to share your activities.
-
-
+
+
From 5b175acd1e378cddf323f26709e0fc50e3ad6f6a Mon Sep 17 00:00:00 2001
From: "Randhir Mayatra (OpenERP)"
Date: Wed, 12 Sep 2012 12:22:13 +0530
Subject: [PATCH 186/408] [IMP]make changes into purchase view
bzr revid: rma@tinyerp.com-20120912065213-1kqs35ndjz7yapbz
---
addons/purchase/purchase_view.xml | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml
index ab5df67f52d..f5c7b0a64aa 100644
--- a/addons/purchase/purchase_view.xml
+++ b/addons/purchase/purchase_view.xml
@@ -26,7 +26,9 @@
-
+
@@ -185,7 +187,7 @@
-
+
From f1ac51cb218c18360c68f1df9511a4c77901bda0 Mon Sep 17 00:00:00 2001
From: Saurang Suthar
Date: Wed, 12 Sep 2012 12:40:31 +0530
Subject: [PATCH 187/408] [IMP]hr_holidays:made fields holiday_type and
employee_id visible only for HR/Officer
bzr revid: ssu@tinyerp.com-20120912071031-fopmip7rp06ymqmr
---
addons/hr_holidays/hr_holidays_view.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/hr_holidays/hr_holidays_view.xml b/addons/hr_holidays/hr_holidays_view.xml
index 958c2cab062..8bd00d58832 100644
--- a/addons/hr_holidays/hr_holidays_view.xml
+++ b/addons/hr_holidays/hr_holidays_view.xml
@@ -149,8 +149,8 @@
-
-
+
+
From aa779d50007291de06427110ca6012dec36ebe95 Mon Sep 17 00:00:00 2001
From: "Ajay Chauhan (OpenERP)"
Date: Wed, 12 Sep 2012 13:03:57 +0530
Subject: [PATCH 188/408] [IMP] sale: update 'Manual_order_policy.yml'
bzr revid: cha@tinyerp.com-20120912073357-naznvtd9n0zja3pd
---
addons/sale/test/manual_order_policy.yml | 34 +++++++++---------------
1 file changed, 12 insertions(+), 22 deletions(-)
diff --git a/addons/sale/test/manual_order_policy.yml b/addons/sale/test/manual_order_policy.yml
index 3a8dcbd2f5b..d67677c8254 100644
--- a/addons/sale/test/manual_order_policy.yml
+++ b/addons/sale/test/manual_order_policy.yml
@@ -15,38 +15,28 @@
ctx = context.copy()
ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale_order_2")], "active_id":ref("sale_order_2")})
order_line = self.pool.get('sale.order.line').browse(cr, uid, ref("sale_order_line_4"), context=context)
- pay_id = self.create(cr, uid, {'advance_payment_method': 'fixed', 'product_id': order_line.product_id.id, 'amount': order_line.price_subtotal, 'qtty': order_line.product_uom_qty})
+ pay_id = self.create(cr, uid, {'advance_payment_method': 'fixed', 'product_id': order_line.product_id.id, 'amount': order_line.price_unit})
self.create_invoices(cr, uid, [pay_id], context=ctx)
-
- I check Invoice which made advance
+ I check Invoice which made advance.
-
!python {model: sale.order}: |
order = self.browse(cr, uid, ref('sale_order_2'))
assert order.invoice_ids, "Invoice should be created after make advance invoice."
-
- I create Invoice from sale order line.
+ I create advance invoice where payment method is 'all'.
-
- !python {model: sale.order.line.make.invoice}: |
+ !python {model: sale.advance.payment.inv}: |
ctx = context.copy()
- ctx.update({"active_model": 'sale.order.line', "active_ids": [ref("sale_order_line_5")], "active_id":ref("sale_order_line_5")})
- self.make_invoices(cr, uid, [], context=ctx)
+ ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale_order_2")], "active_id":ref("sale_order_2")})
+ pay_id = self.create(cr, uid, {'advance_payment_method': 'all'})
+ self.create_invoices(cr, uid, [pay_id], context=ctx)
-
- I check Invoice which made from sale order line.
+ I check Invoice which made advance where payment method is 'all'.
-
- !python {model: sale.order.line}: |
- line = self.browse(cr, uid, ref('sale_order_line_5'))
- assert line.invoiced, "Line is not invoiced."
- assert line.invoice_lines, "Invoice line should be created."
--
- I create manual Invoice for order.
--
- !record {model: sale.make.invoice, id: sale_make_invoice_1}:
- invoice_date: !eval time.strftime('%Y-%m-%d')
--
- !python {model: sale.make.invoice}: |
- ctx = context.copy()
- ctx = ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale_order_2")], "active_id":ref("sale_order_2")})
- self.make_invoices(cr, uid, [ref("sale_make_invoice_1")], context)
+ !python {model: sale.order}: |
+ order = self.browse(cr, uid, ref('sale_order_2'))
+ assert order.invoice_ids, "Invoice should be created after make advance invoice where payment method is 'all'."
-
I open the Invoice.
-
@@ -76,7 +66,7 @@
sale_order = self.browse(cr, uid, ref("sale_order_2"))
assert sale_order.invoice_ids, "Invoice should be created."
assert sale_order.invoiced, "Order is not invoiced."
- assert sale_order.state == 'manual', 'Order should be in Manual.'
+ assert sale_order.state == 'progress', 'Order should be in Progress.'
-
I set order policy "Deliver & invoice on demand" as default policy.
From 427200a24168d589054198c91cf322b9b7cd54da Mon Sep 17 00:00:00 2001
From: "Ajay Chauhan (OpenERP)"
Date: Wed, 12 Sep 2012 14:40:40 +0530
Subject: [PATCH 189/408] [IMP] sale: update some statements in yml & clear
unwanted code in sale.py file.
bzr revid: cha@tinyerp.com-20120912091040-yezbspjjucempq2e
---
addons/sale/sale.py | 37 +++++++++++++-----------
addons/sale/test/manual_order_policy.yml | 15 +++++-----
2 files changed, 28 insertions(+), 24 deletions(-)
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index f86d5722da2..04523e86ecb 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -145,13 +145,6 @@ class sale_order(osv.osv):
res[sale.id] = 0.0
return res
- def _get_invoiced_amount(self, cr, uid, sale, context=None):
- invoiced_amount = 0
- for invoice in sale.invoice_ids:
- if invoice.state!='cancel':
- invoiced_amount += invoice.amount_total
- return invoiced_amount
-
def _invoice_exists(self, cursor, user, ids, name, arg, context=None):
res = {}
for sale in self.browse(cursor, user, ids, context=context):
@@ -535,25 +528,35 @@ class sale_order(osv.osv):
This function returns an action that display existing invoices of given sale order ids. It can either be a in a list or in a form view, if there is only one invoice to show.
'''
mod_obj = self.pool.get('ir.model.data')
- act_obj = self.pool.get('ir.actions.act_window')
-
- result = mod_obj.get_object_reference(cr, uid, 'account', 'action_invoice_tree1')
- id = result and result[1] or False
- result = act_obj.read(cr, uid, [id], context=context)[0]
+ result = {
+ 'name': _('Cutomer Invoice'),
+ 'view_type': 'form',
+ 'res_model': 'account.invoice',
+ 'context': "{'type':'out_invoice', 'journal_type': 'sale'}",
+ 'type': 'ir.actions.act_window',
+ 'nodestroy': True,
+ 'target': 'current',
+ }
#compute the number of invoices to display
inv_ids = []
for so in self.browse(cr, uid, ids, context=context):
inv_ids += [invoice.id for invoice in so.invoice_ids]
#choose the view_mode accordingly
- if len(inv_ids) > 1:
- result['domain'] = "[('id','in',["+','.join(map(str, inv_ids))+"])]"
+ if len(inv_ids)>1:
+ res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_tree')
+ result.update({
+ 'view_mode': 'tree,form',
+ 'res_id': inv_ids or False
+ })
else:
res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_form')
- result['views'] = [(res and res[1] or False, 'form')]
- result['res_id'] = inv_ids and inv_ids[0] or False
+ result.update({
+ 'view_mode': 'form',
+ 'res_id': inv_ids and inv_ids[0] or False,
+ })
+ result.update(view_id = res and res[1] or False)
return result
-
def action_view_delivery(self, cr, uid, ids, context=None):
'''
This function returns an action that display existing delivery orders of given sale order ids. It can either be a in a list or in a form view, if there is only one delivery order to show.
diff --git a/addons/sale/test/manual_order_policy.yml b/addons/sale/test/manual_order_policy.yml
index d67677c8254..17ebeb9f86b 100644
--- a/addons/sale/test/manual_order_policy.yml
+++ b/addons/sale/test/manual_order_policy.yml
@@ -1,5 +1,5 @@
-
- I confirm the Quotation with "Deliver & invoice on demand".
+ I confirm the Quotation with "On Demand" order policy.
-
!workflow {model: sale.order, action: order_confirm, ref: sale_order_2}
-
@@ -9,7 +9,7 @@
sale_order = self.browse(cr, uid, ref("sale_order_2"))
assert len(sale_order.invoice_ids) == False, "Invoice should not created."
-
- I create advance invoice.
+ I create advance invoice where type is 'Fixed Price'.
-
!python {model: sale.advance.payment.inv}: |
ctx = context.copy()
@@ -24,7 +24,7 @@
order = self.browse(cr, uid, ref('sale_order_2'))
assert order.invoice_ids, "Invoice should be created after make advance invoice."
-
- I create advance invoice where payment method is 'all'.
+ I create advance invoice where type is 'Invoice all the Sale Order'.
-
!python {model: sale.advance.payment.inv}: |
ctx = context.copy()
@@ -32,11 +32,11 @@
pay_id = self.create(cr, uid, {'advance_payment_method': 'all'})
self.create_invoices(cr, uid, [pay_id], context=ctx)
-
- I check Invoice which made advance where payment method is 'all'.
+ I check Invoice which made advance where type is 'Invoice all the Sale Order'.
-
!python {model: sale.order}: |
order = self.browse(cr, uid, ref('sale_order_2'))
- assert order.invoice_ids, "Invoice should be created after make advance invoice where payment method is 'all'."
+ assert order.invoice_ids, "Invoice should be created after make advance invoice where type is 'Invoice all the Sale Order'."
-
I open the Invoice.
-
@@ -47,7 +47,7 @@
for invoice in so.invoice_ids:
wf_service.trg_validate(uid, 'account.invoice', invoice.id, 'invoice_open', cr)
-
- I pay the invoice
+ I pay the invoice.
-
!python {model: account.invoice}: |
sale_order = self.pool.get('sale.order')
@@ -65,7 +65,8 @@
!python {model: sale.order}: |
sale_order = self.browse(cr, uid, ref("sale_order_2"))
assert sale_order.invoice_ids, "Invoice should be created."
- assert sale_order.invoiced, "Order is not invoiced."
+ assert sale_order.invoice_exists, "Order is not invoiced."
+ assert sale_order.invoiced, "Order is not paid."
assert sale_order.state == 'progress', 'Order should be in Progress.'
-
From c669824898ad0bd597c8addc5ae11c3c38e73c79 Mon Sep 17 00:00:00 2001
From: Saurang Suthar
Date: Wed, 12 Sep 2012 14:58:57 +0530
Subject: [PATCH 190/408] [IMP]:improved code for opening employee form view
while clicking on Hire button and employee list view while selecting
Categories Structure
bzr revid: ssu@tinyerp.com-20120912092857-q7j1qje1p6q0dr2f
---
addons/hr/hr_view.xml | 2 +-
addons/hr_holidays/hr_holidays_view.xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/hr/hr_view.xml b/addons/hr/hr_view.xml
index 00ed2afbef2..5d4c2ae9d45 100644
--- a/addons/hr/hr_view.xml
+++ b/addons/hr/hr_view.xml
@@ -180,7 +180,7 @@
Employeeshr.employeeform
- tree,form
+ form,tree
diff --git a/addons/hr_holidays/hr_holidays_view.xml b/addons/hr_holidays/hr_holidays_view.xml
index 8bd00d58832..e1f18236d35 100644
--- a/addons/hr_holidays/hr_holidays_view.xml
+++ b/addons/hr_holidays/hr_holidays_view.xml
@@ -482,7 +482,7 @@
hr.employee.leave.tree
- hr.employee
+ hr.holidays.status
From 9dbe22e3612c0c727ad504386f21b7ab1858927a Mon Sep 17 00:00:00 2001
From: "Foram Katharotiya (OpenERP)"
Date: Wed, 12 Sep 2012 15:34:35 +0530
Subject: [PATCH 191/408] [IMP] Rename Our first company's blogpost !
bzr revid: fka@tinyerp.com-20120912100435-uo7l8hk2i5ajoesb
---
addons/portal/portal_demo.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/portal/portal_demo.xml b/addons/portal/portal_demo.xml
index 1ace02f3d7d..460954dde3e 100644
--- a/addons/portal/portal_demo.xml
+++ b/addons/portal/portal_demo.xml
@@ -19,7 +19,7 @@
- Our first company's blogpost !
+ Our company's first blog-post !mail.group
Date: Wed, 12 Sep 2012 16:11:38 +0530
Subject: [PATCH 192/408] [FIX] stock : Form open with a lable 'Transfer
Products' instead of 'Deliver products'.
bzr revid: mdi@tinyerp.com-20120912104138-5fv3xyr0aqt5dscd
---
addons/stock/wizard/stock_partial_picking.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/stock/wizard/stock_partial_picking.py b/addons/stock/wizard/stock_partial_picking.py
index b3720b8a51b..755da7c42ee 100644
--- a/addons/stock/wizard/stock_partial_picking.py
+++ b/addons/stock/wizard/stock_partial_picking.py
@@ -78,7 +78,7 @@ class stock_partial_picking(osv.osv_memory):
if context is None:
context={}
res = super(stock_partial_picking, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
- type = context.get('active_model','').split('.')[-1]
+ type = context.get('default_type', False)
if type:
doc = etree.XML(res['arch'])
for node in doc.xpath("//button[@name='do_partial']"):
From 215631a895f09e94acc3a1fe219314cd13649055 Mon Sep 17 00:00:00 2001
From: "Foram Katharotiya (OpenERP)"
Date: Wed, 12 Sep 2012 16:21:39 +0530
Subject: [PATCH 193/408] [IMP] change menu name on message in linkedin
bzr revid: fka@tinyerp.com-20120912105139-x2vh6kvzfnvagxoe
---
addons/web_linkedin/static/src/xml/linkedin.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/web_linkedin/static/src/xml/linkedin.xml b/addons/web_linkedin/static/src/xml/linkedin.xml
index 1a8009ab066..4956fd7df5a 100644
--- a/addons/web_linkedin/static/src/xml/linkedin.xml
+++ b/addons/web_linkedin/static/src/xml/linkedin.xml
@@ -30,7 +30,7 @@
LinkedIn access was not enabled on this server.
- Please ask your administrator to configure it in Settings > Configuration > Linkedin.
+ Please ask your administrator to configure it in Settings > Configuration > Sales > Social Network Integration.
\ No newline at end of file
From 2b8e7613a0b2031fca358312e349b3cc63965106 Mon Sep 17 00:00:00 2001
From: "Nimesh (Open ERP)"
Date: Wed, 12 Sep 2012 18:26:23 +0530
Subject: [PATCH 194/408] [IMP] reduce the call when rendering vote, do the
related changes in py, and improve the code for js and py
bzr revid: nco@tinyerp.com-20120912125623-ffrhgf84ttosjx44
---
addons/mail/mail_message.py | 25 ++++++++++++------------
addons/mail/mail_vote.py | 2 +-
addons/mail/static/src/js/mail.js | 30 +++++++++++++----------------
addons/mail/static/src/xml/mail.xml | 4 ++--
4 files changed, 29 insertions(+), 32 deletions(-)
diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py
index 1a2cd1881ed..86bbb405b9c 100644
--- a/addons/mail/mail_message.py
+++ b/addons/mail/mail_message.py
@@ -124,7 +124,7 @@ class mail_message(osv.Model):
'unread': fields.function(_get_unread, fnct_search=_search_unread,
type='boolean', string='Unread',
help='Functional field to search for unread messages linked to uid'),
- 'vote_user_ids': fields.many2many('mail.vote', 'message_vote_rel', 'message_id', 'vote_id', 'Votes'),
+ 'vote_user_ids': fields.many2many('res.users', 'mail_vote', 'message_id', 'user_id', 'Votes'),
}
@@ -146,21 +146,20 @@ class mail_message(osv.Model):
#---------------------------------------------------
#Mail Vote system (Like or Unlike comments
#-----------------------------------------------------
- def vote_toggle(self, cr, uid, ids, context=None):
+ def vote_toggle(self, cr, uid, ids, user_ids=None, context=None):
'''
Toggles when Comment is liked or unlike.
create vote entries if current user like comment..
'''
+ if not user_ids: user_ids = [uid]
vote_pool = self.pool.get('mail.vote')
- new_vote_id = False
+
for message in self.browse(cr, uid, ids, context):
- voters_ids = [x.id for x in message.vote_user_ids if x.user_id.id == uid]
+ voters_ids = [x.id for x in message.vote_user_ids if x.id == uid]
if not voters_ids:
- new_vote_id = vote_pool.create(cr, uid, {'msg_id': message.id, 'user_id': uid}, context=context)
- self.write(cr, uid, ids, {'vote_user_ids': [(4, new_vote_id)]}, context=context)
+ self.write(cr, uid, ids, {'vote_user_ids': [(4, user_id) for user_id in user_ids]}, context=context)
else:
- self.write(cr, uid, ids, {'vote_user_ids': [(3, voters_ids[0])]}, context=context)
- vote_pool.unlink(cr, uid, voters_ids, context=context)
+ self.write(cr, uid, ids, {'vote_user_ids': [(3, uid)]}, context=context)
return True
#------------------------------------------------------
@@ -170,12 +169,14 @@ class mail_message(osv.Model):
def _message_dict_get(self, cr, uid, msg, context=None):
""" Return a dict representation of the message browse record. """
vote_pool = self.pool.get('mail.vote')
+ has_voted = False;
+ vote_ids = []
attachment_ids = self.pool.get('ir.attachment').name_get(cr, uid, [x.id for x in msg.attachment_ids], context=context)
vote_ids = vote_pool.name_get(cr, uid, [x.id for x in msg.vote_user_ids], context=context)
- has_voted = False;
- for vote in msg.vote_user_ids:
- if (uid == vote.user_id.id):
- has_voted = True;
+ if msg.vote_user_ids:
+ for user_id in msg.vote_user_ids:
+ if (uid == user_id.id):
+ has_voted = True;
author_id = self.pool.get('res.partner').name_get(cr, uid, [msg.author_id.id], context=context)[0]
author_user_id = self.pool.get('res.users').name_get(cr, uid, [msg.author_id.user_ids[0].id], context=context)[0]
partner_ids = self.pool.get('res.partner').name_get(cr, uid, [x.id for x in msg.partner_ids], context=context)
diff --git a/addons/mail/mail_vote.py b/addons/mail/mail_vote.py
index 5d63de80864..81ca4e4e75e 100644
--- a/addons/mail/mail_vote.py
+++ b/addons/mail/mail_vote.py
@@ -30,7 +30,7 @@ class mail_vote(osv.Model):
_name = 'mail.vote'
_description = 'Mail Vote'
_columns = {
- 'msg_id': fields.many2one('mail.message', 'Message', required=True),
+ 'message_id': fields.many2one('mail.message', 'Message', required=True),
'user_id': fields.many2one('res.users', 'User', required=True),
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js
index c5d4119881c..7ede8bdc7e3 100644
--- a/addons/mail/static/src/js/mail.js
+++ b/addons/mail/static/src/js/mail.js
@@ -272,7 +272,7 @@ openerp.mail = function(session) {
});
return
},
-
+
find_parent_element: function(name, message_id){
parent_element = false;
_.each($(name), function(element){
@@ -283,27 +283,22 @@ openerp.mail = function(session) {
return parent_element;
},
- render_vote: function(message_id){
+ render_vote: function(record){
+ vote_element = session.web.qweb.render('VoteDisplay', {});
+ var message_id = record.id
var self = this;
- this.ds_message.call('message_read', [[parseInt(message_id)]]).then(function(result){
- vote_count = 0;
- _.each(result, function(res){
- if (res.vote_user_ids){
- vote_count = res.vote_user_ids.length;
- }
- parent_element = self.find_parent_element(".oe_mail_msg_vote", message_id);
- vote_element = session.web.qweb.render('VoteDisplay', {'msg_id': message_id, 'vote_count': vote_count, 'has_voted': res.has_voted});
- $(parent_element).html(vote_element);
- self.add_vote_event($(parent_element));
- });
- });
+ var to_render_element = false;
+ vote_element = session.web.qweb.render('VoteDisplay', {'message_id': message_id, 'vote_count': record.vote_user_ids.length, 'has_voted': record.has_voted});
+ parent_element = self.find_parent_element(".oe_mail_msg_vote",message_id);
+ $(parent_element).html(vote_element);
+ self.add_vote_event($(parent_element));
},
subscribe_vote: function(message_id){
var self = this;
this.mail_message = new session.web.DataSet(this, 'mail.message');
return this.mail_message.call('vote_toggle', [[parseInt(message_id)]]).then(function(result){
- self.render_vote(message_id);
+ //self.render_vote(message_id);
});
},
@@ -481,8 +476,6 @@ openerp.mail = function(session) {
* - record.is_author: is the current user the author of the record */
display_record: function (record) {
// formatting and additional fields
- //Render Votes.
- this.render_vote(record.id);
record.date = session.web.format_value(record.date, {type:"datetime"});
record.timerelative = $.timeago(record.date);
if (record.type == 'email') {
@@ -509,6 +502,9 @@ openerp.mail = function(session) {
moreClass: 'oe_mail_expand',
lessClass: 'oe_mail_reduce',
});
+
+ //Render Votes.
+ this.render_vote(record);
},
/** Display 'show more' button */
diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml
index cd17838dadf..696d52e1766 100644
--- a/addons/mail/static/src/xml/mail.xml
+++ b/addons/mail/static/src/xml/mail.xml
@@ -99,12 +99,12 @@
-
+ +1
-
+ -1
From 553c04b260e63cadbffbd7391b4f5ec7417710a4 Mon Sep 17 00:00:00 2001
From: "Nimesh (Open ERP)"
Date: Wed, 12 Sep 2012 18:29:55 +0530
Subject: [PATCH 195/408] [REMOVE] remove unused variable.
bzr revid: nco@tinyerp.com-20120912125955-djn6ivs3vtkrw49n
---
addons/mail/static/src/js/mail.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js
index 7ede8bdc7e3..ff0dfaa01b8 100644
--- a/addons/mail/static/src/js/mail.js
+++ b/addons/mail/static/src/js/mail.js
@@ -285,9 +285,8 @@ openerp.mail = function(session) {
render_vote: function(record){
vote_element = session.web.qweb.render('VoteDisplay', {});
- var message_id = record.id
var self = this;
- var to_render_element = false;
+ var message_id = record.id
vote_element = session.web.qweb.render('VoteDisplay', {'message_id': message_id, 'vote_count': record.vote_user_ids.length, 'has_voted': record.has_voted});
parent_element = self.find_parent_element(".oe_mail_msg_vote",message_id);
$(parent_element).html(vote_element);
From 951b6653cd58832ad2f546f05168c4da89c24ff7 Mon Sep 17 00:00:00 2001
From: "Nimesh (Open ERP)"
Date: Wed, 12 Sep 2012 18:45:51 +0530
Subject: [PATCH 196/408] [ADD] add function to fatch the new vote and render
it.
bzr revid: nco@tinyerp.com-20120912131551-xzz16f5zuz3mlz6r
---
addons/mail/static/src/js/mail.js | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js
index ff0dfaa01b8..084c1001be7 100644
--- a/addons/mail/static/src/js/mail.js
+++ b/addons/mail/static/src/js/mail.js
@@ -292,12 +292,17 @@ openerp.mail = function(session) {
$(parent_element).html(vote_element);
self.add_vote_event($(parent_element));
},
-
+ fetch_voters: function (message_id) {
+ var self= this
+ this.ds_message.call('message_read', [[parseInt(message_id)]]).then(function(result){
+ self.render_vote(result[0]);
+ });
+ },
subscribe_vote: function(message_id){
var self = this;
this.mail_message = new session.web.DataSet(this, 'mail.message');
return this.mail_message.call('vote_toggle', [[parseInt(message_id)]]).then(function(result){
- //self.render_vote(message_id);
+ self.fetch_voters(message_id);
});
},
From 885ef0e8bac253e0294ab8498fdee61e99666c14 Mon Sep 17 00:00:00 2001
From: "Randhir Mayatra (OpenERP)"
Date: Wed, 12 Sep 2012 18:50:01 +0530
Subject: [PATCH 197/408] [IMP]make changes into purchase view
bzr revid: rma@tinyerp.com-20120912132001-l52d44rvte3vgei5
---
addons/account/res_config_view.xml | 2 --
addons/purchase/res_config.py | 3 +++
addons/purchase/res_config_view.xml | 10 ++++++++++
3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/addons/account/res_config_view.xml b/addons/account/res_config_view.xml
index bc8ace5c262..2ff931eda62 100644
--- a/addons/account/res_config_view.xml
+++ b/addons/account/res_config_view.xml
@@ -240,11 +240,9 @@
-
-
diff --git a/addons/purchase/res_config.py b/addons/purchase/res_config.py
index 3d9c858cec5..4fb34afa88d 100644
--- a/addons/purchase/res_config.py
+++ b/addons/purchase/res_config.py
@@ -62,6 +62,9 @@ class purchase_config_settings(osv.osv_memory):
help="""Purchase Requisitions are used when you want to request quotations from several suppliers for a given set of products.
You can configure per product if you directly do a Request for Quotation
to one supplier or if you want a purchase requisition to negotiate with several suppliers."""),
+ 'group_analytic_account_for_purchases': fields.boolean('analytic accounting for purchases',
+ implied_group='purchase.group_analytic_accounting',
+ help="Allows you to specify an analytic account on purchase orders."),
}
_defaults = {
diff --git a/addons/purchase/res_config_view.xml b/addons/purchase/res_config_view.xml
index 00e0b6108e8..824bbdfbc7a 100644
--- a/addons/purchase/res_config_view.xml
+++ b/addons/purchase/res_config_view.xml
@@ -77,6 +77,16 @@
From 6a4d58ace80320db0b42bc86ab7877bcf14b1e47 Mon Sep 17 00:00:00 2001
From: "Mayur Maheshwari (OpenERP)"
Date: Thu, 13 Sep 2012 13:00:45 +0530
Subject: [PATCH 206/408] [IMP]stock : set group on warehouse user and default
value in action
bzr revid: mma@tinyerp.com-20120913073045-ee9fidsc4inufjha
---
addons/stock/board_warehouse_view.xml | 2 +-
addons/stock/stock_view.xml | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/addons/stock/board_warehouse_view.xml b/addons/stock/board_warehouse_view.xml
index b223e731e8f..839a99c1fa7 100644
--- a/addons/stock/board_warehouse_view.xml
+++ b/addons/stock/board_warehouse_view.xml
@@ -61,7 +61,7 @@
parent="base.menu_reporting_dashboard"
action="open_board_warehouse"
sequence="25"
- groups="group_stock_manager"/>
+ groups="stock.group_stock_user"/>
diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml
index f278edb0758..26616cca5a4 100644
--- a/addons/stock/stock_view.xml
+++ b/addons/stock/stock_view.xml
@@ -1496,7 +1496,7 @@
tree,form['|','&',('picking_id','=',False),('location_id.usage', 'in', ['customer','supplier']),'&',('picking_id','!=',False),('picking_id.type','=','in')]
-
+ {'product_receive': True, 'search_default_future': True, 'picking_type': 'in'}
Click to register a product reception.
@@ -1631,7 +1631,7 @@
tree,form['|','&',('picking_id','=',False),('location_dest_id.usage', 'in', ['customer','supplier']),'&',('picking_id','!=',False),('picking_id.type','=','out')]
-
+ {'picking_type': 'out', 'search_default_future': True}
You will find in this list all products you have to deliver to
From df8cddd9df893d89ea66e055c49c89b0af23bf2d Mon Sep 17 00:00:00 2001
From: "ajay javiya (OpenERP)"
Date: Thu, 13 Sep 2012 14:56:26 +0530
Subject: [PATCH 207/408] [ADD]:Add button for close period
bzr revid: aja@tinyerp.com-20120913092626-re2ox32a4dcwugcc
---
addons/account/account_view.xml | 1 +
1 file changed, 1 insertion(+)
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index 8c0de73ef8c..b1f9b7f0b40 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -102,6 +102,7 @@
+
From a931a9f298e1fb92ff362e474a4dc15cb35849d3 Mon Sep 17 00:00:00 2001
From: "Turkesh Patel (Open ERP)"
Date: Thu, 13 Sep 2012 14:58:14 +0530
Subject: [PATCH 208/408] [IMP] improved code of periodical vat declaration
wizard.
bzr revid: tpa@tinyerp.com-20120913092814-eoxgnv0vzydpwfp3
---
addons/l10n_be/__init__.py | 1 -
addons/l10n_be/company.py | 45 -------------------
.../wizard/l10n_be_account_vat_declaration.py | 22 ++++-----
3 files changed, 12 insertions(+), 56 deletions(-)
delete mode 100644 addons/l10n_be/company.py
diff --git a/addons/l10n_be/__init__.py b/addons/l10n_be/__init__.py
index 1b2677d295e..7bdc1f61b1f 100644
--- a/addons/l10n_be/__init__.py
+++ b/addons/l10n_be/__init__.py
@@ -19,7 +19,6 @@
#
##############################################################################
-import company
import wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/l10n_be/company.py b/addons/l10n_be/company.py
deleted file mode 100644
index 118696ec9f6..00000000000
--- a/addons/l10n_be/company.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 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 osv
-
-class res_company(osv.osv):
- _inherit = "res.company"
- _description = 'Company'
-
- def _get_default_ad(self, addresses):
- name = email = phone = city = post_code = address = country_code = ""
- for ads in addresses:
- if ads.type == 'default':
- city = ads.city or ""
- post_code = ads.zip or ""
- if ads.street:
- address = ads.street or ""
- if ads.street2:
- address += " " + ads.street2
- if ads.country_id:
- country_code = ads.country_id and ads.country_id.code or ""
- name = ads.name or ""
- email = ads.email or ""
- phone = ads.phone or ""
- return name, email, phone, city, post_code, address, country_code
-res_company()
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/l10n_be/wizard/l10n_be_account_vat_declaration.py b/addons/l10n_be/wizard/l10n_be_account_vat_declaration.py
index ab6ea82eeab..5eb4215e576 100644
--- a/addons/l10n_be/wizard/l10n_be_account_vat_declaration.py
+++ b/addons/l10n_be/wizard/l10n_be_account_vat_declaration.py
@@ -70,6 +70,7 @@ class l10n_be_vat_declaration(osv.osv_memory):
obj_tax_code = self.pool.get('account.tax.code')
obj_acc_period = self.pool.get('account.period')
obj_user = self.pool.get('res.users')
+ obj_partner = self.pool.get('res.partner')
mod_obj = self.pool.get('ir.model.data')
if context is None:
@@ -93,8 +94,9 @@ class l10n_be_vat_declaration(osv.osv_memory):
ctx['period_id'] = data['period_id'][0]
tax_info = obj_tax_code.read(cr, uid, tax_code_ids, ['code','sum_period'], context=ctx)
- name = email = phone = address = post_code = city = country_code = ''
- name, email, phone, city, post_code, address, country_code = self.pool.get('res.company')._get_default_ad(obj_company.partner_id)
+ default_address = obj_partner.address_get(cr, uid, [obj_company.partner_id.id])
+ default_address_id = default_address.get("default", obj_company.partner_id.id)
+ address_id= obj_partner.browse(cr, uid, default_address_id, context)
account_period = obj_acc_period.browse(cr, uid, data['period_id'][0], context=context)
issued_by = vat_no[:2]
@@ -106,21 +108,21 @@ class l10n_be_vat_declaration(osv.osv_memory):
ending_month = account_period.date_stop[5:7]
quarter = str(((int(starting_month) - 1) / 3) + 1)
- if not email:
+ if not address_id.email:
raise osv.except_osv(_('Insufficient Data!'),_('No email address associated with the company.'))
- if not phone:
+ if not address_id.phone:
raise osv.except_osv(_('Insufficient Data!'),_('No phone associated with the company.'))
file_data = {
'issued_by': issued_by,
'vat_no': vat_no,
'only_vat': vat_no[2:],
'cmpny_name': obj_company.name,
- 'address': address,
- 'post_code': post_code,
- 'city': city,
- 'country_code': country_code,
- 'email': email,
- 'phone': phone.replace('.','').replace('/','').replace('(','').replace(')','').replace(' ',''),
+ 'address': "%s %s"%(address_id.street or "",address_id.street2 or ""),
+ 'post_code': address_id.zip or "",
+ 'city': address_id.city or "",
+ 'country_code': address_id.country_id and address_id.country_id.code or "",
+ 'email': address_id.email or "",
+ 'phone': address_id.phone.replace('.','').replace('/','').replace('(','').replace(')','').replace(' ',''),
'send_ref': send_ref,
'quarter': quarter,
'month': starting_month,
From f35f86745e5c652421261e7eccf312d14e61d471 Mon Sep 17 00:00:00 2001
From: Vishmita
Date: Thu, 13 Sep 2012 15:09:21 +0530
Subject: [PATCH 209/408] [FIX]change image path of node.
bzr revid: vja@tinyerp.com-20120913093921-hv1jgfahc1cn2ef7
---
addons/process/static/src/js/process.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/process/static/src/js/process.js b/addons/process/static/src/js/process.js
index bbf9080de95..57c6f196012 100644
--- a/addons/process/static/src/js/process.js
+++ b/addons/process/static/src/js/process.js
@@ -143,7 +143,7 @@ instance.web.ViewManager.include({
var image_node = nodes.kind == "subflow" ? "node-subflow" : "node";
image_node = nodes.gray ? image_node + "-gray" : image_node;
image_node = nodes.active ? 'node-current': image_node;
- var img_src = '/web_process/static/src/img/'+ image_node + '.png';
+ var img_src = '/process/static/src/img/'+ image_node + '.png';
var image = r['image'](img_src, nodes.x-25, nodes.y,150, 100).attr({"cursor": "default"}) .mousedown(function() { return false; });
//For Node
var process_node = r['rect'](nodes.x, nodes.y, 150, 150).attr({stroke: "none"});
From 2bd286e93a2842bb242aefd41f6f860dd93e2d5e Mon Sep 17 00:00:00 2001
From: "Khushboo Bhatt (Open ERP)"
Date: Thu, 13 Sep 2012 15:16:11 +0530
Subject: [PATCH 210/408] [REM]account_assets:removed graph view form assets
bzr revid: kbh@tinyerp.com-20120913094611-4k5itc8wlo7w68tv
---
addons/account_asset/account_asset_view.xml | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/addons/account_asset/account_asset_view.xml b/addons/account_asset/account_asset_view.xml
index bb0222d5e4f..3fab306863c 100644
--- a/addons/account_asset/account_asset_view.xml
+++ b/addons/account_asset/account_asset_view.xml
@@ -129,7 +129,7 @@
-
+
@@ -159,11 +159,6 @@
-
-
-
-
-
From d9629687e97d3307d4a995096405f4bea95496b0 Mon Sep 17 00:00:00 2001
From: niv-openerp
Date: Thu, 13 Sep 2012 11:54:14 +0200
Subject: [PATCH 211/408] [IMP] removed default_selection
bzr revid: nicolas.vanhoren@openerp.com-20120913095414-n0r5veemxniao6hi
---
addons/account/account_view.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index d89108c7726..a535d891d2e 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -1052,7 +1052,7 @@
account.move.line
-
+
@@ -1943,7 +1943,7 @@
account.move.line
-
+
From 7ee881b98d0af19f81888b967457873f785f922f Mon Sep 17 00:00:00 2001
From: "Mayur Maheshwari (OpenERP)"
Date: Thu, 13 Sep 2012 17:08:32 +0530
Subject: [PATCH 212/408] [IMP]stock : add button claim on right side of
delivery order and added data file for claim and give a acces right of borad
to warehouse user
bzr revid: mma@tinyerp.com-20120913113832-80jmjtoj83pjflra
---
addons/claim_from_delivery/__openerp__.py | 4 ++-
.../claim_delivery_data.xml | 10 ++++++++
.../claim_delivery_view.xml | 25 +++++++++++++++----
addons/stock/security/ir.model.access.csv | 3 ++-
4 files changed, 35 insertions(+), 7 deletions(-)
create mode 100644 addons/claim_from_delivery/claim_delivery_data.xml
diff --git a/addons/claim_from_delivery/__openerp__.py b/addons/claim_from_delivery/__openerp__.py
index 9c4395927af..9e3f7f59ca2 100644
--- a/addons/claim_from_delivery/__openerp__.py
+++ b/addons/claim_from_delivery/__openerp__.py
@@ -30,7 +30,9 @@ Create a claim from a delivery order.
Adds a Claim link to the delivery order.
""",
- 'data' : ['claim_delivery_view.xml'],
+ 'data' : [
+ 'claim_delivery_view.xml',
+ 'claim_delivery_data.xml',],
'auto_install': False,
'installable': True,
'certificate' : '001101649349223746957',
diff --git a/addons/claim_from_delivery/claim_delivery_data.xml b/addons/claim_from_delivery/claim_delivery_data.xml
new file mode 100644
index 00000000000..d5faa279434
--- /dev/null
+++ b/addons/claim_from_delivery/claim_delivery_data.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+ Delivery Order
+ stock.picking.out
+
+
+
\ No newline at end of file
diff --git a/addons/claim_from_delivery/claim_delivery_view.xml b/addons/claim_from_delivery/claim_delivery_view.xml
index f345484b4a9..17803b1f546 100644
--- a/addons/claim_from_delivery/claim_delivery_view.xml
+++ b/addons/claim_from_delivery/claim_delivery_view.xml
@@ -1,11 +1,26 @@
-
+
+ Claim From Delivery
+ crm.claim
+ form
+
+ {}
+
+
+
+ crm.claim.from_delivery.form
+ stock.picking.out
+
+
+
+
+
From ca4326bbd1e3c7c9afd4415931ce6194f376495b Mon Sep 17 00:00:00 2001
From: Raphael Collet
Date: Fri, 14 Sep 2012 15:21:13 +0200
Subject: [PATCH 234/408] [IMP] portal: remove groups Portal Officer and Portal
Manager
bzr revid: rco@openerp.com-20120914132113-15r6rcmiwb5tr5ia
---
addons/portal/__openerp__.py | 1 -
addons/portal/portal_data.xml | 6 ++++
addons/portal/portal_view.xml | 2 +-
addons/portal/security/ir.model.access.csv | 2 --
addons/portal/security/portal_security.xml | 33 ---------------------
addons/portal/wizard/portal_wizard_view.xml | 2 +-
addons/portal/wizard/share_wizard.py | 3 --
addons/portal/wizard/share_wizard_view.xml | 6 ++--
8 files changed, 11 insertions(+), 44 deletions(-)
delete mode 100644 addons/portal/security/portal_security.xml
diff --git a/addons/portal/__openerp__.py b/addons/portal/__openerp__.py
index d7356fc9ce5..f5e3c9ff452 100644
--- a/addons/portal/__openerp__.py
+++ b/addons/portal/__openerp__.py
@@ -44,7 +44,6 @@ very handy when used in combination with the module 'share'.
""",
'website': 'http://www.openerp.com',
'data': [
- 'security/portal_security.xml',
'security/ir.model.access.csv',
'portal_data.xml',
'portal_view.xml',
diff --git a/addons/portal/portal_data.xml b/addons/portal/portal_data.xml
index eb06ca656d6..42447afdfd5 100644
--- a/addons/portal/portal_data.xml
+++ b/addons/portal/portal_data.xml
@@ -2,6 +2,12 @@
+
+
+ Portal Member
+ Portal members can access information through the portal menu. Also, they are chrooted in this specific menu.
+
+
Portal
diff --git a/addons/portal/portal_view.xml b/addons/portal/portal_view.xml
index fd15a842405..924f74565cd 100644
--- a/addons/portal/portal_view.xml
+++ b/addons/portal/portal_view.xml
@@ -84,7 +84,7 @@
-
+
diff --git a/addons/portal/security/ir.model.access.csv b/addons/portal/security/ir.model.access.csv
index 56b3ae5f269..29c43bb4815 100644
--- a/addons/portal/security/ir.model.access.csv
+++ b/addons/portal/security/ir.model.access.csv
@@ -1,8 +1,6 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_all,access.portal.all,model_res_portal,,1,0,0,0
access_widget_all,access.portal.widget.all,model_res_portal_widget,,1,0,0,0
-access_manager,access.portal.manager,model_res_portal,group_portal_manager,1,1,1,1
-access_widget_manager,access.portal.widget.manager,model_res_portal_widget,group_portal_manager,1,1,1,1
access_mail_message,mail.message,mail.model_mail_message,group_portal_member,1,0,1,1
access_mail_message_all,mail.message.all,mail.model_mail_message,group_portal_member,1,0,0,0
access_mail_thread,mail.thread,mail.model_mail_thread,group_portal_member,1,0,0,0
diff --git a/addons/portal/security/portal_security.xml b/addons/portal/security/portal_security.xml
deleted file mode 100644
index 4a493204d67..00000000000
--- a/addons/portal/security/portal_security.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
- Portal Member
- Portal members can access information through the portal menu. Also, they are chrooted in this specific menu.
-
-
-
- Portal
-
- 25
-
-
-
-
- Officer
- Portal officers can create new portal users with the portal wizard.
-
-
-
-
- Manager
- Portal managers have access to the portal definitions, and can easily configure the users, access rights and menus of portal users.
-
-
-
-
-
-
-
diff --git a/addons/portal/wizard/portal_wizard_view.xml b/addons/portal/wizard/portal_wizard_view.xml
index 0cf84646bab..7a81def67b0 100644
--- a/addons/portal/wizard/portal_wizard_view.xml
+++ b/addons/portal/wizard/portal_wizard_view.xml
@@ -8,7 +8,7 @@
res_model="res.portal.wizard"
view_type="form" view_mode="form"
key2="client_action_multi" target="new"
- groups="group_portal_officer"/>
+ groups="base.group_partner_manager"/>
diff --git a/addons/portal/wizard/share_wizard.py b/addons/portal/wizard/share_wizard.py
index ca950a61b08..e56e7517348 100644
--- a/addons/portal/wizard/share_wizard.py
+++ b/addons/portal/wizard/share_wizard.py
@@ -44,9 +44,6 @@ class share_wizard_portal(osv.TransientModel):
'group_ids': fields.many2many('res.groups', 'share_wizard_res_group_rel', 'share_id', 'group_id', 'Existing groups', domain=[('share', '=', False)]),
}
- def is_portal_manager(self, cr, uid, context=None):
- return self.has_group(cr, uid, module='portal', group_xml_id='group_portal_manager', context=context)
-
def _check_preconditions(self, cr, uid, wizard_data, context=None):
if wizard_data.user_type == 'existing':
self._assert(wizard_data.user_ids,
diff --git a/addons/portal/wizard/share_wizard_view.xml b/addons/portal/wizard/share_wizard_view.xml
index 72ae857eaaf..065a7aa317e 100644
--- a/addons/portal/wizard/share_wizard_view.xml
+++ b/addons/portal/wizard/share_wizard_view.xml
@@ -36,12 +36,12 @@
-
+
-
-
+
+
From be03938f47cd835674f3cecd23792d7934604278 Mon Sep 17 00:00:00 2001
From: Raphael Collet
Date: Fri, 14 Sep 2012 15:41:16 +0200
Subject: [PATCH 235/408] [FIX] portal: move group definition of portal back to
security/portal_security.xml
bzr revid: rco@openerp.com-20120914134116-sg2yqsro8c62bxg2
---
addons/portal/portal_data.xml | 6 ------
addons/portal/security/portal_security.xml | 13 +++++++++++++
2 files changed, 13 insertions(+), 6 deletions(-)
create mode 100644 addons/portal/security/portal_security.xml
diff --git a/addons/portal/portal_data.xml b/addons/portal/portal_data.xml
index 42447afdfd5..eb06ca656d6 100644
--- a/addons/portal/portal_data.xml
+++ b/addons/portal/portal_data.xml
@@ -2,12 +2,6 @@
-
-
- Portal Member
- Portal members can access information through the portal menu. Also, they are chrooted in this specific menu.
-
-
Portal
diff --git a/addons/portal/security/portal_security.xml b/addons/portal/security/portal_security.xml
new file mode 100644
index 00000000000..9a71b9b181f
--- /dev/null
+++ b/addons/portal/security/portal_security.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Portal
+ Portal members can access information through the portal menu. Also, they are chrooted in this specific menu.
+
+
+
+
+
From 5720ae3a90d11428c610c0c040f37315ce433488 Mon Sep 17 00:00:00 2001
From: Raphael Collet
Date: Fri, 14 Sep 2012 15:42:51 +0200
Subject: [PATCH 236/408] [IMP] portal: rename xml id
'portal.group_portal_member' to 'portal.group_portal'
bzr revid: rco@openerp.com-20120914134251-answ8jr65vfeeiz3
---
addons/portal/portal_data.xml | 2 +-
addons/portal/portal_view.xml | 2 +-
addons/portal/security/ir.model.access.csv | 14 ++--
addons/portal/security/portal_security.xml | 2 +-
.../portal_claim/security/ir.model.access.csv | 4 +-
.../portal_claim/security/portal_security.xml | 2 +-
.../portal_event/security/ir.model.access.csv | 4 +-
.../portal_event/security/portal_security.xml | 4 +-
.../security/ir.model.access.csv | 10 +--
.../security/ir.model.access.csv | 8 +--
.../security/portal_security.xml | 2 +-
.../security/ir.model.access.csv | 4 +-
.../security/portal_security.xml | 2 +-
.../portal_sale/security/ir.model.access.csv | 64 +++++++++----------
.../portal_sale/security/portal_security.xml | 12 ++--
15 files changed, 68 insertions(+), 68 deletions(-)
diff --git a/addons/portal/portal_data.xml b/addons/portal/portal_data.xml
index eb06ca656d6..5edb4bed8c7 100644
--- a/addons/portal/portal_data.xml
+++ b/addons/portal/portal_data.xml
@@ -4,7 +4,7 @@
Portal
-
+
diff --git a/addons/portal/portal_view.xml b/addons/portal/portal_view.xml
index 924f74565cd..5241d7cf54f 100644
--- a/addons/portal/portal_view.xml
+++ b/addons/portal/portal_view.xml
@@ -5,7 +5,7 @@
diff --git a/addons/portal/security/ir.model.access.csv b/addons/portal/security/ir.model.access.csv
index 29c43bb4815..60687e8a0cc 100644
--- a/addons/portal/security/ir.model.access.csv
+++ b/addons/portal/security/ir.model.access.csv
@@ -1,10 +1,10 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_all,access.portal.all,model_res_portal,,1,0,0,0
access_widget_all,access.portal.widget.all,model_res_portal_widget,,1,0,0,0
-access_mail_message,mail.message,mail.model_mail_message,group_portal_member,1,0,1,1
-access_mail_message_all,mail.message.all,mail.model_mail_message,group_portal_member,1,0,0,0
-access_mail_thread,mail.thread,mail.model_mail_thread,group_portal_member,1,0,0,0
-access_mail_followers,mail.followers,mail.model_mail_followers,group_portal_member,1,0,1,1
-access_mail_notification,mail.notification,mail.model_mail_notification,group_portal_member,1,0,1,0
-access_mail_group,mail.group,mail.model_mail_group,group_portal_member,1,0,0,0
-access_mail_alias,mail.alias,mail.model_mail_alias,group_portal_member,1,0,0,0
+access_mail_message,mail.message,mail.model_mail_message,group_portal,1,0,1,1
+access_mail_message_all,mail.message.all,mail.model_mail_message,group_portal,1,0,0,0
+access_mail_thread,mail.thread,mail.model_mail_thread,group_portal,1,0,0,0
+access_mail_followers,mail.followers,mail.model_mail_followers,group_portal,1,0,1,1
+access_mail_notification,mail.notification,mail.model_mail_notification,group_portal,1,0,1,0
+access_mail_group,mail.group,mail.model_mail_group,group_portal,1,0,0,0
+access_mail_alias,mail.alias,mail.model_mail_alias,group_portal,1,0,0,0
diff --git a/addons/portal/security/portal_security.xml b/addons/portal/security/portal_security.xml
index 9a71b9b181f..0bf4cb2dcfc 100644
--- a/addons/portal/security/portal_security.xml
+++ b/addons/portal/security/portal_security.xml
@@ -3,7 +3,7 @@
-
+ PortalPortal members can access information through the portal menu. Also, they are chrooted in this specific menu.
diff --git a/addons/portal_claim/security/ir.model.access.csv b/addons/portal_claim/security/ir.model.access.csv
index 554c66cc998..ab2a2f66770 100644
--- a/addons/portal_claim/security/ir.model.access.csv
+++ b/addons/portal_claim/security/ir.model.access.csv
@@ -1,3 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-access_crm_claim,crm.claim,crm_claim.model_crm_claim,portal.group_portal_member,1,0,0,0
-access_crm_claim_stage,crm.claim.stage,crm_claim.model_crm_claim_stage,portal.group_portal_member,1,0,0,0
+access_crm_claim,crm.claim,crm_claim.model_crm_claim,portal.group_portal,1,0,0,0
+access_crm_claim_stage,crm.claim.stage,crm_claim.model_crm_claim_stage,portal.group_portal,1,0,0,0
diff --git a/addons/portal_claim/security/portal_security.xml b/addons/portal_claim/security/portal_security.xml
index e902bd043ad..9fc47c4cfb0 100644
--- a/addons/portal_claim/security/portal_security.xml
+++ b/addons/portal_claim/security/portal_security.xml
@@ -6,7 +6,7 @@
Portal Personal Claims[('partner_id','child_of',user.partner_id.id)]
-
+
diff --git a/addons/portal_event/security/ir.model.access.csv b/addons/portal_event/security/ir.model.access.csv
index b418acbb9c4..7418b08bb4b 100644
--- a/addons/portal_event/security/ir.model.access.csv
+++ b/addons/portal_event/security/ir.model.access.csv
@@ -1,3 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-access_event,event,event.model_event_event,portal.group_portal_member,1,0,0,0
-access_registration,registration,event.model_event_registration,portal.group_portal_member,1,0,0,0
+access_event,event,event.model_event_event,portal.group_portal,1,0,0,0
+access_registration,registration,event.model_event_registration,portal.group_portal,1,0,0,0
diff --git a/addons/portal_event/security/portal_security.xml b/addons/portal_event/security/portal_security.xml
index 6a3ed0ac786..74b2372c147 100644
--- a/addons/portal_event/security/portal_security.xml
+++ b/addons/portal_event/security/portal_security.xml
@@ -6,14 +6,14 @@
Portal Visible Events[('visibility', '=', 'public')]
-
+ Portal Personal Registrations[('partner_id','child_of',user.partner_id.id)]
-
+
diff --git a/addons/portal_hr_employees/security/ir.model.access.csv b/addons/portal_hr_employees/security/ir.model.access.csv
index 6131f49d749..d18aeb90e1c 100644
--- a/addons/portal_hr_employees/security/ir.model.access.csv
+++ b/addons/portal_hr_employees/security/ir.model.access.csv
@@ -1,6 +1,6 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-access_hr_employee_user,hr.employee user,hr.model_hr_employee,portal.group_portal_member,1,0,0,0
-access_res_partner,res.partner,base.model_res_partner,portal.group_portal_member,1,0,0,0
-access_res_partner_address,res.partner_address,base.model_res_partner_address,portal.group_portal_member,1,0,0,0
-access_res_partner_category,res.partner_category,base.model_res_partner_category,portal.group_portal_member,1,0,0,0
-access_res_partner_title,res.partner_title,base.model_res_partner_title,portal.group_portal_member,1,0,0,0
+access_hr_employee_user,hr.employee user,hr.model_hr_employee,portal.group_portal,1,0,0,0
+access_res_partner,res.partner,base.model_res_partner,portal.group_portal,1,0,0,0
+access_res_partner_address,res.partner_address,base.model_res_partner_address,portal.group_portal,1,0,0,0
+access_res_partner_category,res.partner_category,base.model_res_partner_category,portal.group_portal,1,0,0,0
+access_res_partner_title,res.partner_title,base.model_res_partner_title,portal.group_portal,1,0,0,0
diff --git a/addons/portal_project/security/ir.model.access.csv b/addons/portal_project/security/ir.model.access.csv
index dceca5ba8bb..85463868ee1 100644
--- a/addons/portal_project/security/ir.model.access.csv
+++ b/addons/portal_project/security/ir.model.access.csv
@@ -1,5 +1,5 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-access_task,tasks,project.model_project_task,portal.group_portal_member,1,0,0,0
-access_task_type,task_type,project.model_project_task_type,portal.group_portal_member,1,0,0,0
-access_task_work,task_work,project.model_project_task_work,portal.group_portal_member,1,0,0,0
-access_project_category,project_category,project.model_project_category,portal.group_portal_member,1,0,0,0
+access_task,tasks,project.model_project_task,portal.group_portal,1,0,0,0
+access_task_type,task_type,project.model_project_task_type,portal.group_portal,1,0,0,0
+access_task_work,task_work,project.model_project_task_work,portal.group_portal,1,0,0,0
+access_project_category,project_category,project.model_project_category,portal.group_portal,1,0,0,0
diff --git a/addons/portal_project/security/portal_security.xml b/addons/portal_project/security/portal_security.xml
index b995c79bbbc..b9d37cec099 100644
--- a/addons/portal_project/security/portal_security.xml
+++ b/addons/portal_project/security/portal_security.xml
@@ -6,7 +6,7 @@
Portal Personal Task[('partner_id','child_of',user.partner_id.id)]
-
+
diff --git a/addons/portal_project_issue/security/ir.model.access.csv b/addons/portal_project_issue/security/ir.model.access.csv
index 5257f9b6d02..80a38366b51 100644
--- a/addons/portal_project_issue/security/ir.model.access.csv
+++ b/addons/portal_project_issue/security/ir.model.access.csv
@@ -1,3 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-access_issues,project_issue,project_issue.model_project_issue,portal.group_portal_member,1,0,0,0
-access_case_section,crm_case_section,crm.model_crm_case_section,portal.group_portal_member,1,0,0,0
+access_issues,project_issue,project_issue.model_project_issue,portal.group_portal,1,0,0,0
+access_case_section,crm_case_section,crm.model_crm_case_section,portal.group_portal,1,0,0,0
diff --git a/addons/portal_project_issue/security/portal_security.xml b/addons/portal_project_issue/security/portal_security.xml
index 4ef8da5e4b6..358b5e6a0ad 100644
--- a/addons/portal_project_issue/security/portal_security.xml
+++ b/addons/portal_project_issue/security/portal_security.xml
@@ -6,7 +6,7 @@
Portal Personal Issues[('partner_id','child_of',user.partner_id.id)]
-
+
diff --git a/addons/portal_sale/security/ir.model.access.csv b/addons/portal_sale/security/ir.model.access.csv
index 32266499af7..751c0b9baff 100644
--- a/addons/portal_sale/security/ir.model.access.csv
+++ b/addons/portal_sale/security/ir.model.access.csv
@@ -1,33 +1,33 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-access_sale_order,sale.order,sale.model_sale_order,portal.group_portal_member,1,0,0,0
-access_sale_order_line,sale.order.line,sale.model_sale_order_line,portal.group_portal_member,1,0,0,0
-access_stock_picking,stock.picking,stock.model_stock_picking,portal.group_portal_member,1,0,0,0
-access_stock_picking.out,stock.picking.out,stock.model_stock_picking_out,portal.group_portal_member,1,0,0,0
-access_stock_move,stock.move,stock.model_stock_move,portal.group_portal_member,1,0,0,0
-access_stock_warehouse_orderpoint,stock.warehouse.orderpoint,procurement.model_stock_warehouse_orderpoint,portal.group_portal_member,1,0,0,0
-access_account_invoice,account.invoice,account.model_account_invoice,portal.group_portal_member,1,0,0,0
-access_account_invoice_tax,account.invoice.tax,account.model_account_invoice_tax,portal.group_portal_member,1,0,0,0
-access_account_invoice_line,account.invoice.line,account.model_account_invoice_line,portal.group_portal_member,1,0,0,0
-access_account_journal,account.journal,account.model_account_journal,portal.group_portal_member,1,0,0,0
-access_account_voucher,account.voucher,account_voucher.model_account_voucher,portal.group_portal_member,1,0,0,0
-access_account_voucher_line,account.voucher.line,account_voucher.model_account_voucher_line,portal.group_portal_member,1,0,0,0
-access_account_move,account.move,account.model_account_move,portal.group_portal_member,1,0,0,0
-access_account_move_line,account.move.line,account.model_account_move_line,portal.group_portal_member,1,0,0,0
-access_account_move_reconcile,account.move.reconcile,account.model_account_move_reconcile,portal.group_portal_member,1,0,0,0
-access_account_fiscalyear,account.sequence.fiscalyear,account.model_account_sequence_fiscalyear,portal.group_portal_member,1,0,0,0
-access_sale_shop,sale.shop,sale.model_sale_shop,portal.group_portal_member,1,0,0,0
-access_product_list,product.pricelist,product.model_product_pricelist,portal.group_portal_member,1,0,0,0
-access_product,product.product,product.model_product_product,portal.group_portal_member,1,0,0,0
-access_res_partner,res.partner,base.model_res_partner,portal.group_portal_member,1,0,0,0
-access_product_uom,product.uom,product.model_product_uom,portal.group_portal_member,1,0,0,0
-access_account_tax,account.tax,account.model_account_tax,portal.group_portal_member,1,0,0,0
-access_mrp_property,mrp.property,procurement.model_mrp_property,portal.group_portal_member,1,0,0,0
-access_product_template,product.template,product.model_product_template,portal.group_portal_member,1,0,0,0
-access_stock_warehouse,stock.warehouse,stock.model_stock_warehouse,portal.group_portal_member,1,0,0,0
-access_stock_location,stock.location,stock.model_stock_location,portal.group_portal_member,1,0,0,0
-access_account_fiscalyear,account.fiscalyear,account.model_account_fiscalyear,portal.group_portal_member,1,0,0,0
-access_res_partner_category,res.partner.category,base.model_res_partner_category,portal.group_portal_member,1,0,0,0
-access_product_supplierinfo,product.supplierinfo,product.model_product_supplierinfo,portal.group_portal_member,1,0,0,0
-access_product_packaging,product.packaging,product.model_product_packaging,portal.group_portal_member,1,0,0,0
-access_account_period,account.period,account.model_account_period,portal.group_portal_member,1,0,0,0
-access_account_account,account.account,account.model_account_account,portal.group_portal_member,1,0,0,0
+access_sale_order,sale.order,sale.model_sale_order,portal.group_portal,1,0,0,0
+access_sale_order_line,sale.order.line,sale.model_sale_order_line,portal.group_portal,1,0,0,0
+access_stock_picking,stock.picking,stock.model_stock_picking,portal.group_portal,1,0,0,0
+access_stock_picking.out,stock.picking.out,stock.model_stock_picking_out,portal.group_portal,1,0,0,0
+access_stock_move,stock.move,stock.model_stock_move,portal.group_portal,1,0,0,0
+access_stock_warehouse_orderpoint,stock.warehouse.orderpoint,procurement.model_stock_warehouse_orderpoint,portal.group_portal,1,0,0,0
+access_account_invoice,account.invoice,account.model_account_invoice,portal.group_portal,1,0,0,0
+access_account_invoice_tax,account.invoice.tax,account.model_account_invoice_tax,portal.group_portal,1,0,0,0
+access_account_invoice_line,account.invoice.line,account.model_account_invoice_line,portal.group_portal,1,0,0,0
+access_account_journal,account.journal,account.model_account_journal,portal.group_portal,1,0,0,0
+access_account_voucher,account.voucher,account_voucher.model_account_voucher,portal.group_portal,1,0,0,0
+access_account_voucher_line,account.voucher.line,account_voucher.model_account_voucher_line,portal.group_portal,1,0,0,0
+access_account_move,account.move,account.model_account_move,portal.group_portal,1,0,0,0
+access_account_move_line,account.move.line,account.model_account_move_line,portal.group_portal,1,0,0,0
+access_account_move_reconcile,account.move.reconcile,account.model_account_move_reconcile,portal.group_portal,1,0,0,0
+access_account_fiscalyear,account.sequence.fiscalyear,account.model_account_sequence_fiscalyear,portal.group_portal,1,0,0,0
+access_sale_shop,sale.shop,sale.model_sale_shop,portal.group_portal,1,0,0,0
+access_product_list,product.pricelist,product.model_product_pricelist,portal.group_portal,1,0,0,0
+access_product,product.product,product.model_product_product,portal.group_portal,1,0,0,0
+access_res_partner,res.partner,base.model_res_partner,portal.group_portal,1,0,0,0
+access_product_uom,product.uom,product.model_product_uom,portal.group_portal,1,0,0,0
+access_account_tax,account.tax,account.model_account_tax,portal.group_portal,1,0,0,0
+access_mrp_property,mrp.property,procurement.model_mrp_property,portal.group_portal,1,0,0,0
+access_product_template,product.template,product.model_product_template,portal.group_portal,1,0,0,0
+access_stock_warehouse,stock.warehouse,stock.model_stock_warehouse,portal.group_portal,1,0,0,0
+access_stock_location,stock.location,stock.model_stock_location,portal.group_portal,1,0,0,0
+access_account_fiscalyear,account.fiscalyear,account.model_account_fiscalyear,portal.group_portal,1,0,0,0
+access_res_partner_category,res.partner.category,base.model_res_partner_category,portal.group_portal,1,0,0,0
+access_product_supplierinfo,product.supplierinfo,product.model_product_supplierinfo,portal.group_portal,1,0,0,0
+access_product_packaging,product.packaging,product.model_product_packaging,portal.group_portal,1,0,0,0
+access_account_period,account.period,account.model_account_period,portal.group_portal,1,0,0,0
+access_account_account,account.account,account.model_account_account,portal.group_portal,1,0,0,0
diff --git a/addons/portal_sale/security/portal_security.xml b/addons/portal_sale/security/portal_security.xml
index f69fd283db6..8028d5360c4 100644
--- a/addons/portal_sale/security/portal_security.xml
+++ b/addons/portal_sale/security/portal_security.xml
@@ -7,42 +7,42 @@
Portal Personal Quotations/Sales Orders[('partner_id','child_of',user.partner_id.id)]
-
+ Portal Personal Delivery Orders[('partner_id','child_of',[user.partner_id.id])]
-
+ Portal Personal Delivery Orders Out[('partner_id','child_of',[user.partner_id.id])]
-
+ Portal Personal Account Invoices[('partner_id','child_of',user.partner_id.id)]
-
+ Portal Personal Payments[('partner_id','child_of',user.partner_id.id)]
-
+ Portal Personal Contacts[('id','child_of',user.partner_id.id)]
-
+
From 941cb76283aa05bc7e255c2af68251bd39b7ca78 Mon Sep 17 00:00:00 2001
From: Raphael Collet
Date: Fri, 14 Sep 2012 16:46:33 +0200
Subject: [PATCH 237/408] [IMP] portal: replace model 'res.portal' by
'res.groups' where field 'is_portal' is True
bzr revid: rco@openerp.com-20120914144633-z3xpe7392egz3640
---
addons/portal/mail_mail.py | 2 +-
addons/portal/portal.py | 190 +--------------------
addons/portal/portal_data.xml | 8 -
addons/portal/portal_demo.xml | 2 +-
addons/portal/portal_view.xml | 71 ++------
addons/portal/security/portal_security.xml | 4 +-
addons/portal/tests/test_portal.py | 2 +-
addons/portal/wizard/portal_wizard.py | 14 +-
addons/portal/wizard/share_wizard.py | 8 +-
9 files changed, 35 insertions(+), 266 deletions(-)
diff --git a/addons/portal/mail_mail.py b/addons/portal/mail_mail.py
index 72c8469c042..5b149c1146a 100644
--- a/addons/portal/mail_mail.py
+++ b/addons/portal/mail_mail.py
@@ -43,7 +43,7 @@ class mail_mail_portal(osv.Model):
:param partner: browse_record of the specific recipient partner
"""
if partner:
- portal_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'portal', 'portal')
+ portal_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'portal', 'portal_group')
portal_id = portal_ref and portal_ref[1] or False
url = self._generate_signin_url(cr, uid, partner.id, portal_id, 1234, context=context)
body = tools.append_content_to_html(mail.body_html, url)
diff --git a/addons/portal/portal.py b/addons/portal/portal.py
index 3672d87cf30..13cde80f849 100644
--- a/addons/portal/portal.py
+++ b/addons/portal/portal.py
@@ -20,196 +20,14 @@
##############################################################################
from osv import osv, fields
-from tools.translate import _
-
class portal(osv.osv):
+ """ A portal is simply a group of users with the flag 'is_portal' set to True.
+ The flag 'is_portal' makes a user group usable as a portal.
"""
- A portal is a group of users with specific menu, widgets, and typically
- restricted access rights.
- """
- _name = 'res.portal'
- _description = 'Portal'
- _inherits = {'res.groups': 'group_id'}
-
+ _inherit = 'res.groups'
_columns = {
- 'group_id': fields.many2one('res.groups', required=True, ondelete='cascade',
- string='Group',
- help='The group corresponding to this portal'),
- 'url': fields.char('URL',
- help="The url where portal users can connect to the server"),
- 'home_action_id': fields.many2one('ir.actions.actions',
- string='Home Action',
- help="if set, replaces the standard home action (first screen after loggin) for the portal's users"),
- 'menu_action_id': fields.many2one('ir.actions.act_window', readonly=True,
- # ISSUE: 'ondelete' constraints do not seem effective on this field...
- string='Menu Action',
- help="If set, replaces the standard menu for the portal's users"),
- 'parent_menu_id': fields.many2one('ir.ui.menu', ondelete='restrict',
- string='Parent Menu',
- help='The menu action opens the submenus of this menu item'),
- 'widget_ids': fields.one2many('res.portal.widget', 'portal_id',
- string='Widgets',
- help='Widgets assigned to portal users'),
+ 'is_portal': fields.boolean('Portal', help="If checked, this group is usable as a portal."),
}
- def copy(self, cr, uid, id, values, context=None):
- """ override copy(): menu_action_id must be different """
- values['menu_action_id'] = None
- return super(portal, self).copy(cr, uid, id, values, context)
-
- def create(self, cr, uid, values, context=None):
- """ extend create() to assign the portal menu to users """
- if context is None:
- context = {}
-
- # create portal (admin should not be included)
- context['noadmin'] = True
- portal_id = super(portal, self).create(cr, uid, values, context)
-
- # assign menu action and widgets to users
- if values.get('users') or values.get('menu_action_id'):
- self._assign_menu(cr, uid, [portal_id], context)
- if values.get('users') or values.get('widget_ids'):
- self._assign_widgets(cr, uid, [portal_id], context)
-
- return portal_id
-
- def write(self, cr, uid, ids, values, context=None):
- """ extend write() to reflect changes on users """
- # first apply portal changes
- super(portal, self).write(cr, uid, ids, values, context)
-
- # assign menu action and widgets to users
- if values.get('users') or values.get('menu_action_id'):
- self._assign_menu(cr, uid, ids, context)
- if values.get('users') or values.get('widget_ids'):
- self._assign_widgets(cr, uid, ids, context)
-
- # if parent_menu_id has changed, apply the change on menu_action_id
- if 'parent_menu_id' in values:
- act_window_obj = self.pool.get('ir.actions.act_window')
- portals = self.browse(cr, uid, ids, context)
- action_ids = [p.menu_action_id.id for p in portals if p.menu_action_id]
- if action_ids:
- action_values = {'domain': [('parent_id', '=', values['parent_menu_id'])]}
- act_window_obj.write(cr, uid, action_ids, action_values, context)
-
- return True
-
- def _assign_menu(self, cr, uid, ids, context=None):
- """ assign portal_menu_settings to users of portals (ids) """
- user_obj = self.pool.get('res.users')
- for p in self.browse(cr, uid, ids, context):
- # user menu action = portal menu action if set in portal
- if p.menu_action_id:
- user_ids = [u.id for u in p.users if u.id != 1]
- user_values = {'menu_id': p.menu_action_id.id}
- user_obj.write(cr, uid, user_ids, user_values, context)
-
- def _assign_widgets(self, cr, uid, ids, context=None):
- """ assign portal widgets to users of portals (ids) """
- widget_user_obj = self.pool.get('res.widget.user')
- for p in self.browse(cr, uid, ids, context):
- for w in p.widget_ids:
- values = {'sequence': w.sequence, 'widget_id': w.widget_id.id}
- for u in p.users:
- if u.id == 1: continue
- values['user_id'] = u.id
- widget_user_obj.create(cr, uid, values, context)
-
- def _res_xml_id(self, cr, uid, module, xml_id):
- """ return the resource id associated to the given xml_id """
- data_obj = self.pool.get('ir.model.data')
- data_id = data_obj._get_id(cr, uid, module, xml_id)
- return data_obj.browse(cr, uid, data_id).res_id
-
-portal()
-
-
-
-class portal_override_menu(osv.osv):
- """
- Extend res.portal with a boolean field 'Override Users Menu', that
- triggers the creation or removal of menu_action_id
- """
- _name = 'res.portal'
- _inherit = 'res.portal'
-
- def _get_override_menu(self, cr, uid, ids, field_name, arg, context=None):
- assert field_name == 'override_menu'
- result = {}
- for p in self.browse(cr, uid, ids, context):
- result[p.id] = bool(p.menu_action_id)
- return result
-
- def _set_override_menu(self, cr, uid, id, field_name, field_value, arg, context=None):
- assert field_name == 'override_menu'
- if field_value:
- self.create_menu_action(cr, uid, id, context)
- else:
- self.write(cr, uid, [id], {'menu_action_id': False}, context)
-
- def create_menu_action(self, cr, uid, id, context=None):
- """ create, if necessary, a menu action that opens the menu items below
- parent_menu_id """
- p = self.browse(cr, uid, id, context)
- if not p.menu_action_id:
- actions_obj = self.pool.get('ir.actions.act_window')
- parent_id = p.parent_menu_id.id if p.parent_menu_id else False
- action_values = {
- 'name': _('%s Menu') % p.name,
- 'type': 'ir.actions.act_window',
- 'usage': 'menu',
- 'res_model': 'ir.ui.menu',
- 'view_type': 'tree',
- 'view_id': self._res_xml_id(cr, uid, 'base', 'view_menu'),
- 'domain': [('parent_id', '=', parent_id)],
- }
- action_id = actions_obj.create(cr, uid, action_values, context)
- self.write(cr, uid, [id], {'menu_action_id': action_id}, context)
-
- _columns = {
- 'override_menu': fields.function(
- _get_override_menu, fnct_inv=_set_override_menu,
- type='boolean', string='Override Menu Action of Users',
- help='Enable this option to override the Menu Action of portal users'),
- }
-
-portal_override_menu()
-
-
-
-class portal_widget(osv.osv):
- """
- Similar to res.widget.user (res_widget.py), but with a portal instead.
- New users in a portal are assigned the portal's widgets.
- """
- _name='res.portal.widget'
- _description = 'Portal Widgets'
- _order = 'sequence'
- _columns = {
- 'sequence': fields.integer('Sequence'),
- 'portal_id': fields.many2one('res.portal', select=1, ondelete='cascade',
- string='Portal'),
- 'widget_id': fields.many2one('res.widget', required=True, ondelete='cascade',
- string='Widget'),
- }
-
- def create(self, cr, uid, values, context=None):
- domain = [('portal_id', '=', values.get('portal_id')),
- ('widget_id', '=', values.get('widget_id'))]
- existing = self.search(cr, uid, domain, context=context)
- if existing:
- res = existing[0]
- else:
- res = super(portal_widget, self).create(cr, uid, values, context=context)
- return res
-
-portal_widget()
-
-
-
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/portal/portal_data.xml b/addons/portal/portal_data.xml
index 5edb4bed8c7..a980552a854 100644
--- a/addons/portal/portal_data.xml
+++ b/addons/portal/portal_data.xml
@@ -2,14 +2,6 @@
-
- Portal
-
-
-
-
-
-
Company's news
diff --git a/addons/portal/portal_demo.xml b/addons/portal/portal_demo.xml
index 1ace02f3d7d..f4ba8fe2192 100644
--- a/addons/portal/portal_demo.xml
+++ b/addons/portal/portal_demo.xml
@@ -13,7 +13,7 @@
-
+
diff --git a/addons/portal/portal_view.xml b/addons/portal/portal_view.xml
index 5241d7cf54f..abd013d719c 100644
--- a/addons/portal/portal_view.xml
+++ b/addons/portal/portal_view.xml
@@ -21,71 +21,30 @@
-
-
- Portal List
- res.portal
+
+
+ Group Search
+ res.groups
+
-
-
-
+
+
+
-
-
+
+ Portal Form
- res.portal
+ res.groups
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
- Portals
- res.portal
- form
- tree,form
-
- {'form_view_ref': 'portal.portal_form_view'}
-
-
- Click to create a new portal.
-
- A portal helps defining specific views and rules for a group of
- users (the portal group). A portal menu, widgets and specific
- groups may be assigned to the portal's users.
-
-
-
-
-
-
-
-
diff --git a/addons/portal/security/portal_security.xml b/addons/portal/security/portal_security.xml
index 0bf4cb2dcfc..3d5cf47b0be 100644
--- a/addons/portal/security/portal_security.xml
+++ b/addons/portal/security/portal_security.xml
@@ -6,7 +6,9 @@
PortalPortal members can access information through the portal menu. Also, they are chrooted in this specific menu.
-
+
+
+
diff --git a/addons/portal/tests/test_portal.py b/addons/portal/tests/test_portal.py
index 2c301228859..809bc131034 100644
--- a/addons/portal/tests/test_portal.py
+++ b/addons/portal/tests/test_portal.py
@@ -42,7 +42,7 @@ class test_portal(test_mail.TestMailMockups):
user_admin = self.res_users.browse(cr, uid, uid)
self.mail_invite = self.registry('mail.wizard.invite')
base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url', default='')
- portal_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'portal', 'portal')
+ portal_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'portal', 'portal_group')
portal_id = portal_ref and portal_ref[1] or False
# 0 - Admin
diff --git a/addons/portal/wizard/portal_wizard.py b/addons/portal/wizard/portal_wizard.py
index da9d9b4e18d..969f74b5bd8 100644
--- a/addons/portal/wizard/portal_wizard.py
+++ b/addons/portal/wizard/portal_wizard.py
@@ -78,7 +78,7 @@ class wizard(osv.osv_memory):
_columns = {
'partner_id': fields.many2one('res.partner', required=True, string="Partner"),
- 'portal_id': fields.many2one('res.portal', required=True,
+ 'portal_id': fields.many2one('res.groups', domain=[('is_portal', '=', True)], required=True,
string='Portal',
help="The portal in which new users must be added"),
'user_ids': fields.one2many('res.portal.wizard.user', 'wizard_id',
@@ -157,7 +157,7 @@ class wizard(osv.osv_memory):
for address in partner.child_ids:
_portal_user(address)
partner_user_ids = self._search_partner_user(cr, uid, partner.id, context=context)
- portal_users = [u.id for u in self.pool.get('res.portal').browse(cr, uid, portal_id, context=context).group_id.users]
+ portal_users = [u.id for u in self.pool.get('res.groups').browse(cr, uid, portal_id, context=context).users]
for user in res_user.browse(cr, uid, partner_user_ids, context=context):
email = user and user.email or False
has_portal_user = False
@@ -302,17 +302,17 @@ class wizard_user(osv.osv_memory):
return user_id
def link_portal_user(self, cr, uid, portal_id, user_id, context=None):
- res_portal = self.pool.get('res.portal')
- portal = res_portal.browse(cr, uid, portal_id, context=context)
- portal_user_ids = [u.id for u in portal.group_id.users]
+ res_groups = self.pool.get('res.groups')
+ portal = res_groups.browse(cr, uid, portal_id, context=context)
+ portal_user_ids = [u.id for u in portal.users]
if user_id not in portal_user_ids:
return portal.write({'users': [(4, user_id)]}, context=context)
if user_id in portal_user_ids:
return False
def unlink_portal_user(self, cr, uid, portal_id, user_id, context=None):
- res_portal = self.pool.get('res.portal')
- return res_portal.write(cr, uid, [portal_id], {'users': [(3, user_id)]}, context=context)
+ res_groups = self.pool.get('res.groups')
+ return res_groups.write(cr, uid, [portal_id], {'users': [(3, user_id)]}, context=context)
def unlink_user(self, cr, uid, user_id, context=None):
#TODO: search portal groups
diff --git a/addons/portal/wizard/share_wizard.py b/addons/portal/wizard/share_wizard.py
index e56e7517348..b1b6e980dec 100644
--- a/addons/portal/wizard/share_wizard.py
+++ b/addons/portal/wizard/share_wizard.py
@@ -119,16 +119,14 @@ class share_wizard_portal(osv.TransientModel):
# alter the rules of the groups so they can see the shared data
if wizard_data.group_ids:
# get the list of portals and the related groups to install their menus.
- Portals = self.pool.get('res.portal')
- all_portals = Portals.browse(cr, UID_ROOT, Portals.search(cr, UID_ROOT, [])) #no context!
- all_portal_group_ids = [p.group_id.id for p in all_portals]
+ res_groups = self.pool.get('res.groups')
+ all_portal_group_ids = res_groups.search(cr, UID_ROOT, [('is_portal', '=', True)])
# populate result lines with the users of each group and
# setup the menu for portal groups
for group in wizard_data.group_ids:
if group.id in all_portal_group_ids:
- portal = all_portals[all_portal_group_ids.index(group.id)]
- self._create_shared_data_menu(cr, uid, wizard_data, portal, context=context)
+ self._create_shared_data_menu(cr, uid, wizard_data, group.id, context=context)
for user in group.users:
new_line = {'user_id': user.id,
From 4cc9269e4ba4a171b2cffe16c612f8d9f42e8d1c Mon Sep 17 00:00:00 2001
From: niv-openerp
Date: Fri, 14 Sep 2012 17:31:33 +0200
Subject: [PATCH 238/408] wip
bzr revid: nicolas.vanhoren@openerp.com-20120914153133-dghxbx2k8k7o98bu
---
.../account/account_move_reconciliation.xml | 36 ++-----------------
.../src/js/account_move_reconciliation.js | 10 ++++++
2 files changed, 12 insertions(+), 34 deletions(-)
diff --git a/addons/account/account_move_reconciliation.xml b/addons/account/account_move_reconciliation.xml
index 1bf2bc7ecdf..b3cbb062f2c 100644
--- a/addons/account/account_move_reconciliation.xml
+++ b/addons/account/account_move_reconciliation.xml
@@ -1,38 +1,6 @@
-
-
- account.move.reconciliation.form
- account.move.reconciliation
- form
-
-
-
-
-
@@ -40,7 +8,7 @@
account.move.lineformaccount_reconciliation_list,form
-
+
@@ -49,7 +17,7 @@
account.move.lineformaccount_reconciliation_list,form
-
+
diff --git a/addons/account/static/src/js/account_move_reconciliation.js b/addons/account/static/src/js/account_move_reconciliation.js
index cde4e88773b..ab15242d593 100644
--- a/addons/account/static/src/js/account_move_reconciliation.js
+++ b/addons/account/static/src/js/account_move_reconciliation.js
@@ -15,6 +15,16 @@ openerp.account = function (instance) {
this.$el.prepend(QWeb.render("AccountReconciliation"));
return tmp;
},
+ do_search: function(domain, context, group_by) {
+ var sup = this._super;
+ var mod = new instance.web.Model(this.model, context, domain);
+ return mod.query("partner_id").group_by(["partner_id"]).pipe(function(result) {
+ var vals = _.chain(result).pluck("attributes").pluck("value")
+ .filter(function(el) {return !!el;}).value();
+ debugger;
+ return sup(new instance.web.CompoundDomain(domain, [["partner_id", "in", _.pluck(vals, 0)]]), context, group_by);
+ });
+ },
});
/*instance.web.views.add('form_clone', 'instance.account.extend_form_view');
From 87e8b0ea51af9f18763d6a4badcf4e8eca91651d Mon Sep 17 00:00:00 2001
From: "Atul Patel (OpenERP)"
Date: Mon, 17 Sep 2012 11:12:43 +0530
Subject: [PATCH 239/408] [IMP]: Improve description of sale and sale_stock
module. change tooltips for res_config file
bzr revid: atp@tinyerp.com-20120917054243-iko6uihhcy9b0ref
---
addons/sale/__openerp__.py | 11 ++-----
addons/sale/res_config.py | 3 +-
addons/sale_stock/__openerp__.py | 50 ++++++++++++++------------------
addons/sale_stock/sale_stock.py | 12 ++------
4 files changed, 29 insertions(+), 47 deletions(-)
diff --git a/addons/sale/__openerp__.py b/addons/sale/__openerp__.py
index f8ad10f9a93..1e6585618b5 100644
--- a/addons/sale/__openerp__.py
+++ b/addons/sale/__openerp__.py
@@ -29,23 +29,18 @@
Manage sales quotations and orders
==================================
-This application allows you to manage your sales goals in an effective and efficient manner by keeping track of all sales orders and history.
+This application allows you to make a sale order, validate it and encode payment without having to deal with anything related to warehouse management.
-It handles the full sales workflow:
+It handles the sales workflow :
* **Quotation** -> **Sales order** -> **Invoice**
Preferences
-----------
-* Shipping: Choice of delivery at once or partial delivery
* Invoicing: choose how invoices will be paid
-* Incoterms: International Commercial terms
-
-You can choose flexible invoicing methods:
+There is one invoicing methods:
* *On Demand*: Invoices are created manually from Sales Orders when needed
-* *On Delivery Order*: Invoices are generated from picking (delivery)
-* *Before Delivery*: A Draft invoice is created and must be paid before delivery
The Dashboard for the Sales Manager will include
diff --git a/addons/sale/res_config.py b/addons/sale/res_config.py
index f0f99883c98..4cfb1e7eb06 100644
--- a/addons/sale/res_config.py
+++ b/addons/sale/res_config.py
@@ -70,7 +70,8 @@ class sale_configuration(osv.osv_memory):
This installs the module analytic_user_function."""),
'module_project': fields.boolean("Project"),
'module_sale_stock': fields.boolean("Sale and Warehouse Management",
- help="""Allows you to Make Quotation, Sale Order using different Order policy and Manage Related Stock """),
+ help="""Allows you to Make Quotation, Sale Order using different Order policy and Manage Related Stock.
+ This installs the module sale_stock."""),
}
def default_get(self, cr, uid, fields, context=None):
diff --git a/addons/sale_stock/__openerp__.py b/addons/sale_stock/__openerp__.py
index 37671cdb7cb..1bbafae7952 100644
--- a/addons/sale_stock/__openerp__.py
+++ b/addons/sale_stock/__openerp__.py
@@ -25,41 +25,33 @@
'category': 'Hidden',
'summary': 'Quotation, Sale Orders, Delivery & Invoicing Control',
'description': """
-
-This Module manage quotations and sales orders.
-===========================================================================
+Manage sales quotations and orders
+==================================
-Workflow with validation steps:
--------------------------------
- * **Quotation** -> **Sales order** -> **Invoice**
+This application allows you to manage your sales goals in an effective and efficient manner by keeping track of all sales orders and history.
-Create Invoice:
----------------
- * Invoice on Demand
- * Invoice on Delivery Order
- * Invoice Before Delivery
+It handles the full sales workflow:
-Partners preferences:
----------------------
- * Incoterm
- * Shipping
- * Invoicing
+* **Quotation** -> **Sales order** -> **Invoice**
-Products stocks and prices:
----------------------------
+Preferences
+-----------
+* Shipping: Choice of delivery at once or partial delivery
+* Invoicing: choose how invoices will be paid
+* Incoterms: International Commercial terms
-Delivery method:
------------------
- * The Poste
- * Free Delivery Charges
- * Normal Delivery Charges
- * Based on the Delivery Order(if not Add to sale order)
+You can choose flexible invoicing methods:
-Dashboard for Sales Manager that includes:
-------------------------------------------
- * My Quotations
- * Monthly Turnover (Graph)
- """,
+* *On Demand*: Invoices are created manually from Sales Orders when needed
+* *On Delivery Order*: Invoices are generated from picking (delivery)
+* *Before Delivery*: A Draft invoice is created and must be paid before delivery
+
+
+The Dashboard for the Sales Manager will include
+------------------------------------------------
+* My Quotations
+* Monthly Turnover (Graph)
+""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'images': [],
diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py
index 92df2f3c8fb..29adf643d62 100644
--- a/addons/sale_stock/sale_stock.py
+++ b/addons/sale_stock/sale_stock.py
@@ -212,20 +212,14 @@ class sale_order(osv.osv):
def action_wait(self, cr, uid, ids, context=None):
+ res = super(sale_order, self).action_wait(cr, uid, ids, context=context)
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.'))
noprod = self.test_no_product(cr, uid, o, context)
if noprod and o.order_policy=='picking':
self.write(cr, uid, [o.id], {'order_policy': 'manual'}, context=context)
- if (o.order_policy == 'manual') or noprod:
- self.write(cr, uid, [o.id], {'state': 'manual', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)})
- else:
+ if not (o.order_policy == 'manual') or not noprod:
self.write(cr, uid, [o.id], {'state': 'progress', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)})
- self.pool.get('sale.order.line').button_confirm(cr, uid, [x.id for x in o.order_line])
- self.confirm_send_note(cr, uid, ids, context)
- return True
-
+ return res
def action_invoice_create(self, cr, uid, ids, grouped=False, states=['confirmed', 'done', 'exception'], date_inv = False, context=None):
picking_obj = self.pool.get('stock.picking')
From 51ee2bf5ea6258dd05dbec24e76a9150502b0e34 Mon Sep 17 00:00:00 2001
From: "Vidhin Mehta (OpenERP)"
Date: Mon, 17 Sep 2012 11:23:26 +0530
Subject: [PATCH 240/408] [IMP]kanban view fix vertical group text possition.
bzr revid: vme@tinyerp.com-20120917055326-p7egwibhy2skyowm
---
addons/web_kanban/static/src/css/kanban.css | 2 +-
addons/web_kanban/static/src/css/kanban.sass | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/web_kanban/static/src/css/kanban.css b/addons/web_kanban/static/src/css/kanban.css
index 48cf725ead3..96d8e021347 100644
--- a/addons/web_kanban/static/src/css/kanban.css
+++ b/addons/web_kanban/static/src/css/kanban.css
@@ -135,7 +135,7 @@
white-space: nowrap;
display: none;
position: relative;
- top: 5px;
+ top: 25px;
}
.openerp .oe_kanban_view .oe_kanban_add, .openerp .oe_kanban_view .oe_kanban_header .oe_dropdown_toggle {
margin-left: 4px;
diff --git a/addons/web_kanban/static/src/css/kanban.sass b/addons/web_kanban/static/src/css/kanban.sass
index 95a63dbd1a2..a59c331bd1a 100644
--- a/addons/web_kanban/static/src/css/kanban.sass
+++ b/addons/web_kanban/static/src/css/kanban.sass
@@ -146,7 +146,7 @@
white-space: nowrap
display: none
position: relative
- top: 5px
+ top: 25px
// }}}
// KanbanQuickCreate {{{
.oe_kanban_add, .oe_kanban_header .oe_dropdown_toggle
From a6e77b12e2aa5d738056ec50a90d859926b37ce7 Mon Sep 17 00:00:00 2001
From: Amit Patel
Date: Mon, 17 Sep 2012 11:43:16 +0530
Subject: [PATCH 241/408] [IMP]:hr_expense:add accountant group for journal.
bzr revid: apa@tinyerp.com-20120917061316-bnjex2lyoplo3jom
---
addons/hr_expense/hr_expense_view.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/hr_expense/hr_expense_view.xml b/addons/hr_expense/hr_expense_view.xml
index 4219899e4c5..909e3102699 100644
--- a/addons/hr_expense/hr_expense_view.xml
+++ b/addons/hr_expense/hr_expense_view.xml
@@ -131,7 +131,7 @@
-
+
From eef634b3dc0616bc3fba6f980f022e10afe32984 Mon Sep 17 00:00:00 2001
From: "Atul Patel (OpenERP)"
Date: Mon, 17 Sep 2012 11:51:00 +0530
Subject: [PATCH 242/408] [IMP]: Improve sale stock action_wait method
bzr revid: atp@tinyerp.com-20120917062100-pb6msmh01t4kirca
---
addons/sale/sale.py | 2 ++
addons/sale_stock/sale_stock.py | 2 --
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index 08fbeb87f02..1a17a389a9b 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -594,6 +594,8 @@ class sale_order(osv.osv):
noprod = self.test_no_product(cr, uid, o, context)
if (o.order_policy == 'manual') or noprod:
self.write(cr, uid, [o.id], {'state': 'manual', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)})
+ else:
+ self.write(cr, uid, [o.id], {'state': 'progress', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)})
self.pool.get('sale.order.line').button_confirm(cr, uid, [x.id for x in o.order_line])
self.confirm_send_note(cr, uid, ids, context)
return True
diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py
index 29adf643d62..bd81f2b1902 100644
--- a/addons/sale_stock/sale_stock.py
+++ b/addons/sale_stock/sale_stock.py
@@ -217,8 +217,6 @@ class sale_order(osv.osv):
noprod = self.test_no_product(cr, uid, o, context)
if noprod and o.order_policy=='picking':
self.write(cr, uid, [o.id], {'order_policy': 'manual'}, context=context)
- if not (o.order_policy == 'manual') or not noprod:
- self.write(cr, uid, [o.id], {'state': 'progress', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)})
return res
def action_invoice_create(self, cr, uid, ids, grouped=False, states=['confirmed', 'done', 'exception'], date_inv = False, context=None):
From 4a14de9e0b2fb5a6d2fd9f10f6ea3dc48dbbc0d0 Mon Sep 17 00:00:00 2001
From: Amit Patel
Date: Mon, 17 Sep 2012 11:57:03 +0530
Subject: [PATCH 243/408] [IMP]:hr fix
bzr revid: apa@tinyerp.com-20120917062703-vi4geb7l1q9n40zc
---
addons/hr_holidays/hr_holidays_view.xml | 1 +
1 file changed, 1 insertion(+)
diff --git a/addons/hr_holidays/hr_holidays_view.xml b/addons/hr_holidays/hr_holidays_view.xml
index 8bd00d58832..084a8cc7412 100644
--- a/addons/hr_holidays/hr_holidays_view.xml
+++ b/addons/hr_holidays/hr_holidays_view.xml
@@ -483,6 +483,7 @@
hr.employee.leave.treehr.employee
+ 20
From 924b15f9747c81fd4381746a4bf12c60516e8f79 Mon Sep 17 00:00:00 2001
From: "Atul Patel (OpenERP)"
Date: Mon, 17 Sep 2012 12:44:59 +0530
Subject: [PATCH 244/408] [FIX]: Fix res configuration problem.
bzr revid: atp@tinyerp.com-20120917071459-tk7yropfczkfws22
---
addons/sale_stock/res_config.py | 2 +-
addons/sale_stock/security/sale_stock_security.xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/sale_stock/res_config.py b/addons/sale_stock/res_config.py
index 796a4cc20c5..36e1dc7ed21 100644
--- a/addons/sale_stock/res_config.py
+++ b/addons/sale_stock/res_config.py
@@ -30,7 +30,7 @@ class sale_configuration(osv.osv_memory):
implied_group='sale.group_invoice_so_lines',
help="To allow your salesman to make invoices for sale order lines using the menu 'Lines to Invoice'."),
'group_invoice_deli_orders': fields.boolean('Generate invoices after and based on delivery orders',
- implied_group='sale.group_invoice_deli_orders',
+ implied_group='sale_stock.group_invoice_deli_orders',
help="To allow your salesman to make invoices for Delivery Orders using the menu 'Deliveries to Invoice'."),
'task_work': fields.boolean("Prepare invoices based on task's activities",
help="""Lets you transfer the entries under tasks defined for Project Management to
diff --git a/addons/sale_stock/security/sale_stock_security.xml b/addons/sale_stock/security/sale_stock_security.xml
index ac8bfef9864..7f93084d43d 100644
--- a/addons/sale_stock/security/sale_stock_security.xml
+++ b/addons/sale_stock/security/sale_stock_security.xml
@@ -5,7 +5,7 @@
Enable Invoicing Delivery orders
-
+
From 3fa4a257fc6c23bc282a87871994303d57f071a0 Mon Sep 17 00:00:00 2001
From: Amit Patel
Date: Mon, 17 Sep 2012 12:57:12 +0530
Subject: [PATCH 245/408] [IMP]:improved view priority
bzr revid: apa@tinyerp.com-20120917072712-7sn4h0rf9boiqint
---
addons/hr_holidays/hr_holidays_view.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/hr_holidays/hr_holidays_view.xml b/addons/hr_holidays/hr_holidays_view.xml
index 084a8cc7412..76a7de47624 100644
--- a/addons/hr_holidays/hr_holidays_view.xml
+++ b/addons/hr_holidays/hr_holidays_view.xml
@@ -483,7 +483,7 @@
hr.employee.leave.treehr.employee
- 20
+
From 8cdd46aeec9ebbd23f82e946d7fe68ffa92a9847 Mon Sep 17 00:00:00 2001
From: Raphael Collet
Date: Mon, 17 Sep 2012 09:54:22 +0200
Subject: [PATCH 246/408] [FIX] portal: load missing file
security/portal_security.xml, and remove access rights about suppressed
models
bzr revid: rco@openerp.com-20120917075422-9ov3vd57phdes6yj
---
addons/portal/__openerp__.py | 1 +
addons/portal/security/ir.model.access.csv | 2 --
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/addons/portal/__openerp__.py b/addons/portal/__openerp__.py
index f5e3c9ff452..d7356fc9ce5 100644
--- a/addons/portal/__openerp__.py
+++ b/addons/portal/__openerp__.py
@@ -44,6 +44,7 @@ very handy when used in combination with the module 'share'.
""",
'website': 'http://www.openerp.com',
'data': [
+ 'security/portal_security.xml',
'security/ir.model.access.csv',
'portal_data.xml',
'portal_view.xml',
diff --git a/addons/portal/security/ir.model.access.csv b/addons/portal/security/ir.model.access.csv
index 60687e8a0cc..2d7a17e0016 100644
--- a/addons/portal/security/ir.model.access.csv
+++ b/addons/portal/security/ir.model.access.csv
@@ -1,6 +1,4 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-access_all,access.portal.all,model_res_portal,,1,0,0,0
-access_widget_all,access.portal.widget.all,model_res_portal_widget,,1,0,0,0
access_mail_message,mail.message,mail.model_mail_message,group_portal,1,0,1,1
access_mail_message_all,mail.message.all,mail.model_mail_message,group_portal,1,0,0,0
access_mail_thread,mail.thread,mail.model_mail_thread,group_portal,1,0,0,0
From 16772e8f430a8de14855ac68bcb5fc3ed0c5405a Mon Sep 17 00:00:00 2001
From: "Harry (OpenERP)"
Date: Mon, 17 Sep 2012 13:36:10 +0530
Subject: [PATCH 247/408] [FIX] purchase: workflow, invoice should not end
without invoiced and menu, purchase order lines should be display if does not
have link with product for TO Invoice
bzr revid: hmo@tinyerp.com-20120917080610-gczz23anlt4kcazp
---
addons/purchase/purchase_view.xml | 2 +-
addons/purchase/purchase_workflow.xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml
index 8f755d77a54..aa0f4233a42 100644
--- a/addons/purchase/purchase_view.xml
+++ b/addons/purchase/purchase_view.xml
@@ -519,7 +519,7 @@
On Purchase Order Linesir.actions.act_windowpurchase.order.line
- [('order_id.invoice_method','<>','picking'), ('state','in',('confirmed','done')), ('invoiced', '=', False)]
+ ['|', ('product_id','=',False),('order_id.invoice_method','<>','picking'),('state','in',('confirmed','done')), ('invoiced', '=', False)]formtree,form
diff --git a/addons/purchase/purchase_workflow.xml b/addons/purchase/purchase_workflow.xml
index 00fb5517568..212ce304e07 100644
--- a/addons/purchase/purchase_workflow.xml
+++ b/addons/purchase/purchase_workflow.xml
@@ -145,7 +145,7 @@
- invoice_method<>'order'
+ invoice_method<>'order' and invoiced
From 230ed4a0614f2f7aa61b5652c31cd80ae3ea7f21 Mon Sep 17 00:00:00 2001
From: niv-openerp
Date: Mon, 17 Sep 2012 10:23:04 +0200
Subject: [PATCH 248/408] fixed bug
bzr revid: nicolas.vanhoren@openerp.com-20120917082304-uufuuwa8gwtg39y3
---
addons/account/static/src/js/account_move_reconciliation.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/addons/account/static/src/js/account_move_reconciliation.js b/addons/account/static/src/js/account_move_reconciliation.js
index ab15242d593..ceda8417d75 100644
--- a/addons/account/static/src/js/account_move_reconciliation.js
+++ b/addons/account/static/src/js/account_move_reconciliation.js
@@ -16,12 +16,11 @@ openerp.account = function (instance) {
return tmp;
},
do_search: function(domain, context, group_by) {
- var sup = this._super;
+ var sup = _.bind(this._super, this);
var mod = new instance.web.Model(this.model, context, domain);
return mod.query("partner_id").group_by(["partner_id"]).pipe(function(result) {
var vals = _.chain(result).pluck("attributes").pluck("value")
.filter(function(el) {return !!el;}).value();
- debugger;
return sup(new instance.web.CompoundDomain(domain, [["partner_id", "in", _.pluck(vals, 0)]]), context, group_by);
});
},
From 7d93e8077db3c978a6c7e92db08a3716ae9c85a3 Mon Sep 17 00:00:00 2001
From: Raphael Collet
Date: Mon, 17 Sep 2012 10:23:36 +0200
Subject: [PATCH 249/408] [FIX] share: add inheritance on groups search view
bzr revid: rco@openerp.com-20120917082336-87tau8ef2qiu5v3p
---
addons/share/res_users_view.xml | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/addons/share/res_users_view.xml b/addons/share/res_users_view.xml
index 9a657ffdbb6..608c2ac3b92 100644
--- a/addons/share/res_users_view.xml
+++ b/addons/share/res_users_view.xml
@@ -25,13 +25,11 @@
res.groups.search.shareres.groups
-
+
-
-
-
+
-
+
From 8bca30ec6f9dcdb62333cffd09ab1471bc9eb5ac Mon Sep 17 00:00:00 2001
From: niv-openerp
Date: Mon, 17 Sep 2012 10:41:30 +0200
Subject: [PATCH 250/408] wip
bzr revid: nicolas.vanhoren@openerp.com-20120917084130-c3x2ryabewwksy5h
---
.../static/src/js/account_move_reconciliation.js | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/addons/account/static/src/js/account_move_reconciliation.js b/addons/account/static/src/js/account_move_reconciliation.js
index ceda8417d75..9d61152d6a6 100644
--- a/addons/account/static/src/js/account_move_reconciliation.js
+++ b/addons/account/static/src/js/account_move_reconciliation.js
@@ -16,14 +16,24 @@ openerp.account = function (instance) {
return tmp;
},
do_search: function(domain, context, group_by) {
- var sup = _.bind(this._super, this);
+ var self = this;
+ this.last_domain = domain;
+ this.last_context = context;
+ this.last_group_by = group_by;
+ this.old_search = _.bind(this._super, this);
var mod = new instance.web.Model(this.model, context, domain);
return mod.query("partner_id").group_by(["partner_id"]).pipe(function(result) {
- var vals = _.chain(result).pluck("attributes").pluck("value")
+ self.partners = _.chain(result).pluck("attributes").pluck("value")
.filter(function(el) {return !!el;}).value();
- return sup(new instance.web.CompoundDomain(domain, [["partner_id", "in", _.pluck(vals, 0)]]), context, group_by);
+ self.current_partner = self.partners.length == 0 ? null : 0;
+ return self.search_by_partner(self.current_partner);
+
});
},
+ search_by_partner: function(partner) {
+ return this.old_search(new instance.web.CompoundDomain(this.last_domain, [["partner_id", "in", partner === null ? [] : [this.partners[partner][0]] ]]),
+ this.last_context, this.last_group_by);
+ }
});
/*instance.web.views.add('form_clone', 'instance.account.extend_form_view');
From 20820fd8c5060828e40413c27ca65e7a89f7df42 Mon Sep 17 00:00:00 2001
From: "Harry (OpenERP)"
Date: Mon, 17 Sep 2012 14:15:34 +0530
Subject: [PATCH 251/408] [FIX] purchase: if user does not belong to UOM group,
should not display warning regarding UOM category mismatch.
bzr revid: hmo@tinyerp.com-20120917084534-tdr8e6ygjrywv6eg
---
addons/purchase/purchase.py | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 42f8b849fda..0c8c327c2f7 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -867,6 +867,12 @@ class purchase_order_line(osv.osv):
supplier_delay = int(supplier_info.delay) if supplier_info else 0
return datetime.strptime(date_order_str, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(days=supplier_delay)
+ def _check_product_uom_group(self, cr, uid, context=None):
+ group_uom = self.pool.get('ir.model.data').get_object(cr, uid, 'product', 'group_uom')
+ res = [user for user in group_uom.users if user.id == uid]
+ return len(res) and True or False
+
+
def onchange_product_id(self, cr, uid, ids, pricelist_id, product_id, qty, uom_id,
partner_id, date_order=False, fiscal_position_id=False, date_planned=False,
name=False, price_unit=False, context=None):
@@ -912,7 +918,8 @@ class purchase_order_line(osv.osv):
uom_id = product_uom_po_id
if product.uom_id.category_id.id != product_uom.browse(cr, uid, uom_id, context=context).category_id.id:
- res['warning'] = {'title': _('Warning!'), 'message': _('Selected Unit of Measure does not belong to the same category as the product Unit of Measure.')}
+ if self._check_product_uom_group(cr, uid, context=context):
+ res['warning'] = {'title': _('Warning!'), 'message': _('Selected Unit of Measure does not belong to the same category as the product Unit of Measure.')}
uom_id = product_uom_po_id
res['value'].update({'product_uom': uom_id})
From 48c3104836f5dccf0e36ac8e22ce3c2c30319b73 Mon Sep 17 00:00:00 2001
From: niv-openerp
Date: Mon, 17 Sep 2012 11:55:18 +0200
Subject: [PATCH 252/408] wip
bzr revid: nicolas.vanhoren@openerp.com-20120917095518-fco1enwa3yl7mo2b
---
.../static/src/js/account_move_reconciliation.js | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/addons/account/static/src/js/account_move_reconciliation.js b/addons/account/static/src/js/account_move_reconciliation.js
index 9d61152d6a6..9e4b9fd30dd 100644
--- a/addons/account/static/src/js/account_move_reconciliation.js
+++ b/addons/account/static/src/js/account_move_reconciliation.js
@@ -9,10 +9,11 @@ openerp.account = function (instance) {
instance.web.account.ReconciliationListView = instance.web.ListView.extend({
init: function() {
this._super.apply(this, arguments);
+ this.current_partner = null;
},
on_loaded: function() {
var tmp = this._super.apply(this, arguments);
- this.$el.prepend(QWeb.render("AccountReconciliation"));
+ this.$el.prepend(QWeb.render("AccountReconciliation", {widget: self}));
return tmp;
},
do_search: function(domain, context, group_by) {
@@ -26,14 +27,13 @@ openerp.account = function (instance) {
self.partners = _.chain(result).pluck("attributes").pluck("value")
.filter(function(el) {return !!el;}).value();
self.current_partner = self.partners.length == 0 ? null : 0;
- return self.search_by_partner(self.current_partner);
-
+ self.search_by_partner();
});
},
- search_by_partner: function(partner) {
- return this.old_search(new instance.web.CompoundDomain(this.last_domain, [["partner_id", "in", partner === null ? [] : [this.partners[partner][0]] ]]),
- this.last_context, this.last_group_by);
- }
+ search_by_partner: function() {
+ return this.old_search(new instance.web.CompoundDomain(this.last_domain, [["partner_id", "in", this.current_partner === null ? [] :
+ [this.partners[this.current_partner][0]] ]]), this.last_context, this.last_group_by);
+ },
});
/*instance.web.views.add('form_clone', 'instance.account.extend_form_view');
From c353c80621ba2190a67044491717dde0c747b66f Mon Sep 17 00:00:00 2001
From: "Randhir Mayatra (OpenERP)"
Date: Mon, 17 Sep 2012 15:31:52 +0530
Subject: [PATCH 253/408] [IMP] improve the purchase view
bzr revid: rma@tinyerp.com-20120917100152-miaqma5m5tw6n8bl
---
addons/purchase/purchase_view.xml | 12 +++++-------
addons/purchase/res_config.py | 13 ++++++++-----
addons/purchase/res_config_view.xml | 4 ++++
3 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml
index 8f755d77a54..f8d6dca86a6 100644
--- a/addons/purchase/purchase_view.xml
+++ b/addons/purchase/purchase_view.xml
@@ -14,7 +14,9 @@
-
+
@@ -22,10 +24,6 @@
-
-
@@ -349,7 +347,7 @@
ir.actions.act_windowpurchase.order{'search_default_draft': 1}
- [('state','in',('draft','sent','confirmed'))]
+ [('state','in',('draft','sent'))]tree,form,graph,calendar
@@ -375,7 +373,7 @@
purchase.ordertree,form,graph,calendar{}
- [('state','not in',('draft','sent','confirmed'))]
+ [('state','not in',('draft','sent'))]
diff --git a/addons/purchase/res_config.py b/addons/purchase/res_config.py
index bf7512a8666..19b059d4d5b 100644
--- a/addons/purchase/res_config.py
+++ b/addons/purchase/res_config.py
@@ -46,10 +46,6 @@ class purchase_config_settings(osv.osv_memory):
'group_purchase_delivery_address': fields.boolean("Allow a different address for incoming products and invoicings",
implied_group='purchase.group_delivery_invoice_address',
help="Allows you to specify different delivery and invoice addresses on a purchase order."),
- 'module_purchase_analytic_plans': fields.boolean('Allow using multiple analytic accounts on the same order',
- help ="""Allows the user to maintain several analysis plans. These let you split
- lines on a purchase order between several accounts and analytic plans.
- This installs the module purchase_analytic_plans."""),
'module_warning': fields.boolean("Alerts by products or supplier",
help="""Allow to configure warnings on products and trigger them when a user wants to purchase a given product or a given supplier.
Example: Product: this product is deprecated, do not purchase more than 5.
@@ -62,6 +58,12 @@ class purchase_config_settings(osv.osv_memory):
help="""Purchase Requisitions are used when you want to request quotations from several suppliers for a given set of products.
You can configure per product if you directly do a Request for Quotation
to one supplier or if you want a purchase requisition to negotiate with several suppliers."""),
+ 'module_purchase_analytic_plans': fields.boolean('Use multiple analytic accounts on purchase orders',
+ help ="""Allows the user to maintain several analysis plans. These let you split lines on a purchase order between several accounts and analytic plans.
+ This installs the module purchase_analytic_plans."""),
+ 'group_analytic_account_for_purchases': fields.boolean('Analytic accounting for purchases',
+ implied_group='purchase.group_analytic_accounting',
+ help="Allows you to specify an analytic account on purchase orders."),
}
_defaults = {
@@ -75,7 +77,8 @@ class account_config_settings(osv.osv_memory):
_inherit = 'account.config.settings'
_columns = {
'module_purchase_analytic_plans': fields.boolean('Use multiple analytic accounts on orders',
- help="""This allows install module purchase_analytic_plans."""),
+ help ="""Allows the user to maintain several analysis plans. These let you split lines on a purchase order between several accounts and analytic plans.
+ This installs the module purchase_analytic_plans."""),
'group_analytic_account_for_purchases': fields.boolean('Analytic accounting for purchases',
implied_group='purchase.group_analytic_accounting',
help="Allows you to specify an analytic account on purchase orders."),
diff --git a/addons/purchase/res_config_view.xml b/addons/purchase/res_config_view.xml
index 6453752a638..f659d7b437f 100644
--- a/addons/purchase/res_config_view.xml
+++ b/addons/purchase/res_config_view.xml
@@ -74,6 +74,10 @@
-
-
-
+
Date: Mon, 17 Sep 2012 17:12:18 +0200
Subject: [PATCH 265/408] removed more stuff
bzr revid: nicolas.vanhoren@openerp.com-20120917151218-4k5c6pnjfxic2v2o
---
addons/account/account_move_reconciliation.py | 138 ------------------
.../account/account_move_reconciliation.xml | 66 ---------
.../account_move_reconciliation.py | 61 --------
.../account_move_reconciliation.xml | 17 ---
4 files changed, 282 deletions(-)
delete mode 100644 addons/account/account_move_reconciliation.py
delete mode 100644 addons/account/account_move_reconciliation.xml
delete mode 100644 addons/account_followup/account_move_reconciliation.py
delete mode 100644 addons/account_followup/account_move_reconciliation.xml
diff --git a/addons/account/account_move_reconciliation.py b/addons/account/account_move_reconciliation.py
deleted file mode 100644
index b89dbacf623..00000000000
--- a/addons/account/account_move_reconciliation.py
+++ /dev/null
@@ -1,138 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 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 .
-#
-##############################################################################
-import time
-
-import tools
-from osv import fields,osv
-
-class account_move_line(osv.osv):
- _inherit = "account.move.line"
-
- def get_unreconcile_entry(self, cr, uid, ids, context=None):
- return self.search(cr, uid, [('id', 'in', ids), ('reconcile_id', '=', False)], context=context)
-
-account_move_line();
-
-
-class account_move_reconciliation(osv.osv):
- _name = "account.move.reconciliation"
- _description = "partner info related account move line"
- _auto = False
- _order = 'last_reconciliation_date'
-
- def search(self, cr, uid, args, offset=0, limit=None, order=None,
- context=None, count=False):
- if context is None:
- context = {}
- account_type = context.get('account_type', False)
- if account_type:
- args += [('type','=', account_type)]
- return super(account_move_reconciliation, self).search(cr, uid, args, offset, limit,
- order, context=context, count=count)
-
-
- def _get_to_reconcile_partners(self, cr, uid, context=None):
- if context is None:
- context = {}
- ctx = dict(context)
- ctx['next_partner_only'] = False
- move_line_obj = self.pool.get("account.move.line")
- to_reconcile_ids = move_line_obj.search(cr, uid, [
- ('reconcile_id','=',False),
- ('account_id.reconcile','=',True),
- ('state','!=', 'draft'),
- ('partner_id','!=', False),
- '|', ('partner_id.last_reconciliation_date', '=', False),('partner_id.last_reconciliation_date','<',time.strftime('%Y-%m-%d 00:00:00')),
- '|', ('debit', '>' ,0), ('credit', '>' ,0)
- ],
- context=ctx)
- partner_ids = []
- for move_line in move_line_obj.browse(cr, uid, to_reconcile_ids, context=ctx):
- partner = move_line.partner_id
- if move_line.date > partner.last_reconciliation_date and partner.id not in partner_ids:
- partner_ids.append(partner.id)
- return len(partner_ids)
-
- def _get_today_reconciled_partners(self, cr, uid, context=None):
- if context is None:
- context = {}
- account_type = context.get("account_type", False)
- supplier = False
- customer = False
- if account_type == 'payable':
- supplier = True
- else:
- customer = True
- today_reconciled_ids = self.pool.get('res.partner').search(cr, uid, [
- ('last_reconciliation_date','>=',time.strftime('%Y-%m-%d 00:00:00')),
- ('last_reconciliation_date','<=',time.strftime('%Y-%m-%d 23:59:59')),
- '|', ('supplier','=',supplier), ('customer','=',customer)
- ], context=context)
- return today_reconciled_ids and len(today_reconciled_ids) or 0
-
- def _rec_progress(self, cr, uid, ids, prop, unknow_none, context=None):
- res = {}
- to_reconcile = self._get_to_reconcile_partners(cr, uid, context=context)
- today_reconciled = self._get_today_reconciled_partners(cr, uid, context=context)
- if to_reconcile < 0:
- reconciliation_progress = 100
- else:
- reconciliation_progress = (100 / (float( to_reconcile + today_reconciled) or 1.0)) * today_reconciled
- for id in ids:
- res[id] = reconciliation_progress
- return res
-
-
- def skip_partner(self, cr, uid, ids, context):
- self.pool.get('res.partner').write(cr, uid, ids ,{'last_reconciliation_date':time.strftime("%Y-%m-%d")}, context)
-
- _columns = {
- 'partner_id':fields.many2one('res.partner', 'Partner'),
- 'last_reconciliation_date':fields.related('partner_id', 'last_reconciliation_date' ,type='datetime', relation='res.partner', string='Last Reconciliation'),
- 'latest_date' :fields.date('Latest Entry'),
- 'type': fields.char('Type', size=156),
- 'supplier': fields.related('partner_id', 'supplier' ,type='boolean', string='Supplier'),
- 'customer': fields.related('partner_id', 'customer' ,type='boolean', string='Customer'),
- 'reconciliation_progress': fields.function(_rec_progress, string='Progress (%)', type='float'),
- }
-
- def init(self, cr):
- tools.drop_view_if_exists(cr, 'account_move_reconciliation')
- cr.execute("""
- CREATE or REPLACE VIEW account_move_reconciliation as (
- SELECT move_line.partner_id AS id, a.type AS type, move_line.partner_id AS partner_id,
- SUM(move_line.debit) AS debit,
- SUM(move_line.credit) AS credit,
- MAX(move_line.date) AS latest_date,
- MIN(partner.last_reconciliation_date) AS last_reconciliation_date
- FROM account_move_line move_line
- LEFT JOIN account_account a ON (a.id = move_line.account_id)
- LEFT JOIN res_partner partner ON (move_line.partner_id = partner.id)
- WHERE a.reconcile IS TRUE
- AND move_line.reconcile_id IS NULL
- AND (partner.last_reconciliation_date IS NULL OR move_line.date > partner.last_reconciliation_date)
- AND move_line.state <> 'draft'
- GROUP BY move_line.partner_id, a.type
- )
- """)
-account_move_reconciliation()
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/account/account_move_reconciliation.xml b/addons/account/account_move_reconciliation.xml
deleted file mode 100644
index b3cbb062f2c..00000000000
--- a/addons/account/account_move_reconciliation.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
-
-
-
-
- Reconcile Customer Entries
- account.move.line
- form
- account_reconciliation_list,form
-
-
-
-
-
- Reconcile Supplier Entries
- account.move.line
- form
- account_reconciliation_list,form
-
-
-
-
-
- account.move.line.account_reconciliation_list
- account.move.line
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/addons/account_followup/account_move_reconciliation.py b/addons/account_followup/account_move_reconciliation.py
deleted file mode 100644
index 01338ddb6eb..00000000000
--- a/addons/account_followup/account_move_reconciliation.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 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
-import tools
-
-class account_move_reconciliation(osv.osv):
- _inherit = 'account.move.reconciliation'
-
- def _get_followup(self, cr, uid, ids, field_name, arg, context=None):
- result = {}
- move_obj = self.pool.get("account.move.line")
- for rec in self.browse(cr, uid, ids, context=context):
- move_line_ids = move_obj.search(cr, uid, [('partner_id','=',rec.partner_id.id),('followup_date','=',rec.followup_date)], context=context)
- move_line = move_line_ids and move_obj.browse(cr, uid, move_line_ids[0], context=context) or False
- result[rec.id] = move_line and move_line.followup_line_id.id or False
- return result
-
- _columns = {
- 'followup_date': fields.date('Latest Follow-up'),
- 'followup_id':fields.function(_get_followup, type='many2one', relation='account_followup.followup.line', string='Max Follow Up Level')
- }
-
- def init(self, cr):
- tools.drop_view_if_exists(cr, 'account_move_reconciliation')
- cr.execute("""
- CREATE or REPLACE VIEW account_move_reconciliation as (
- SELECT move_line.partner_id AS id, a.type AS type, move_line.partner_id AS partner_id,
- SUM(move_line.debit) AS debit,
- SUM(move_line.credit) AS credit,
- MAX(move_line.date) AS latest_date,
- MIN(partner.last_reconciliation_date) AS last_reconciliation_date,
- MAX(move_line.followup_date) as followup_date
- FROM account_move_line move_line
- LEFT JOIN account_account a ON (a.id = move_line.account_id)
- LEFT JOIN res_partner partner ON (move_line.partner_id = partner.id)
- WHERE a.reconcile IS TRUE
- AND move_line.reconcile_id IS NULL
- AND (partner.last_reconciliation_date IS NULL OR move_line.date > partner.last_reconciliation_date)
- AND move_line.state <> 'draft'
- GROUP BY move_line.partner_id, a.type
- )
- """)
-account_move_reconciliation()
diff --git a/addons/account_followup/account_move_reconciliation.xml b/addons/account_followup/account_move_reconciliation.xml
deleted file mode 100644
index 6ec70fd18a5..00000000000
--- a/addons/account_followup/account_move_reconciliation.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
- account.move.reconciliation.followup
- account.move.reconciliation
-
-
-
-
-
-
-
-
-
-
-
From ac47444f6a6a9ef5e69f621e2e21be05cbfe4625 Mon Sep 17 00:00:00 2001
From: niv-openerp
Date: Mon, 17 Sep 2012 17:27:22 +0200
Subject: [PATCH 266/408] put back necessary stuff
bzr revid: nicolas.vanhoren@openerp.com-20120917152722-mknjm8lckr8nr83c
---
addons/account/account_view.xml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index 4ddeaf2f3b4..7b49a2f4075 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -1545,7 +1545,8 @@
context="{'search_default_next_partner':1,'view_mode':True}"
id="action_account_manual_reconcile" name="Journal Items"
res_model="account.move.line"
- view_id="view_move_line_tree"/>
+ view_id="view_move_line_tree"
+ view_mode="account_reconciliation_list" />
Date: Mon, 17 Sep 2012 17:33:43 +0200
Subject: [PATCH 267/408] put back one more thing
bzr revid: nicolas.vanhoren@openerp.com-20120917153343-9i33ossljtfkl8op
---
addons/account/account_view.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index 7b49a2f4075..aa52d4430ce 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -1542,7 +1542,7 @@
Date: Mon, 17 Sep 2012 17:41:03 +0200
Subject: [PATCH 268/408] finally got a fucking working version
bzr revid: nicolas.vanhoren@openerp.com-20120917154103-97mg5dp41oyfhq80
---
addons/account/static/src/js/account_move_reconciliation.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/account/static/src/js/account_move_reconciliation.js b/addons/account/static/src/js/account_move_reconciliation.js
index 58992dd4d08..beeb64116bb 100644
--- a/addons/account/static/src/js/account_move_reconciliation.js
+++ b/addons/account/static/src/js/account_move_reconciliation.js
@@ -67,7 +67,7 @@ openerp.account = function (instance) {
return false;
}
- new instance.web.Model("ir.model.data").call("get_object_reference", ["account", "action_account_reconcile_select"]).pipe(function(result) {
+ new instance.web.Model("ir.model.data").call("get_object_reference", ["account", "action_view_account_move_line_reconcile"]).pipe(function(result) {
var additional_context = _.extend({
active_id: ids[0],
active_ids: ids,
From 4de5eb2c96f083791149aaa00a7c9ee807eced69 Mon Sep 17 00:00:00 2001
From: niv-openerp
Date: Mon, 17 Sep 2012 17:52:54 +0200
Subject: [PATCH 269/408] remove useless stuff
bzr revid: nicolas.vanhoren@openerp.com-20120917155254-n9k71w41ik5o10vw
---
addons/account/account_view.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index aa52d4430ce..c5774677676 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -1542,7 +1542,7 @@
Date: Mon, 17 Sep 2012 23:40:59 +0530
Subject: [PATCH 270/408] [FIX]: Workflow signal trigger fix.
bzr revid: atp@tinyerp.com-20120917181059-7s9q4oks766k1cpj
---
addons/stock/stock.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 31d5a68c9fe..14ee58bafd7 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -2923,6 +2923,11 @@ class stock_picking_out(osv.osv):
#instead of it's own workflow (which is not existing)
return self.pool.get('stock.picking')._workflow_trigger(cr, uid, ids, trigger, context=context)
+ def _workflow_signal(self, cr, uid, ids, signal, context=None):
+ #override in order to Fire the workflow Signal on given stock.picking workflow instance.
+ #instead of it's own workflow (which is not existing)
+ return self.pool.get('stock.picking')._workflow_signal(cr, uid, ids, signal, context=context)
+
_columns = {
'state': fields.selection(
[('draft', 'Draft'),
From 5ceb28cb906cbdb81b0d973560959a0b567e3035 Mon Sep 17 00:00:00 2001
From: Raphael Collet
Date: Tue, 18 Sep 2012 09:10:03 +0200
Subject: [PATCH 271/408] [FIX] portal: fix incorrect external reference in
inherited mail.mail
bzr revid: rco@openerp.com-20120918071003-9h02rsu3y6fk595r
---
addons/portal/mail_mail.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/portal/mail_mail.py b/addons/portal/mail_mail.py
index 5b149c1146a..a41c28f15e2 100644
--- a/addons/portal/mail_mail.py
+++ b/addons/portal/mail_mail.py
@@ -43,7 +43,7 @@ class mail_mail_portal(osv.Model):
:param partner: browse_record of the specific recipient partner
"""
if partner:
- portal_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'portal', 'portal_group')
+ portal_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'portal', 'group_portal')
portal_id = portal_ref and portal_ref[1] or False
url = self._generate_signin_url(cr, uid, partner.id, portal_id, 1234, context=context)
body = tools.append_content_to_html(mail.body_html, url)
From 7c8ffe131557f362ac515ac8390bcf310f7db8a7 Mon Sep 17 00:00:00 2001
From: Vishmita
Date: Tue, 18 Sep 2012 12:48:06 +0530
Subject: [PATCH 272/408] [Fix]Improve code
bzr revid: vja@tinyerp.com-20120918071806-da0yjuhby2xd1kqi
---
addons/web/static/src/js/view_list.js | 9 ++++++---
addons/web/static/src/xml/base.xml | 4 ++--
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js
index 3c0ebae4122..bbea57cb959 100644
--- a/addons/web/static/src/js/view_list.js
+++ b/addons/web/static/src/js/view_list.js
@@ -399,10 +399,14 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
*/
setup_columns: function (fields, grouped) {
var registry = instance.web.list.columns;
+ var reorder = this.options.reorderable;
this.columns.splice(0, this.columns.length);
this.columns.push.apply(this.columns,
_(this.fields_view.arch.children).map(function (field) {
var id = field.attrs.name;
+ if(field.attrs.widget == 'handle' && !reorder){
+ field.attrs.reorderable = reorder || true;
+ }
return registry.for_(id, fields[id], field);
}));
if (grouped) {
@@ -411,9 +415,8 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
}
this.visible_columns = _.filter(this.columns, function (column) {
- return column.invisible !== '1';
+ return column.invisible !== '1' && !column.reorderable;
});
-
this.aggregate_columns = _(this.visible_columns).invoke('to_aggregate');
},
/**
@@ -1417,7 +1420,7 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
if ((dataset.sort && dataset.sort())
|| !_(this.columns).any(function (column) {
return column.widget === 'handle'
- || column.name === 'sequence'; }) || !list.options.reorderable){
+ || column.name === 'sequence'; })){
return;
}
var sequence_field = _(this.columns).find(function (c) {
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 37d2dfab414..bc107b36746 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -629,7 +629,7 @@
-
@@ -682,7 +682,7 @@
-
From 91df7dea1db4c959e3d4f24ec10d19cffbccda70 Mon Sep 17 00:00:00 2001
From: Raphael Collet
Date: Tue, 18 Sep 2012 10:03:06 +0200
Subject: [PATCH 273/408] [IMP] portal: simplify the portal access wizard and
generalize it to several partners
bzr revid: rco@openerp.com-20120918080306-gebronsl568xpan1
---
addons/portal/wizard/portal_wizard.py | 10 ++--------
addons/portal/wizard/portal_wizard_view.xml | 3 +--
2 files changed, 3 insertions(+), 10 deletions(-)
diff --git a/addons/portal/wizard/portal_wizard.py b/addons/portal/wizard/portal_wizard.py
index 26fbb383e11..7fcb49fcc58 100644
--- a/addons/portal/wizard/portal_wizard.py
+++ b/addons/portal/wizard/portal_wizard.py
@@ -75,7 +75,6 @@ class wizard(osv.osv_memory):
_description = 'Portal Access Management'
_columns = {
- 'partner_id': fields.many2one('res.partner', required=True, string="Partner"),
'portal_id': fields.many2one('res.groups', domain=[('is_portal', '=', True)], required=True,
string='Portal', help="The portal that users can be added in or removed from."),
'user_ids': fields.one2many('portal.wizard.user', 'wizard_id', string='Users'),
@@ -83,23 +82,18 @@ class wizard(osv.osv_memory):
help="This text is included in the welcome email sent to the users."),
}
- def _default_partner(self, cr, uid, context):
- return context and context.get('active_id') or False
-
def _default_portal(self, cr, uid, context):
portal_ids = self.pool.get('res.groups').search(cr, uid, [('is_portal', '=', True)])
return portal_ids and portal_ids[0] or False
_defaults = {
- 'partner_id': _default_partner,
'portal_id': _default_portal,
}
- def onchange_portal_id(self, cr, uid, ids, partner_id, portal_id, context=None):
- assert partner_id
+ def onchange_portal_id(self, cr, uid, ids, portal_id, context=None):
# for each partner, determine corresponding portal.wizard.user records
res_partner = self.pool.get('res.partner')
- partner_ids = [partner_id]
+ partner_ids = context and context.get('active_ids') or []
user_changes = []
for partner in res_partner.browse(cr, SUPERUSER_ID, partner_ids, context):
for contact in (partner.child_ids or [partner]):
diff --git a/addons/portal/wizard/portal_wizard_view.xml b/addons/portal/wizard/portal_wizard_view.xml
index e6d7901e2aa..6c31a3da371 100644
--- a/addons/portal/wizard/portal_wizard_view.xml
+++ b/addons/portal/wizard/portal_wizard_view.xml
@@ -17,8 +17,7 @@
-
-
+
From 91c096faf55875f82caef317ec26ca02abace0f9 Mon Sep 17 00:00:00 2001
From: Raphael Collet
Date: Tue, 18 Sep 2012 10:11:14 +0200
Subject: [PATCH 274/408] [IMP] portal: clean up method _send_email of portal
access wizard
bzr revid: rco@openerp.com-20120918081114-oi91eh8dvpadvm7d
---
addons/portal/wizard/portal_wizard.py | 27 ++++++++++++++-------------
1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/addons/portal/wizard/portal_wizard.py b/addons/portal/wizard/portal_wizard.py
index 7fcb49fcc58..696cb78eabc 100644
--- a/addons/portal/wizard/portal_wizard.py
+++ b/addons/portal/wizard/portal_wizard.py
@@ -184,36 +184,37 @@ class wizard_user(osv.osv_memory):
@param wizard_user: browse record of model portal.wizard.user
@return: the id of the created mail.mail record
"""
- user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context)
- if not user.email:
+ this_context = context
+ this_user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context)
+ if not this_user.email:
raise osv.except_osv(_('Email required'),
_('You must have an email address in your User Preferences to send emails.'))
# determine subject and body in the portal user's language
- portal_user = wizard_user.partner_id.user_ids[0]
- main_context = context
- context = dict(main_context or {}, lang=portal_user.lang)
+ url = self.pool.get('ir.config_parameter').get_param(cr, SUPERUSER_ID, 'web.base.url', context=this_context)
+ user = wizard_user.partner_id.user_ids[0]
+ context = dict(this_context or {}, lang=user.lang)
data = {
- 'company': user.company_id.name,
+ 'company': this_user.company_id.name,
'portal': wizard_user.wizard_id.portal_id.name,
'message': wizard_user.wizard_id.message or "",
- 'url': _("(missing url)"),
+ 'url': url or _("(missing url)"),
'db': cr.dbname,
- 'login': portal_user.login,
- 'password': portal_user.password,
- 'name': portal_user.name
+ 'login': user.login,
+ 'password': user.password,
+ 'name': user.name
}
subject = _(WELCOME_EMAIL_SUBJECT) % data
body = _(WELCOME_EMAIL_BODY) % data
mail_mail = self.pool.get('mail.mail')
mail_values = {
- 'email_from': user.email,
- 'email_to': portal_user.email,
+ 'email_from': this_user.email,
+ 'email_to': user.email,
'subject': subject,
'body_html': '
%s
' % body,
'state': 'outgoing',
}
- return mail_mail.create(cr, uid, mail_values, context=main_context)
+ return mail_mail.create(cr, uid, mail_values, context=this_context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
From bcab2e061e15671374244dc475074244f57e5af6 Mon Sep 17 00:00:00 2001
From: Raphael Collet
Date: Tue, 18 Sep 2012 11:01:18 +0200
Subject: [PATCH 275/408] [IMP] portal: sanitize email address when using it as
a user login
bzr revid: rco@openerp.com-20120918090118-xhmgpq5fgqwjnfxw
---
addons/portal/wizard/portal_wizard.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/portal/wizard/portal_wizard.py b/addons/portal/wizard/portal_wizard.py
index 696cb78eabc..04e39801496 100644
--- a/addons/portal/wizard/portal_wizard.py
+++ b/addons/portal/wizard/portal_wizard.py
@@ -170,7 +170,7 @@ class wizard_user(osv.osv_memory):
res_users = self.pool.get('res.users')
create_context = dict(context or {}, noshortcut=True) # to prevent shortcut creation
values = {
- 'login': wizard_user.email,
+ 'login': extract_email(wizard_user.email),
'password': random_password(),
'partner_id': wizard_user.partner_id.id,
'groups_id': [(6, 0, [])],
From dd41075caa728bef2e08f7fe24026d04630fcc6d Mon Sep 17 00:00:00 2001
From: Raphael Collet
Date: Tue, 18 Sep 2012 11:02:31 +0200
Subject: [PATCH 276/408] [IMP] portal: delete user when removed from all
portals
bzr revid: rco@openerp.com-20120918090231-14v6ep20dc23zhui
---
addons/portal/wizard/portal_wizard.py | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/addons/portal/wizard/portal_wizard.py b/addons/portal/wizard/portal_wizard.py
index 04e39801496..8ad956510eb 100644
--- a/addons/portal/wizard/portal_wizard.py
+++ b/addons/portal/wizard/portal_wizard.py
@@ -144,10 +144,14 @@ class wizard_user(osv.osv_memory):
# remove the user (if it exists) from the portal group
if user:
if portal in user.groups_id:
- values = {'groups_id': [(3, portal.id)]}
if len(user.groups_id) == 1:
- values['active'] = False # deactivate user
- user.write(values)
+ # delete or deactivate the user
+ try:
+ user.unlink()
+ except:
+ user.write({'groups_id': [(3, portal.id)], 'active': False})
+ else:
+ user.write({'groups_id': [(3, portal.id)]})
def _retrieve_user(self, cr, uid, wizard_user, context=None):
""" retrieve the (possibly inactive) user corresponding to wizard_user.partner_id
From 75b55a0df7f0d8dcb805cc40afd3a2b2f798b4b5 Mon Sep 17 00:00:00 2001
From: Raphael Collet
Date: Tue, 18 Sep 2012 11:03:35 +0200
Subject: [PATCH 277/408] [IMP] portal: make the wizard modify contact emails
(because related field does not work)
bzr revid: rco@openerp.com-20120918090335-mvmy2n8l3misnxow
---
addons/portal/wizard/portal_wizard.py | 10 +++++++++-
addons/portal/wizard/portal_wizard_view.xml | 6 +++++-
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/addons/portal/wizard/portal_wizard.py b/addons/portal/wizard/portal_wizard.py
index 8ad956510eb..aa6a9cf96c6 100644
--- a/addons/portal/wizard/portal_wizard.py
+++ b/addons/portal/wizard/portal_wizard.py
@@ -123,10 +123,18 @@ class wizard_user(osv.osv_memory):
_columns = {
'wizard_id': fields.many2one('portal.wizard', string='Wizard', required=True),
'partner_id': fields.many2one('res.partner', string='Contact', required=True, readonly=True),
- 'email': fields.related('partner_id', 'email', type='char', string='Email'),
+ 'email': fields.char(size=240, string='Email'),
'in_portal': fields.boolean('In Portal'),
}
+ def create(self, cr, uid, values, context=None):
+ """ overridden to update the partner's email (if necessary) """
+ id = super(wizard_user, self).create(cr, uid, values, context)
+ wuser = self.browse(cr, uid, id, context)
+ if wuser.partner_id.email != wuser.email:
+ wuser.partner_id.write({'email': wuser.email})
+ return id
+
def action_apply(self, cr, uid, ids, context=None):
res_users = self.pool.get('res.users')
for wizard_user in self.browse(cr, SUPERUSER_ID, ids, context):
diff --git a/addons/portal/wizard/portal_wizard_view.xml b/addons/portal/wizard/portal_wizard_view.xml
index 6c31a3da371..b2686b34c27 100644
--- a/addons/portal/wizard/portal_wizard_view.xml
+++ b/addons/portal/wizard/portal_wizard_view.xml
@@ -19,7 +19,11 @@
-
+
+ Select which contacts should belong to the portal in the list below.
+ The email address of each selected contact must be valid and unique.
+ If necessary, you can fix any contact's email address directly in the list.
+