-
+
+
@@ -143,7 +144,8 @@
-
+
+
diff --git a/addons/base_contact/migrations/1.2/pre-10-res_partner_address_change.py b/addons/base_contact/migrations/1.2/pre-10-res_partner_address_change.py
new file mode 100644
index 00000000000..26deac23e7f
--- /dev/null
+++ b/addons/base_contact/migrations/1.2/pre-10-res_partner_address_change.py
@@ -0,0 +1,32 @@
+# -*- coding: utf8 -*-
+
+__name__ = "res.partner.adress: for each address it should create a contact with the name of the address"
+
+def migrate(cr, version):
+ generate_contact(cr)
+
+def generate_contact(cr):
+ cr.execute("""DROP TRIGGER IF EXISTS contactjob on res_partner_contact;
+ DROP LANGUAGE IF EXISTS plpgsql CASCADE;
+ CREATE LANGUAGE plpgsql ;
+ CREATE OR REPLACE FUNCTION add_to_job() RETURNS TRIGGER AS $contactjob$
+ DECLARE
+ new_name varchar;
+ new_phonenum varchar;
+ BEGIN
+ IF(TG_OP='INSERT') THEN
+ INSERT INTO res_partner_job(contact_id, address_id, function, state) VALUES(NEW.id, NEW.website::integer,NEW.first_name, 'current');
+ UPDATE res_partner_contact set first_name=Null, website=Null, active=True where id=NEW.id;
+ END IF;
+ RETURN NEW;
+ END;
+ $contactjob$ LANGUAGE plpgsql;
+ CREATE TRIGGER contactjob AFTER INSERT ON res_partner_contact FOR EACH ROW EXECUTE PROCEDURE add_to_job();""")
+ cr.commit()
+
+ cr.execute("INSERT into res_partner_contact (name, title, email, first_name, website) (SELECT coalesce(name, 'Noname'), title, email, function , to_char(id, '99999999') from res_partner_address)")
+ cr.commit()
+ cr.execute("DROP TRIGGER IF EXISTS contactjob on res_partner_contact")
+ cr.execute("DROP LANGUAGE IF EXISTS plpgsql CASCADE;")
+ cr.execute("DROP FUNCTION IF EXISTS add_to_job()")
+ cr.commit()
\ No newline at end of file
diff --git a/addons/base_module_quality/i18n/zh_CN.po b/addons/base_module_quality/i18n/zh_CN.po
index a4ee55061c2..f9b78c86564 100644
--- a/addons/base_module_quality/i18n/zh_CN.po
+++ b/addons/base_module_quality/i18n/zh_CN.po
@@ -8,19 +8,19 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME \n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
-"PO-Revision-Date: 2010-03-17 14:08+0000\n"
-"Last-Translator: 英华 \n"
+"PO-Revision-Date: 2010-06-09 16:41+0000\n"
+"Last-Translator: Wei \"oldrev\" Li \n"
"Language-Team: Simplified Chinese \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-04-17 04:20+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:43+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base_module_quality
#: field:module.quality.check,final_score:0
msgid "Final Score (%)"
-msgstr ""
+msgstr "最终评分(%)"
#. module: base_module_quality
#: constraint:ir.model:0
diff --git a/addons/base_report_designer/i18n/hr.po b/addons/base_report_designer/i18n/hr.po
index 6adc7468085..56742afa154 100644
--- a/addons/base_report_designer/i18n/hr.po
+++ b/addons/base_report_designer/i18n/hr.po
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-07 03:43+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:43+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"
diff --git a/addons/base_setup/base_setup_installer.xml b/addons/base_setup/base_setup_installer.xml
index 7a543f5466f..cbe4c9d24a2 100644
--- a/addons/base_setup/base_setup_installer.xml
+++ b/addons/base_setup/base_setup_installer.xml
@@ -18,10 +18,10 @@
If you don't think you need any of these right now, you can easily install them later on.
-
- 15
-
-
+
+ 15
+
+ Install Generic Modules
@@ -29,7 +29,7 @@ If you don't think you need any of these right now, you can easily install them
-
+
@@ -60,11 +60,11 @@ If you don't think you need any of these right now, you can easily install them
base_setup_installer_action_replacetree
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/addons/base_setup/base_setup_todo.xml b/addons/base_setup/base_setup_todo.xml
index 2d6b400d2c5..5ec9be53d76 100644
--- a/addons/base_setup/base_setup_todo.xml
+++ b/addons/base_setup/base_setup_todo.xml
@@ -10,45 +10,45 @@
Main Company Setup
-
- Information of your company will be used to custiomise your documents like Invoices, Sale Orders,...
-
-
- Configure Your Company
-
-
- 25
-
-
+
+ Information of your company will be used to custiomise your documents like Invoices, Sale Orders,...
+
+
+ Configure Your Company
+
+
+ 25
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
diff --git a/addons/base_setup/i18n/hr.po b/addons/base_setup/i18n/hr.po
index 687d398b8f6..236c8a46a53 100644
--- a/addons/base_setup/i18n/hr.po
+++ b/addons/base_setup/i18n/hr.po
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-07 03:43+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:42+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"
diff --git a/addons/base_setup/security/ir.model.access.csv b/addons/base_setup/security/ir.model.access.csv
index 912e3c1c634..9cc4e8bda68 100644
--- a/addons/base_setup/security/ir.model.access.csv
+++ b/addons/base_setup/security/ir.model.access.csv
@@ -1,4 +1,4 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-"access_base_setup_installer","base.setup.installer","model_base_setup_installer",,1,0,0,0
-"access_base_setup_company","base.setup.company","model_base_setup_company",,1,0,0,0
-"access_base_setup_config","base.setup.config","model_base_setup_config",,1,0,0,0
+"access_base_setup_installer","base.setup.installer","model_base_setup_installer",base.group_system,1,1,1,1
+"access_base_setup_company","base.setup.company","model_base_setup_company",base.group_system,1,1,1,1
+"access_base_setup_config","base.setup.config","model_base_setup_config",base.group_system,1,1,1,1
diff --git a/addons/board_manufacturing/board_manufacturing_view.xml b/addons/board_manufacturing/board_manufacturing_view.xml
index 191f1818612..37624d6e025 100644
--- a/addons/board_manufacturing/board_manufacturing_view.xml
+++ b/addons/board_manufacturing/board_manufacturing_view.xml
@@ -14,8 +14,8 @@
-
-
+
+
diff --git a/addons/board_purchase/board_purchase_view.xml b/addons/board_purchase/board_purchase_view.xml
index 5548b3f2838..8e08ee7134d 100644
--- a/addons/board_purchase/board_purchase_view.xml
+++ b/addons/board_purchase/board_purchase_view.xml
@@ -2,13 +2,13 @@
-
+
-
+ Draft Purchasesir.actions.act_windowpurchase.order
@@ -17,7 +17,7 @@
[('date_order','>',time.strftime('%Y-01-01 00:00:00')),('date_order','<',time.strftime('%Y-12-31 23:59:59')), ('state','=','draft')]
-
+ Quotation Requestir.actions.act_windowpurchase.order
@@ -47,7 +47,7 @@
-
+ Purchase Dashboardboard.boardform
@@ -55,7 +55,7 @@
menu
-
-
+
diff --git a/addons/caldav/wizard/calendar_event_export.py b/addons/caldav/wizard/calendar_event_export.py
index 856d9e9bc91..0be54df9f56 100644
--- a/addons/caldav/wizard/calendar_event_export.py
+++ b/addons/caldav/wizard/calendar_event_export.py
@@ -32,16 +32,6 @@ class calendar_event_export(osv.osv_memory):
"""
Export Calendar Event.
"""
- def process_export_ics(self, cr, uid, ids, context):
- """
- Get Default value for file_path field.
- """
- model = context.get('model', 'basic.calendar')
- model_obj = self.pool.get(model)
-
- calendar = model_obj.export_cal(cr, uid, context['active_ids'], context)
- self.write(cr, uid, ids, {'file_path': base64.encodestring(calendar)})
- return False
def default_get(self, cr, uid, fields, context):
"""
@@ -54,6 +44,9 @@ class calendar_event_export(osv.osv_memory):
name = 'OpenERP %s.ics' % (model_obj._description)
if 'name' in fields:
res.update({'name': name})
+ if 'file_path' in fields:
+ calendar = model_obj.export_cal(cr, uid, context['active_ids'], context)
+ res.update({'file_path': base64.encodestring(calendar)})
return res
_name = "calendar.event.export"
diff --git a/addons/caldav/wizard/calendar_event_export_view.xml b/addons/caldav/wizard/calendar_event_export_view.xml
index 227822966d0..cfadf945bf4 100644
--- a/addons/caldav/wizard/calendar_event_export_view.xml
+++ b/addons/caldav/wizard/calendar_event_export_view.xml
@@ -13,8 +13,8 @@
-
-
+
+
diff --git a/addons/claim_from_delivery/__init__.py b/addons/claim_from_delivery/__init__.py
new file mode 100644
index 00000000000..6f95fbf0fbc
--- /dev/null
+++ b/addons/claim_from_delivery/__init__.py
@@ -0,0 +1,22 @@
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 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 .
+#
+##############################################################################
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
diff --git a/addons/claim_from_delivery/__openerp__.py b/addons/claim_from_delivery/__openerp__.py
new file mode 100644
index 00000000000..86d357834ff
--- /dev/null
+++ b/addons/claim_from_delivery/__openerp__.py
@@ -0,0 +1,35 @@
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 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" : "Claim from delivery",
+ "version" : "1.0",
+ "author" : "Tiny",
+ "category" : "Enterprise Specific Modules/Food Industries",
+ "depends" : ["base", "crm_claim", "stock"],
+ "init_xml" : [],
+ "demo_xml" : [],
+ "description": '''Create Claim from delivery order:
+''',
+ "update_xml" : ["claim_delivery_view.xml"],
+ "active": False,
+ "installable": True
+}
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
diff --git a/addons/claim_from_delivery/claim_delivery_view.xml b/addons/claim_from_delivery/claim_delivery_view.xml
new file mode 100644
index 00000000000..a1c8be870e2
--- /dev/null
+++ b/addons/claim_from_delivery/claim_delivery_view.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/addons/crm/crm.py b/addons/crm/crm.py
index d3c640efca3..618dd55cc21 100644
--- a/addons/crm/crm.py
+++ b/addons/crm/crm.py
@@ -30,19 +30,19 @@ from tools.translate import _
MAX_LEVEL = 15
AVAILABLE_STATES = [
- ('draft', 'Draft'),
- ('open', 'Open'),
- ('cancel', 'Cancelled'),
- ('done', 'Closed'),
+ ('draft', 'Draft'),
+ ('open', 'Open'),
+ ('cancel', 'Cancelled'),
+ ('done', 'Closed'),
('pending', 'Pending'),
]
AVAILABLE_PRIORITIES = [
('1', 'Highest'),
- ('2', 'High'),
- ('3', 'Normal'),
- ('4', 'Low'),
- ('5', 'Lowest'),
+ ('2', 'High'),
+ ('3', 'Normal'),
+ ('4', 'Low'),
+ ('5', 'Lowest'),
]
class crm_case(object):
@@ -107,10 +107,10 @@ class crm_case(object):
"""
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
return user.context_section_id.id or False
-
+
def stage_next(self, cr, uid, ids, context=None):
"""This function computes next stage for case from its current stage
- using available stage for that case type
+ using available stage for that case type
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@@ -120,8 +120,8 @@ class crm_case(object):
context = {}
s = self.get_stage_dict(cr, uid, ids, context=context)
+ section = self._name
for case in self.browse(cr, uid, ids, context):
- section = (case.section_id.id or False)
if section in s:
st = case.stage_id.id or False
if st in s[section]:
@@ -137,13 +137,13 @@ class crm_case(object):
@param context: A standard dictionary for contextual values"""
if not context:
context = {}
-
- sid = self.pool.get('crm.case.stage').search(cr, uid, \
+ stage_obj = self.pool.get('crm.case.stage')
+ sid = stage_obj.search(cr, uid, \
[('object_id.model', '=', self._name)], context=context)
s = {}
previous = {}
- for stage in self.pool.get('crm.case.stage').browse(cr, uid, sid, context=context):
- section = stage.section_id.id or False
+ section = self._name
+ for stage in stage_obj.browse(cr, uid, sid, context=context):
s.setdefault(section, {})
s[section][previous.get(section, False)] = stage.id
previous[section] = stage.id
@@ -151,7 +151,7 @@ class crm_case(object):
def stage_previous(self, cr, uid, ids, context=None):
"""This function computes previous stage for case from its current stage
- using available stage for that case type
+ using available stage for that case type
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@@ -161,9 +161,8 @@ class crm_case(object):
context = {}
s = self.get_stage_dict(cr, uid, ids, context=context)
+ section = self._name
for case in self.browse(cr, uid, ids, context):
- section = (case.section_id.id or False)
-
if section in s:
st = case.stage_id.id or False
s[section] = dict([(v, k) for (k, v) in s[section].iteritems()])
@@ -178,11 +177,11 @@ class crm_case(object):
@param uid: the current user’s ID for security checks,
@param ids: List of case IDs
@param part: Partner's id
- @email: Partner's email ID
+ @email: Partner's email ID
"""
if not part:
- return {'value': {'partner_address_id': False,
- 'email_from': False,
+ return {'value': {'partner_address_id': False,
+ 'email_from': False,
}}
addr = self.pool.get('res.partner').address_get(cr, uid, [part], ['contact'])
data = {'partner_address_id': addr['contact']}
@@ -196,13 +195,13 @@ class crm_case(object):
@param uid: the current user’s ID for security checks,
@param ids: List of case IDs
@param add: Id of Partner's address
- @email: Partner's email ID
+ @email: Partner's email ID
"""
if not add:
return {'value': {'email_from': False}}
address = self.pool.get('res.partner.address').browse(cr, uid, add)
return {'value': {'email_from': address.email}}
-
+
def _history(self, cr, uid, cases, keyword, history=False, subject=None, email=False, details=None, email_from=False, message_id=False, attach=[], context={}):
mailgate_pool = self.pool.get('mailgate.thread')
return mailgate_pool._history(cr, uid, cases, keyword, history=history,\
@@ -210,7 +209,7 @@ class crm_case(object):
details=details, email_from=email_from,\
message_id=message_id, attach=attach, \
context=context)
-
+
def case_open(self, cr, uid, ids, *args):
"""Opens Case
@param self: The object pointer
@@ -266,7 +265,7 @@ class crm_case(object):
if case.section_id.parent_id.user_id:
data['user_id'] = case.section_id.parent_id.user_id.id
else:
- raise osv.except_osv(_('Error !'), _('You can not escalate this case.\nYou are already at the top level.'))
+ raise osv.except_osv(_('Error !'), _('You can not escalate, You are already at the top level regarding your sales-team category.'))
self.write(cr, uid, [case.id], data)
cases = self.browse(cr, uid, ids)
self._history(cr, uid, cases, _('Escalate'))
@@ -318,7 +317,7 @@ class crm_case(object):
self.write(cr, uid, ids, {'state': 'draft', 'active': True})
self._action(cr, uid, cases, 'draft')
return True
-
+
def remind_partner(self, cr, uid, ids, context={}, attach=False):
"""
@@ -351,7 +350,7 @@ class crm_case(object):
src = case.email_from
dest = case.section_id.reply_to
body = ""
- body = case.email_last or case.description
+ body = case.email_last or case.description
if not destination:
src, dest = dest, src
if body and case.user_id.signature:
@@ -382,7 +381,7 @@ class crm_case(object):
# raise osv.except_osv(_('Email!'),("Email Successfully Sent"))
#else:
# raise osv.except_osv(_('Email Fail!'),("Email is not sent successfully"))
- return True
+ return True
def _check(self, cr, uid, ids=False, context={}):
"""
@@ -429,12 +428,12 @@ class crm_case_section(osv.osv):
_order = "name"
_columns = {
- 'name': fields.char('Sales Team', size=64, required=True, translate=True),
- 'code': fields.char('Code', size=8),
+ 'name': fields.char('Sales Team', size=64, required=True, translate=True),
+ 'code': fields.char('Code', size=8),
'active': fields.boolean('Active', help="If the active field is set to \
- true, it will allow you to hide the sales team without removing it."),
- 'allow_unlink': fields.boolean('Allow Delete', help="Allows to delete non draft cases"),
- 'user_id': fields.many2one('res.users', 'Responsible User'),
+ true, it will allow you to hide the sales team without removing it."),
+ 'allow_unlink': fields.boolean('Allow Delete', help="Allows to delete non draft cases"),
+ 'user_id': fields.many2one('res.users', 'Responsible User'),
'member_ids':fields.many2many('res.users', 'sale_member_rel', 'section_id', 'member_id', 'Team Members'),
'reply_to': fields.char('Reply-To', size=64, help="The email address put \
in the 'Reply-To' of all emails sent by Open ERP about cases in this sales team"),
@@ -446,8 +445,8 @@ class crm_case_section(osv.osv):
}
_defaults = {
- 'active': lambda *a: 1,
- 'allow_unlink': lambda *a: 1,
+ 'active': lambda *a: 1,
+ 'allow_unlink': lambda *a: 1,
}
_sql_constraints = [
@@ -464,7 +463,7 @@ class crm_case_section(osv.osv):
@param ids: List of Sales team ids
"""
level = 100
-
+
while len(ids):
cr.execute('select distinct parent_id from crm_case_section where id =ANY(%s)', (ids,))
ids = filter(None, map(lambda x: x[0], cr.fetchall()))
@@ -510,9 +509,9 @@ class crm_case_categ(osv.osv):
_description = "Category of case"
_columns = {
- 'name': fields.char('Case Category Name', size=64, required=True, translate=True),
- 'section_id': fields.many2one('crm.case.section', 'Sales Team'),
- 'object_id': fields.many2one('ir.model', 'Object Name'),
+ 'name': fields.char('Case Category Name', size=64, required=True, translate=True),
+ 'section_id': fields.many2one('crm.case.section', 'Sales Team'),
+ 'object_id': fields.many2one('ir.model', 'Object Name'),
}
def _find_object_id(self, cr, uid, context=None):
@@ -542,9 +541,9 @@ class crm_case_resource_type(osv.osv):
_rec_name = "name"
_columns = {
- 'name': fields.char('Case Resource Type', size=64, required=True, translate=True),
- 'section_id': fields.many2one('crm.case.section', 'Sales Team'),
- 'object_id': fields.many2one('ir.model', 'Object Name'),
+ 'name': fields.char('Case Resource Type', size=64, required=True, translate=True),
+ 'section_id': fields.many2one('crm.case.section', 'Sales Team'),
+ 'object_id': fields.many2one('ir.model', 'Object Name'),
}
def _find_object_id(self, cr, uid, context=None):
"""Finds id for case object
@@ -573,14 +572,14 @@ class crm_case_stage(osv.osv):
_order = "sequence"
_columns = {
- 'name': fields.char('Stage Name', size=64, required=True, translate=True),
- 'section_id': fields.many2one('crm.case.section', 'Sales Team'),
+ 'name': fields.char('Stage Name', size=64, required=True, translate=True),
+ 'section_id': fields.many2one('crm.case.section', 'Sales Team'),
'sequence': fields.integer('Sequence', help="Gives the sequence order \
- when displaying a list of case stages."),
- 'object_id': fields.many2one('ir.model', 'Object Name'),
- 'probability': fields.float('Probability (%)', required=True),
+ when displaying a list of case stages."),
+ 'object_id': fields.many2one('ir.model', 'Object Name'),
+ 'probability': fields.float('Probability (%)', required=True),
'on_change': fields.boolean('Change Probability Automatically', \
- help="Change Probability on next and previous stages."),
+ help="Change Probability on next and previous stages."),
'requirements': fields.text('Requirements')
}
def _find_object_id(self, cr, uid, context=None):
@@ -595,8 +594,8 @@ class crm_case_stage(osv.osv):
return ids and ids[0]
_defaults = {
- 'sequence': lambda *args: 1,
- 'probability': lambda *args: 0.0,
+ 'sequence': lambda *args: 1,
+ 'probability': lambda *args: 0.0,
'object_id' : _find_object_id
}
@@ -620,7 +619,7 @@ class users(osv.osv):
_inherit = 'res.users'
_description = "Users"
_columns = {
- 'context_section_id': fields.many2one('crm.case.section', 'Sales Team'),
+ 'context_section_id': fields.many2one('crm.case.section', 'Sales Team'),
}
users()
@@ -628,7 +627,7 @@ users()
class res_partner(osv.osv):
_inherit = 'res.partner'
_columns = {
- 'section_id': fields.many2one('crm.case.section', 'Sales Team'),
+ 'section_id': fields.many2one('crm.case.section', 'Sales Team'),
}
res_partner()
diff --git a/addons/crm/crm_data.xml b/addons/crm/crm_data.xml
index 1873f53f573..61a9c4909de 100644
--- a/addons/crm/crm_data.xml
+++ b/addons/crm/crm_data.xml
@@ -7,16 +7,7 @@
-
- Check cases rules
- 4
- hours
- -1
-
-
-
-
-
+
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index c1060f3e658..e92378785d6 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -32,10 +32,11 @@ class crm_lead(osv.osv, crm_case):
""" CRM Lead Case """
_name = "crm.lead"
- _description = "Lead"
+ _description = "Lead/Opportunity"
_order = "priority, id desc"
_inherit = ['res.partner.address']
_inherits = {'mailgate.thread': 'thread_id'}
+ _log_create=True
def _compute_day(self, cr, uid, ids, fields, args, context={}):
"""
diff --git a/addons/crm/crm_lead_menu.xml b/addons/crm/crm_lead_menu.xml
index aad27f9eb14..cea854427dc 100644
--- a/addons/crm/crm_lead_menu.xml
+++ b/addons/crm/crm_lead_menu.xml
@@ -29,7 +29,6 @@
-
+
@@ -273,23 +274,23 @@
search
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
diff --git a/addons/crm/crm_mailgate.py b/addons/crm/crm_mailgate.py
index 00fa761f51d..f2380182aad 100644
--- a/addons/crm/crm_mailgate.py
+++ b/addons/crm/crm_mailgate.py
@@ -32,11 +32,12 @@ from tools.translate import _
import tools
from osv import fields,osv,orm
from osv.orm import except_orm
+import collections
from tools import command_re
-class crm_cases(osv.osv):
- """ crm cases """
+class mailgate_thread(osv.osv):
+ """ mailgate_thread """
_name = "mailgate.thread"
_inherit = "mailgate.thread"
@@ -127,7 +128,7 @@ class crm_cases(osv.osv):
#getattr(self, act)(cr, uid, select)
return res
- def emails_get(self, cr, uid, ids, context={}):
+ def emails_get(self, cr, uid, ids, context=None):
"""
Get Emails
@@ -137,16 +138,24 @@ class crm_cases(osv.osv):
@param ids: List of email’s IDs
@param context: A standard dictionary for contextual values
"""
- res = []
+ res = {}
+
if isinstance(ids, (str, int, long)):
- select = [ids]
+ select = [long(ids)]
else:
select = ids
- for case in self.browse(cr, uid, select):
- user_email = (case.user_id and case.user_id.address_id and case.user_id.address_id.email) or False
- res += [(user_email, case.email_from, case.email_cc or False, getattr(case,'priority') and case.priority or False)]
- if isinstance(ids, (str, int, long)):
- return len(res) and res[0] or False
+
+ for thread in self.browse(cr, uid, select, context=context):
+ values = collections.defaultdict(set)
+
+ for message in thread.message_ids:
+ user_email = (message.user_id and message.user_id.address_id and message.user_id.address_id.email) or False
+ values['user_email'].add(user_email)
+ values['email_from'].add(message.email_from)
+ values['email_cc'].add(message.email_cc or False)
+
+ res[str(thread.id)] = dict((key,list(values[key])) for key, value in values.iteritems())
+
return res
def msg_send(self, cr, uid, id, *args, **argv):
@@ -161,4 +170,4 @@ class crm_cases(osv.osv):
"""
return True
-crm_cases()
+mailgate_thread()
diff --git a/addons/crm/crm_meeting.py b/addons/crm/crm_meeting.py
index 133cb98f9dc..e3116ba39ca 100644
--- a/addons/crm/crm_meeting.py
+++ b/addons/crm/crm_meeting.py
@@ -45,6 +45,7 @@ class crm_meeting(osv.osv, crm_case):
_order = "id desc"
_inherit = ["calendar.event"]
_inherits = {'mailgate.thread': 'thread_id'}
+ _log_create=True
_columns = {
# From crm.case
diff --git a/addons/crm/crm_meeting_menu.xml b/addons/crm/crm_meeting_menu.xml
index aaae9541613..ec58c116baf 100644
--- a/addons/crm/crm_meeting_menu.xml
+++ b/addons/crm/crm_meeting_menu.xml
@@ -38,7 +38,7 @@
-
+ gantt
@@ -85,33 +85,33 @@
+ parent="base.menu_base_partner" sequence="3" />
+ action="crm_case_categ_meet" parent="menu_meeting_sale"
+ sequence="1" />
-
+ Calendarir.ui.menu
-
+
- Meeting Invitations
- ir.actions.act_window
- calendar.attendee
- form
- tree,form
-
+ Meeting Invitations
+ ir.actions.act_window
+ calendar.attendee
+ form
+ tree,form
+ [('ref','like','crm.meeting,')]
- {'default_sent_by_uid': uid}
-
+ {'default_sent_by_uid': uid}
+
+ name="Meeting Invitations" parent="crm.menu_meeting_sale"
+ sequence="10" action="action_view_attendee_form"
+ groups="base.group_extended" />
diff --git a/addons/crm/crm_meeting_view.xml b/addons/crm/crm_meeting_view.xml
index e2decc30340..34bdafe1c58 100644
--- a/addons/crm/crm_meeting_view.xml
+++ b/addons/crm/crm_meeting_view.xml
@@ -2,7 +2,7 @@
-
+
Meeting Categories
@@ -16,7 +16,7 @@
-
+
CRM - Meetings Form
@@ -26,7 +26,7 @@
@@ -233,23 +233,23 @@
search
-
-
-
-
+
+
-
-
-
-
-
+
+
+
+
-
-
+
+
diff --git a/addons/document/report/document_report_view.xml b/addons/document/report/document_report_view.xml
index 4afc66fb4d7..00743d768e7 100644
--- a/addons/document/report/document_report_view.xml
+++ b/addons/document/report/document_report_view.xml
@@ -41,8 +41,8 @@
-
-
+
+
diff --git a/addons/document_ftp/__init__.py b/addons/document_ftp/__init__.py
index 45ec4a6b67f..af514df8985 100644
--- a/addons/document_ftp/__init__.py
+++ b/addons/document_ftp/__init__.py
@@ -18,7 +18,7 @@
# along with this program. If not, see .
#
##############################################################################
-import doc_conf_wizard
import ftpserver
+import wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/document_ftp/__openerp__.py b/addons/document_ftp/__openerp__.py
index 18042dabf93..92ecac1d4ed 100644
--- a/addons/document_ftp/__openerp__.py
+++ b/addons/document_ftp/__openerp__.py
@@ -33,7 +33,8 @@
'depends': ['base', 'document'],
'init_xml': [],
'update_xml': [
- 'document_ftp_view.xml',
+ 'wizard/ftp_browse_view.xml',
+ 'wizard/document_configuration_view.xml',
'security/ir.model.access.csv'
],
'demo_xml': [],
diff --git a/addons/document_ftp/doc_conf_wizard.py b/addons/document_ftp/doc_conf_wizard.py
deleted file mode 100644
index 1399bc276b5..00000000000
--- a/addons/document_ftp/doc_conf_wizard.py
+++ /dev/null
@@ -1,149 +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 base64
-
-from osv import osv, fields
-from osv.orm import except_orm
-import urlparse
-
-import os
-
-class document_configuration_wizard(osv.osv_memory):
-
- _name='document.configuration.wizard'
- _description = 'Auto Directory Configuration'
- _inherit = 'res.config'
- _rec_name = 'host'
- _columns = {
- 'host': fields.char('Address', size=64,
- help="Server address or IP.", required=True),
- }
-
- def detect_ip_addr(self, cr, uid, context=None):
- def _detect_ip_addr(self, cr, uid, context=None):
- from array import array
- import socket
- from struct import pack, unpack
-
- try:
- import fcntl
- except ImportError:
- fcntl = None
-
- if not fcntl: # not UNIX:
- host = socket.gethostname()
- ip_addr = socket.gethostbyname(host)
- else: # UNIX:
- # get all interfaces:
- nbytes = 128 * 32
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- names = array('B', '\0' * nbytes)
- outbytes = unpack('iL', fcntl.ioctl( s.fileno(), 0x8912, pack('iL', nbytes, names.buffer_info()[0])))[0]
- namestr = names.tostring()
- ifaces = [namestr[i:i+32].split('\0', 1)[0] for i in range(0, outbytes, 32)]
-
- for ifname in [iface for iface in ifaces if iface != 'lo']:
- ip_addr = socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, pack('256s', ifname[:15]))[20:24])
- break
- return ip_addr
-
- try:
- ip_addr = _detect_ip_addr(self, cr, uid, context)
- except:
- ip_addr = 'localhost'
- return ip_addr
-
- _defaults = {
- 'host': detect_ip_addr,
- }
-
- def execute(self, cr, uid, ids, context=None):
- conf = self.browse(cr, uid, ids[0], context)
- obj=self.pool.get('document.directory')
- objid=self.pool.get('ir.model.data')
-
- if self.pool.get('sale.order'):
- id = objid._get_id(cr, uid, 'document', 'dir_sale_order_all')
- id = objid.browse(cr, uid, id, context=context).res_id
- mid = self.pool.get('ir.model').search(cr, uid, [('model','=','sale.order')])
- obj.write(cr, uid, [id], {
- 'type':'ressource',
- 'ressource_type_id': mid[0],
- 'domain': '[]',
- })
- aid = objid._get_id(cr, uid, 'sale', 'report_sale_order')
- aid = objid.browse(cr, uid, aid, context=context).res_id
-
- self.pool.get('document.directory.content').create(cr, uid, {
- 'name': "Print Order",
- 'suffix': "_print",
- 'report_id': aid,
- 'extension': '.pdf',
- 'include_name': 1,
- 'directory_id': id,
- })
- id = objid._get_id(cr, uid, 'document', 'dir_sale_order_quote')
- id = objid.browse(cr, uid, id, context=context).res_id
- obj.write(cr, uid, [id], {
- 'type':'ressource',
- 'ressource_type_id': mid[0],
- 'domain': "[('state','=','draft')]",
- })
-
- if self.pool.get('product.product'):
- id = objid._get_id(cr, uid, 'document', 'dir_product')
- id = objid.browse(cr, uid, id, context=context).res_id
- mid = self.pool.get('ir.model').search(cr, uid, [('model','=','product.product')])
- obj.write(cr, uid, [id], {
- 'type':'ressource',
- 'ressource_type_id': mid[0],
- })
-
- if self.pool.get('stock.location'):
- aid = objid._get_id(cr, uid, 'stock', 'report_product_history')
- aid = objid.browse(cr, uid, aid, context=context).res_id
-
- self.pool.get('document.directory.content').create(cr, uid, {
- 'name': "Product Stock",
- 'suffix': "_stock_forecast",
- 'report_id': aid,
- 'extension': '.pdf',
- 'include_name': 1,
- 'directory_id': id,
- })
-
- if self.pool.get('account.analytic.account'):
- id = objid._get_id(cr, uid, 'document', 'dir_project')
- id = objid.browse(cr, uid, id, context=context).res_id
- mid = self.pool.get('ir.model').search(cr, uid, [('model','=','account.analytic.account')])
- obj.write(cr, uid, [id], {
- 'type':'ressource',
- 'ressource_type_id': mid[0],
- 'domain': '[]',
- 'ressource_tree': 1
- })
-
- # Update the action for FTP browse.
- aid = objid._get_id(cr, uid, 'document_ftp', 'action_document_browse')
- aid = objid.browse(cr, uid, aid, context=context).res_id
- self.pool.get('ir.actions.url').write(cr, uid, [aid], {'url': 'ftp://'+(conf.host or 'localhost')+':8021/'})
-document_configuration_wizard()
diff --git a/addons/document_ftp/wizard/__init__.py b/addons/document_ftp/wizard/__init__.py
new file mode 100644
index 00000000000..22971249113
--- /dev/null
+++ b/addons/document_ftp/wizard/__init__.py
@@ -0,0 +1,24 @@
+# -*- 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 ftp_browse
+import document_configuration
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/document_ftp/wizard/document_configuration.py b/addons/document_ftp/wizard/document_configuration.py
new file mode 100644
index 00000000000..e7966c2e3a4
--- /dev/null
+++ b/addons/document_ftp/wizard/document_configuration.py
@@ -0,0 +1,121 @@
+# -*- 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, fields
+from document_ftp import ftpserver
+class document_configuration(osv.osv_memory):
+
+ _name='document.configuration'
+ _description = 'Auto Directory Configuration'
+ _inherit = 'res.config'
+
+ _columns = {
+ 'sale_order' : fields.boolean('Sale Order', help="Auto directory configuration for Sale Orders and Quotation with report."),
+ 'product' : fields.boolean('Product', help="Auto directory configuration for Products."),
+ 'project': fields.boolean('Project', help="Auto directory configuration for Projects."),
+ }
+
+
+ def execute(self, cr, uid, ids, context=None):
+ conf_id = ids and ids[0] or False
+ conf = self.browse(cr, uid, conf_id, context)
+ dir_pool = self.pool.get('document.directory')
+ data_pool = self.pool.get('ir.model.data')
+ model_pool = self.pool.get('ir.model')
+ content_pool = self.pool.get('document.directory.content')
+ if conf.sale_order and self.pool.get('sale.order'):
+ # Sale order
+ dir_data_id = data_pool._get_id(cr, uid, 'document', 'dir_sale_order_all')
+ if dir_data_id:
+ sale_dir_id = data_pool.browse(cr, uid, dir_data_id, context=context).res_id
+ else:
+ sale_dir_id = data_pool.create(cr, uid, {'name': 'Sale Orders'})
+ mid = model_pool.search(cr, uid, [('model','=','sale.order')])
+ dir_pool.write(cr, uid, [sale_dir_id], {
+ 'type':'ressource',
+ 'ressource_type_id': mid[0],
+ 'domain': '[]',
+ })
+ # Qutation
+ dir_data_id = data_pool._get_id(cr, uid, 'document', 'dir_sale_order_quote')
+ if dir_data_id:
+ quta_dir_id = data_pool.browse(cr, uid, dir_data_id, context=context).res_id
+ else:
+ quta_dir_id = data_pool.create(cr, uid, {'name': 'Sale Quotations'})
+
+ dir_pool.write(cr, uid, [quta_dir_id], {
+ 'type':'ressource',
+ 'ressource_type_id': mid[0],
+ 'domain': "[('state','=','draft')]",
+ })
+ # Sale Order Report
+ order_report_data_id = data_pool._get_id(cr, uid, 'sale', 'report_sale_order')
+ if order_report_data_id:
+ order_report_id = data_pool.browse(cr, uid, order_report_data_id, context=context).res_id
+
+ content_pool.create(cr, uid, {
+ 'name': "Print Order",
+ 'suffix': "_print",
+ 'report_id': order_report_id,
+ 'extension': '.pdf',
+ 'include_name': 1,
+ 'directory_id': sale_dir_id,
+ })
+
+ content_pool.create(cr, uid, {
+ 'name': "Print Qutation",
+ 'suffix': "_print",
+ 'report_id': order_report_id,
+ 'extension': '.pdf',
+ 'include_name': 1,
+ 'directory_id': quta_dir_id,
+ })
+
+
+ if conf.product and self.pool.get('product.product'):
+ # Product
+ dir_data_id = data_pool._get_id(cr, uid, 'document', 'dir_product')
+ if dir_data_id:
+ product_dir_id = data_pool.browse(cr, uid, dir_data_id, context=context).res_id
+ else:
+ product_dir_id = data_pool.create(cr, uid, {'name': 'Products'})
+
+ mid = model_pool.search(cr, uid, [('model','=','product.product')])
+ dir_pool.write(cr, uid, [product_dir_id], {
+ 'type':'ressource',
+ 'ressource_type_id': mid[0],
+ })
+
+ if conf.project and self.pool.get('account.analytic.account'):
+ # Project
+ dir_data_id = data_pool._get_id(cr, uid, 'document', 'dir_project')
+ if dir_data_id:
+ project_dir_id = data_pool.browse(cr, uid, dir_data_id, context=context).res_id
+ else:
+ project_dir_id = data_pool.create(cr, uid, {'name': 'Projects'})
+
+ mid = model_pool.search(cr, uid, [('model','=','account.analytic.account')])
+ dir_pool.write(cr, uid, [project_dir_id], {
+ 'type':'ressource',
+ 'ressource_type_id': mid[0],
+ 'domain': '[]',
+ 'ressource_tree': 1
+ })
+document_configuration()
diff --git a/addons/document_ftp/document_ftp_view.xml b/addons/document_ftp/wizard/document_configuration_view.xml
similarity index 67%
rename from addons/document_ftp/document_ftp_view.xml
rename to addons/document_ftp/wizard/document_configuration_view.xml
index d3f4c09498c..c6f40deb429 100644
--- a/addons/document_ftp/document_ftp_view.xml
+++ b/addons/document_ftp/wizard/document_configuration_view.xml
@@ -1,22 +1,8 @@
-
- Browse Files
- ftp://localhost:8021/
-
-
-
-
-
Auto Configure Directory
- document.configuration.wizard
+ document.configurationform
@@ -25,17 +11,21 @@
Auto Configure
- FTP Server Configuration
+ Resource Directory Configuration
- Choose the address for the Document Management System's FTP server.
+ Choose the following Resouces to auto directory configuration.12
-
+
+
+
+
+
@@ -45,7 +35,7 @@
Auto Configure Directoryir.actions.act_window
- document.configuration.wizard
+ document.configurationformform
diff --git a/addons/document_ftp/wizard/ftp_browse.py b/addons/document_ftp/wizard/ftp_browse.py
new file mode 100644
index 00000000000..06c9766997b
--- /dev/null
+++ b/addons/document_ftp/wizard/ftp_browse.py
@@ -0,0 +1,53 @@
+# -*- 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, fields
+from tools.translate import _
+
+from document_ftp import ftpserver
+class document_ftp_browse(osv.osv_memory):
+ _name = 'document.ftp.browse'
+ _description = 'Document FTP Browse'
+
+ _columns = {
+ 'url' : fields.char('FTP Server', size=64, required=True),
+ }
+
+ def default_get(self, cr, uid, fields, context=None):
+ res = {}
+ if 'url' in fields:
+ user_pool = self.pool.get('res.users')
+ current_user = user_pool.browse(cr, uid, uid, context=context)
+ res['url'] = '%s@%s:%d'%(current_user.login, ftpserver.HOST, ftpserver.PORT)
+ return res
+
+ def browse_ftp(self, cr, uid, ids, context):
+ data_id = ids and ids[0] or False
+ data = self.browse(cr, uid, data_id, context)
+ ftp_url = 'ftp://'
+ final_url = ftp_url + data.url
+ return {
+ 'type': 'ir.actions.act_url',
+ 'url':final_url,
+ 'target': 'new'
+ }
+document_ftp_browse()
+
diff --git a/addons/document_ftp/wizard/ftp_browse_view.xml b/addons/document_ftp/wizard/ftp_browse_view.xml
new file mode 100644
index 00000000000..a32f93e096f
--- /dev/null
+++ b/addons/document_ftp/wizard/ftp_browse_view.xml
@@ -0,0 +1,40 @@
+
+
+
+
+ Document FTP Browse
+ document.ftp.browse
+ form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Document Browse
+ ir.actions.act_window
+ document.ftp.browse
+
+ form
+ form
+ new
+
+
+
+
+
+
diff --git a/addons/document_ics/i18n/et.po b/addons/document_ics/i18n/et.po
index 79dbad26d26..8945068e8a4 100644
--- a/addons/document_ics/i18n/et.po
+++ b/addons/document_ics/i18n/et.po
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
-"PO-Revision-Date: 2009-09-16 15:43+0000\n"
-"Last-Translator: Fabien (Open ERP) \n"
+"PO-Revision-Date: 2010-06-08 17:44+0000\n"
+"Last-Translator: lyyser \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-04-17 04:18+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:43+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: document_ics
@@ -36,7 +36,7 @@ msgstr "Viga! Sa ei saa luua regrussiivseid kaustu."
#. module: document_ics
#: field:document.ics.crm.wizard,jobs:0
msgid "Jobs Hiring Process"
-msgstr ""
+msgstr "Töökohad Töölevõtmise Protsess"
#. module: document_ics
#: view:document.ics.crm.wizard:0
@@ -122,7 +122,7 @@ msgstr "Seadista kalendrid sektsioonide jaoks "
#. module: document_ics
#: help:document.ics.crm.wizard,opportunity:0
msgid "Tracks identified business opportunities for your sales pipeline."
-msgstr ""
+msgstr "Jälgib tuvastatud ärivõimalusi sinu müükide konveierile."
#. module: document_ics
#: help:document.ics.crm.wizard,fund:0
@@ -209,6 +209,8 @@ msgid ""
"Manages the supplier and customers claims, including your corrective or "
"preventive actions."
msgstr ""
+"Haldab tarnijate ja klientide nõudeid, sealjuures sinu korrigeerivaid ja "
+"vältivaid tegevusi."
#. module: document_ics
#: selection:document.directory.ics.fields,name:0
@@ -241,6 +243,8 @@ msgid ""
"Help you to encode the result of a phone call or to planify a list of phone "
"calls to process."
msgstr ""
+"Aitab sul arvutada telefonikõne tulemust või planeerida nimekirja "
+"telefonikõnedest töötlemiseks."
#. module: document_ics
#: selection:document.directory.ics.fields,name:0
@@ -315,7 +319,7 @@ msgstr "Tühista"
#. module: document_ics
#: field:document.ics.crm.wizard,opportunity:0
msgid "Business Opportunities"
-msgstr ""
+msgstr "Äri võimalused"
#. module: document_ics
#: selection:document.directory.ics.fields,name:0
diff --git a/addons/email_template/__init__.py b/addons/email_template/__init__.py
old mode 100755
new mode 100644
diff --git a/addons/email_template/__openerp__.py b/addons/email_template/__openerp__.py
old mode 100755
new mode 100644
index 9c5f7bb5c70..ef50f631e3e
--- a/addons/email_template/__openerp__.py
+++ b/addons/email_template/__openerp__.py
@@ -16,6 +16,7 @@
'email_template_view.xml',
'email_template_mailbox_view.xml',
'wizard/email_template_send_wizard_view.xml',
+ 'security/ir.model.access.csv'
],
"installable": True,
"active": False,
diff --git a/addons/email_template/email_template.py b/addons/email_template/email_template.py
old mode 100755
new mode 100644
index 6c46da458c6..2d34a095ff5
--- a/addons/email_template/email_template.py
+++ b/addons/email_template/email_template.py
@@ -17,10 +17,10 @@ try:
TEMPLATE_ENGINES.append(('mako', 'Mako Templates'))
except:
LOGGER.notifyChannel(
- _("Email Template"),
- netsvc.LOG_ERROR,
- _("Mako templates not installed")
- )
+ _("Email Template"),
+ netsvc.LOG_WARNING,
+ _("Mako templates not installed")
+ )
try:
from django.template import Context, Template as DjangoTemplate
#Workaround for bug:
@@ -31,10 +31,10 @@ try:
TEMPLATE_ENGINES.append(('django', 'Django Template'))
except:
LOGGER.notifyChannel(
- _("Email Template"),
- netsvc.LOG_ERROR,
- _("Django templates not installed")
- )
+ _("Email Template"),
+ netsvc.LOG_WARNING,
+ _("Django templates not installed")
+ )
import email_template_engines
import tools
@@ -102,9 +102,15 @@ class email_template(osv.osv):
}
_columns = {
- 'name' : fields.char('Name of Template', size=100, required=True),
+ 'name' : fields.char('Name', size=100, required=True),
'object_name':fields.many2one('ir.model', 'Model'),
'model_int_name':fields.char('Model Internal Name', size=200,),
+ 'enforce_from_account':fields.many2one(
+ 'email_template.account',
+ string="Enforce From Account",
+ help="Emails will be sent only from this account."),
+ 'from_email' : fields.related('enforce_from_account', 'email_id',
+ type='char', string='From',),
'def_to':fields.char(
'Recepient (To)',
size=250,
@@ -141,7 +147,7 @@ class email_template(osv.osv):
help="The text version of the mail",
translate=True),
'use_sign':fields.boolean(
- 'Use Signature',
+ 'Signature',
help="the signature from the User details"
"will be appened to the mail"),
'file_name':fields.char(
@@ -168,11 +174,6 @@ class email_template(osv.osv):
string="Allowed User Groups",
help="Only users from these groups will be"
" allowed to send mails from this Template"),
- 'enforce_from_account':fields.many2one(
- 'email_template.account',
- string="Enforce From Account",
- help="Emails will be sent only from this account.",
- domain="[('company','=','yes')]"),
'model_object_field':fields.many2one(
'ir.model.fields',
string="Field",
@@ -218,6 +219,7 @@ class email_template(osv.osv):
}
_defaults = {
+ 'template_language' : lambda *a:'mako',
}
_sql_constraints = [
@@ -466,7 +468,7 @@ class email_template(osv.osv):
context)
return True
- def generate_mailbox_item_from_template(self,
+ def _generate_mailbox_item_from_template(self,
cursor,
user,
template,
@@ -557,6 +559,8 @@ class email_template(osv.osv):
'folder':'drafts',
'mail_type':'multipart/alternative'
}
+ if not mailbox_values['account_id']:
+ raise Exception("Unable to send the mail. No account linked to the template.")
#Use signatures if allowed
if template.use_sign:
sign = self.pool.get('res.users').read(cursor,
@@ -568,13 +572,17 @@ class email_template(osv.osv):
mailbox_values['body_text'] += sign
if mailbox_values['body_html']:
mailbox_values['body_html'] += sign
+ print 'Creating', mailbox_values
mailbox_id = self.pool.get('email_template.mailbox').create(
cursor,
user,
mailbox_values,
context)
+
+ print 'Sending', mailbox_id
+ self.pool.get('email_template.mailbox').send_this_mail(cursor, user, [mailbox_id], context)
return mailbox_id
-
+
def generate_mail(self,
cursor,
user,
@@ -586,6 +594,7 @@ class email_template(osv.osv):
template = self.browse(cursor, user, template_id, context=context)
if not template:
raise Exception("The requested template could not be loaded")
+ print 'loaded', record_ids
for record_id in record_ids:
mailbox_id = self._generate_mailbox_item_from_template(
cursor,
@@ -593,6 +602,7 @@ class email_template(osv.osv):
template,
record_id,
context)
+ print 'loaded'
mail = self.pool.get('email_template.mailbox').browse(
cursor,
user,
@@ -614,7 +624,7 @@ class email_template(osv.osv):
mailbox_id,
{'folder':'outbox'},
context=context
- )
+ )
return True
email_template()
@@ -623,19 +633,6 @@ class email_template_preview(osv.osv_memory):
_name = "email_template.preview"
_description = "Email Template Preview"
- def _get_model_recs(self, cr, uid, context=None):
- if context is None:
- context = {}
- #Fills up the selection box which allows records from the selected object to be displayed
- self.context = context
- if 'active_id' in context.keys():
-# context['active_id'] = 5
- ref_obj_id = self.pool.get('email.template').read(cr, uid, context['active_id'], ['object_name'], context)
- ref_obj_name = self.pool.get('ir.model').read(cr, uid, ref_obj_id[0], ['model'], context)['model']
- ref_obj_ids = self.pool.get(ref_obj_name).search(cr, uid, [], context=context)
- ref_obj_recs = self.pool.get(ref_obj_name).name_get(cr, uid, ref_obj_ids, context)
- return ref_obj_recs
-
def _default_model(self, cursor, user, context=None):
"""
Returns the default value for model field
@@ -655,7 +652,6 @@ class email_template_preview(osv.osv_memory):
'email.template',
'Template', readonly=True),
'rel_model':fields.many2one('ir.model', 'Model', readonly=True),
- 'rel_model_ref':fields.selection(_get_model_recs, 'Referred Document'),
'to':fields.char('To', size=250, readonly=True),
'cc':fields.char('CC', size=250, readonly=True),
'bcc':fields.char('BCC', size=250, readonly=True),
@@ -668,7 +664,7 @@ class email_template_preview(osv.osv_memory):
'ref_template': lambda self, cr, uid, ctx:ctx['active_id'],
'rel_model': _default_model
}
-
+ # Need to check
def on_change_ref(self, cr, uid, ids, rel_model_ref, context=None):
if context is None:
context = {}
diff --git a/addons/email_template/email_template_account.py b/addons/email_template/email_template_account.py
old mode 100755
new mode 100644
index 2503d19cd10..0bcf3c3d099
--- a/addons/email_template/email_template_account.py
+++ b/addons/email_template/email_template_account.py
@@ -30,7 +30,7 @@ class email_template_account(osv.osv):
'text/html'
]
_columns = {
- 'name': fields.char('Email Account Desc',
+ 'name': fields.char('Description',
size=64, required=True,
readonly=True, select=True,
states={'draft':[('readonly', False)]}),
@@ -56,22 +56,16 @@ class email_template_account(osv.osv):
size=120, invisible=True,
required=False, readonly=True,
states={'draft':[('readonly', False)]}),
- 'smtptls':fields.boolean('Use TLS',
+ 'smtptls':fields.boolean('TLS',
states={'draft':[('readonly', False)]}, readonly=True),
- 'smtpssl':fields.boolean('Use SSL/TLS (only in python 2.6)',
+ 'smtpssl':fields.boolean('SSL/TLS (only in python 2.6)',
states={'draft':[('readonly', False)]}, readonly=True),
'send_pref':fields.selection([
('html', 'HTML otherwise Text'),
('text', 'Text otherwise HTML'),
('both', 'Both HTML & Text')
], 'Mail Format', required=True),
- 'allowed_groups':fields.many2many(
- 'res.groups',
- 'account_group_rel', 'templ_id', 'group_id',
- string="Allowed User Groups",
- help="Only users from these groups will be" \
- "allowed to send mails from this ID"),
'company':fields.selection([
('yes', 'Yes'),
('no', 'No')
@@ -89,7 +83,7 @@ class email_template_account(osv.osv):
('suspended', 'Suspended'),
('approved', 'Approved')
],
- 'Account Status', required=True, readonly=True),
+ 'Status', required=True, readonly=True),
}
_defaults = {
@@ -102,7 +96,6 @@ class email_template_account(osv.osv):
['name'],
context
)['name'],
- 'smtpssl':lambda * a:True,
'state':lambda * a:'draft',
'user':lambda self, cursor, user, context:user,
'send_pref':lambda * a: 'html',
diff --git a/addons/email_template/email_template_account_view.xml b/addons/email_template/email_template_account_view.xml
old mode 100755
new mode 100644
index 573b03e7027..9a35328b25c
--- a/addons/email_template/email_template_account_view.xml
+++ b/addons/email_template/email_template_account_view.xml
@@ -1,72 +1,69 @@
-
+
-
- email_template.account.form
- email_template.account
- form
-
-
+
@@ -153,7 +153,7 @@
project.issuetree
-
+
@@ -186,13 +186,11 @@
search
-
-
+
+
-
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
@@ -302,12 +298,12 @@
-
+
-
+
diff --git a/addons/project_issue/report/project_issue_report.py b/addons/project_issue/report/project_issue_report.py
index 70a08e2c7b4..92f170eb556 100644
--- a/addons/project_issue/report/project_issue_report.py
+++ b/addons/project_issue/report/project_issue_report.py
@@ -9,7 +9,6 @@ AVAILABLE_STATES = [
('done', 'Closed'),
('pending','Pending')
]
-
class project_issue_report(osv.osv):
_name = "project.issue.report"
_auto = False
@@ -51,9 +50,9 @@ class project_issue_report(osv.osv):
_columns = {
'name': fields.char('Year', size=64, required=False, readonly=True),
- 'user_id':fields.many2one('res.users', 'User', readonly=True),
+ 'user_id':fields.many2one('res.users', 'Responsible', readonly=True),
+ 'user_id2':fields.many2one('res.users', 'Assigned To', readonly=True),
'section_id':fields.many2one('crm.case.section', 'Section', readonly=True),
- 'nbr': fields.integer('# of Cases', readonly=True),
'state': fields.selection(AVAILABLE_STATES, 'State', size=16, readonly=True),
'avg_answers': fields.function(_get_data, string='Avg. Answers', method=True, type="integer"),
'perc_done': fields.function(_get_data, string='%Done', method=True, type="float"),
@@ -65,23 +64,30 @@ class project_issue_report(osv.osv):
('09', 'September'), ('10', 'October'),\
('11', 'November'), ('12', 'December')], 'Month', readonly=True),
'company_id': fields.many2one('res.company', 'Company', readonly=True),
- 'create_date': fields.datetime('Create Date', readonly=True),
'day': fields.char('Day', size=128, readonly=True),
+ 'opening_date': fields.date('Opening Date', readonly=True),
+ 'creation_date': fields.date('Creation Date', readonly=True),
+ 'date_closed': fields.date('Closed Date', readonly=True),
'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'project.issue')]"),
'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('object_id.model', '=', 'project.issue')]"),
'nbr': fields.integer('# of Issues', readonly=True),
+ 'working_hours_open': fields.float('# Working Open Hours', readonly=True),
+ 'working_hours_close': fields.float('# Working Closing Hours', readonly=True),
+ 'delay_open': fields.float('Avg opening Delay', digits=(16,2), readonly=True, group_operator="avg",
+ help="Number of Days to close the project issue"),
'delay_close': fields.float('Avg Closing Delay', digits=(16,2), readonly=True, group_operator="avg",
help="Number of Days to close the project issue"),
'company_id' : fields.many2one('res.company', 'Company'),
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
'project_id':fields.many2one('project.project', 'Project',readonly=True),
- 'type_id': fields.many2one('crm.case.resource.type', 'Type', domain="[('object_id.model', '=', 'project.issue')]"),
- 'date_closed': fields.datetime('Close Date', readonly=True),
+ 'type_id': fields.many2one('crm.case.resource.type', 'Version', domain="[('object_id.model', '=', 'project.issue')]"),
+ 'user_id2losed': fields.date('Close Date', readonly=True),
'assigned_to' : fields.many2one('res.users', 'Assigned to',readonly=True),
'partner_id': fields.many2one('res.partner','Partner',domain="[('object_id.model', '=', 'project.issue')]"),
'canal_id': fields.many2one('res.partner.canal', 'Channel',readonly=True),
'task_id': fields.many2one('project.task', 'Task',domain="[('object_id.model', '=', 'project.issue')]" )
}
+
def init(self, cr):
tools.drop_view_if_exists(cr, 'project_issue_report')
cr.execute("""
@@ -91,51 +97,60 @@ class project_issue_report(osv.osv):
to_char(c.create_date, 'YYYY') as name,
to_char(c.create_date, 'MM') as month,
to_char(c.create_date, 'YYYY-MM-DD') as day,
+ to_char(c.date_open, 'YYYY-MM-DD') as opening_date,
+ to_char(c.create_date, 'YYYY-MM-DD') as creation_date,
c.state,
c.user_id,
+ c.working_hours_open,
+ c.working_hours_close,
c.section_id,
c.categ_id,
c.stage_id,
- to_char(c.date_closed, 'YYYY/mm/dd') as date_closed,
- u.company_id as company_id,
+ to_char(c.date_closed, 'YYYY-mm-dd') as date_closed,
+ c.company_id as company_id,
c.priority as priority,
c.project_id as project_id,
c.type_id as type_id,
- count(*) as nbr,
+ (select 1) as nbr,
c.assigned_to,
c.partner_id,
c.canal_id,
c.task_id,
date_trunc('day',c.create_date) as create_date,
+ avg(extract('epoch' from (c.date_open-c.create_date)))/(3600*24) as delay_open,
avg(extract('epoch' from (c.date_closed-c.create_date)))/(3600*24) as delay_close
from
project_issue c
- left join
- res_users u on (c.id = u.id)
+ where c.categ_id in (select res_id from ir_model_data where name='bug_categ')
group by
to_char(c.create_date, 'YYYY'),
to_char(c.create_date, 'MM'),
to_char(c.create_date, 'YYYY-MM-DD'),
c.state,
+ to_char(c.date_open, 'YYYY-MM-DD'),
+ to_char(c.date_closed, 'YYYY-mm-dd'),
c.user_id,
c.section_id,
c.categ_id,
c.stage_id,
- c.date_closed,
- u.company_id,
+ c.company_id,
c.priority,
+ c.working_hours_open,
+ c.working_hours_close,
c.project_id,
+ to_char(c.date_closed, 'YYYY-MM-DD'),
c.type_id,
+ c.working_hours_open,
+ c.working_hours_close,
date_trunc('day',c.create_date),
c.assigned_to,
c.partner_id,
c.canal_id,
c.task_id
- )""")
-
+ )""")
project_issue_report()
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project_issue/report/project_issue_report_view.xml b/addons/project_issue/report/project_issue_report_view.xml
index adc1b3c662f..b4d0af02185 100644
--- a/addons/project_issue/report/project_issue_report_view.xml
+++ b/addons/project_issue/report/project_issue_report_view.xml
@@ -12,10 +12,9 @@
-
+
-
@@ -24,10 +23,13 @@
-
+
+
+
+
@@ -51,29 +53,25 @@
-
-
-
-
-
-
-
+
+
-
-
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
@@ -179,7 +154,7 @@
project.issue.reportformgraph,tree
- {"search_default_This Month":1,"search_default_User":1,"search_default_user_id":uid,'group_by_no_leaf':1,'group_by':[]}
+ {'search_default_This Month':1,'search_default_project':1,'group_by_no_leaf':1,'group_by':[]}
diff --git a/addons/project_issue/security/ir.model.access.csv b/addons/project_issue/security/ir.model.access.csv
index 811387ed55e..2a0b1f24bce 100755
--- a/addons/project_issue/security/ir.model.access.csv
+++ b/addons/project_issue/security/ir.model.access.csv
@@ -1,3 +1,11 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
-"access_project_issue","project.issue","model_project_issue","crm.group_crm_manager",1,1,1,1
-"access_project_issue_report","project.issue.report","model_project_issue_report","crm.group_crm_manager",1,0,0,0
+"access_project_issue_all","project.issue","model_project_issue","project.group_project_manager",1,1,1,1
+"access_project_issue","project.issue","model_project_issue","project_issue.group_project_supporter",1,1,1,1
+"access_project_issue_report_all","project.issue.report","model_project_issue_report","project.group_project_manager",1,1,1,1
+"access_project_issue_report","project.issue.report","model_project_issue_report","project_issue.group_project_supporter",1,1,1,1
+"access_crm_case_categ_id","crm.case.categ","crm.model_crm_case_categ","project.group_project_manager",1,1,1,1
+"access_crm_case_categ_supp","crm.case.categ","crm.model_crm_case_categ","project_issue.group_project_supporter",1,0,0,0
+"access_crm_case_resource_type_project","crm_case_resource_type manager","crm.model_crm_case_resource_type","project.group_project_manager",1,1,1,1
+"access_crm_case_resource_supp","crm_case_resource_type manager","crm.model_crm_case_resource_type","project_issue.group_project_supporter",1,0,0,0
+"access_crm_case_stage_project","crm.case.stage","crm.model_crm_case_stage","project.group_project_manager",1,1,1,1
+"access_crm_case_stage_manager_suppo","crm.case.stage","crm.model_crm_case_stage","project_issue.group_project_supporter",1,0,0,0
diff --git a/addons/project_issue/security/project_issue_security.xml b/addons/project_issue/security/project_issue_security.xml
index 4f7c16cb70b..82b6c003d91 100644
--- a/addons/project_issue/security/project_issue_security.xml
+++ b/addons/project_issue/security/project_issue_security.xml
@@ -2,12 +2,9 @@
-
- project.issue.rule.group
-
-
- ['|',('project_id','=',False),('project_id','=',user.context_project_id)]
+
+ Project / Support Manager
-
+
diff --git a/addons/project_long_term/project_long_term.py b/addons/project_long_term/project_long_term.py
index 212af8a30dc..57fbd1abb5f 100644
--- a/addons/project_long_term/project_long_term.py
+++ b/addons/project_long_term/project_long_term.py
@@ -256,115 +256,7 @@ class task(osv.osv):
_inherit = "project.task"
_columns = {
'phase_id': fields.many2one('project.phase', 'Project Phase'),
- 'occupation_rate': fields.float('Occupation Rate', help='The occupation rate fields indicates how much of his time a user is working on a task. A 100% occupation rate means the user works full time on the tasks. The ending date of a task is computed like this: Starting Date + Duration / Occupation Rate.'),
- 'planned_hours': fields.float('Planned Hours', required=True, help='Estimated time to do the task, usually set by the project manager when the task is in draft state.'),
}
- _defaults = {
- 'occupation_rate': '1'
- }
-
- def onchange_planned(self, cr, uid, ids, project, user_id=False, planned=0.0, effective=0.0, date_start=None, occupation_rate=0.0):
- result = {}
- resource = False
- resource_obj = self.pool.get('resource.resource')
- project_pool = self.pool.get('project.project')
- resource_calendar = self.pool.get('resource.calendar')
- if not project:
- return {'value' : result}
- if date_start:
- hrs = float(planned / float(occupation_rate))
- calendar_id = project_pool.browse(cr, uid, project).resource_calendar_id.id
- dt_start = mx.DateTime.strptime(date_start, '%Y-%m-%d %H:%M:%S')
- resource_id = resource_obj.search(cr, uid, [('user_id','=',user_id)])
- if resource_id:
- resource_data = resource_obj.browse(cr, uid, resource_id)[0]
- resource = resource_data.id
- hrs = planned / (float(occupation_rate) * resource_data.time_efficiency)
- if resource_data.calendar_id.id:
- calendar_id = resource_data.calendar_id.id
- work_times = resource_calendar.interval_get(cr, uid, calendar_id, dt_start, hrs or 0.0, resource or False)
- if work_times:
- result['date_end'] = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S')
- result['remaining_hours'] = planned - effective
- return {'value' : result}
-
- def _check_date_start(self, cr, uid, task, date_end, context={}):
- """
- Check And Compute date_end of task if change in date_start < older time.
- """
- resource_calendar_obj = self.pool.get('resource.calendar')
- resource_obj = self.pool.get('resource.resource')
- calendar_id = task.project_id.resource_calendar_id and task.project_id.resource_calendar_id.id or False
- hours = task.planned_hours / task.occupation_rate
- resource_id = resource_obj.search(cr, uid, [('user_id', '=', task.user_id.id)], context=context)
- if resource_id:
- resource = resource_obj.browse(cr, uid, resource_id[0], context=context)
- if resource.calendar_id.id:
- calendar_id = resource.calendar_id and resource.calendar_id.id or False
- hours = task.planned_hours / (float(task.occupation_rate) * resource.time_efficiency)
- work_times = resource_calendar_obj.interval_min_get(cr, uid, calendar_id, date_end, hours or 0.0, resource_id and resource_id[0] or False)
- dt_start = work_times[0][0].strftime('%Y-%m-%d %H:%M:%S')
- self.write(cr, uid, [task.id], {'date_start' : dt_start,'date_end' : date_end.strftime('%Y-%m-%d %H:%M:%S')})
-
- def _check_date_end(self, cr, uid, task, date_start, context={}):
- """
- Check And Compute date_end of task if change in date_end > older time.
- """
- resource_calendar_obj = self.pool.get('resource.calendar')
- resource_obj = self.pool.get('resource.resource')
- calendar_id = task.project_id.resource_calendar_id and task.project_id.resource_calendar_id.id or False
- hours = task.planned_hours / task.occupation_rate
- resource_id = resource_obj.search(cr,uid,[('user_id', '=', task.user_id.id)], context=context)
- if resource_id:
- resource = resource_obj.browse(cr, uid, resource_id[0], context=context)
- if resource.calendar_id.id:
- calendar_id = resource.calendar_id and resource.calendar_id.id or False
- hours = task.planned_hours / (float(task.occupation_rate) * resource.time_efficiency)
- work_times = resource_calendar_obj.interval_get(cr, uid, calendar_id, date_start, hours or 0.0, resource_id and resource_id[0] or False)
- dt_end = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S')
- self.write(cr, uid, [task.id], {'date_start': date_start.strftime('%Y-%m-%d %H:%M:%S'),'date_end' : dt_end}, context=context)
-
- def write(self, cr, uid, ids, vals, context={}):
- resource_calendar_obj = self.pool.get('resource.calendar')
- resource_obj = self.pool.get('resource.resource')
- if not context:
- context = {}
- if context.get('scheduler',False):
- return super(task, self).write(cr, uid, ids, vals, context=context)
-
- # Consider calendar and efficiency if the task is performed by a resource
- # otherwise consider the project's working calendar
- task_id = ids
- if isinstance(ids, list):
- task_id = ids[0]
- task_rec = self.browse(cr, uid, task_id, context=context)
- calendar_id = task_rec.project_id.resource_calendar_id and task_rec.project_id.resource_calendar_id.id or False
- hrs = task_rec.planned_hours / task_rec.occupation_rate
- resource_id = resource_obj.search(cr, uid, [('user_id', '=', task_rec.user_id.id)], context=context)
- if resource_id:
- resource = resource_obj.browse(cr, uid, resource_id[0], context=context)
- if resource.calendar_id.id:
- calendar_id = resource.calendar_id and resource.calendar_id.id or False
- hrs = task_rec.planned_hours / (float(task_rec.occupation_rate) * resource.time_efficiency)
-
- # Change the date_start and date_end
- # for previous and next tasks respectively based on valid condition
- if vals.get('date_start', False) and vals['date_start'] < task_rec.date_start:
- dt_start = mx.DateTime.strptime(vals['date_start'], '%Y-%m-%d %H:%M:%S')
- work_times = resource_calendar_obj.interval_get(cr, uid, calendar_id, dt_start, hrs or 0.0, resource.id or False)
- if work_times:
- vals['date_end'] = work_times[-1][1].strftime('%Y-%m-%d %H:%M:%S')
- for prv_task in task_rec.parent_ids:
- self._check_date_start(cr, uid, prv_task, dt_start)
- if vals.get('date_end', False) and vals['date_end'] > task_rec.date_end:
- dt_end = mx.DateTime.strptime(vals['date_end'], '%Y-%m-%d %H:%M:%S')
- work_times = resource_calendar_obj.interval_min_get(cr, uid, calendar_id, dt_end, hrs or 0.0, resource.id or False)
- if work_times:
- vals['date_start'] = work_times[0][0].strftime('%Y-%m-%d %H:%M:%S')
- for next_task in task_rec.child_ids:
- self._check_date_end(cr, uid, next_task, dt_end)
-
- return super(task, self).write(cr, uid, ids, vals, context=context)
task()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project_long_term/project_long_term_demo.xml b/addons/project_long_term/project_long_term_demo.xml
index 24bc7ff9438..657658eba46 100644
--- a/addons/project_long_term/project_long_term_demo.xml
+++ b/addons/project_long_term/project_long_term_demo.xml
@@ -404,7 +404,6 @@
2draft
-
@@ -424,7 +423,6 @@
2draft
-
@@ -444,7 +442,6 @@
2draft
-
@@ -464,7 +461,6 @@
2draft
-
@@ -484,7 +480,6 @@
2draft
-
@@ -504,7 +499,6 @@
2draft
-
@@ -524,7 +518,6 @@
2draft
-
@@ -544,7 +537,6 @@
2draft
-
@@ -564,7 +556,6 @@
2draft
-
@@ -584,7 +575,6 @@
2draft
-
@@ -604,7 +594,6 @@
2draft
-
@@ -623,7 +612,6 @@
2draft
-
@@ -642,7 +630,6 @@
2draft
-
@@ -661,7 +648,6 @@
2draft
-
@@ -680,7 +666,6 @@
2draft
-
@@ -699,7 +684,6 @@
2draft
-
@@ -718,7 +702,6 @@
2draft
-
@@ -737,7 +720,6 @@
2draft
-
@@ -756,7 +738,6 @@
2draft
-
@@ -776,7 +757,6 @@
2draft
-
@@ -796,7 +776,6 @@
2draft
-
@@ -816,7 +795,6 @@
2draft
-
@@ -836,7 +814,6 @@
2draft
-
@@ -856,7 +833,6 @@
2draft
-
@@ -876,7 +852,6 @@
2draft
-
@@ -897,7 +872,6 @@
2draft
-
@@ -909,4 +883,4 @@
-
\ No newline at end of file
+
diff --git a/addons/project_long_term/project_long_term_view.xml b/addons/project_long_term/project_long_term_view.xml
index e681b0da57f..cafaefa9633 100644
--- a/addons/project_long_term/project_long_term_view.xml
+++ b/addons/project_long_term/project_long_term_view.xml
@@ -2,7 +2,7 @@
-
+
# ------------------------------------------------------
# Project Resource Allocation
@@ -29,7 +29,7 @@
-
+
@@ -42,8 +42,8 @@
-
-
+
+
@@ -59,7 +59,7 @@
project.resource.allocationformtree,form
- {'search_default_resource': 1}
+ {'search_default_resource': 1}
@@ -128,7 +128,7 @@
-
+
@@ -142,11 +142,10 @@
-
-
+
@@ -157,7 +156,7 @@
-
+
@@ -223,10 +222,10 @@
-
+
-
+
@@ -245,7 +244,7 @@
project.phaseformgantt,tree,form,calendar
- {'search_default_responsible_id':uid}
+ {'search_default_responsible_id':uid}
@@ -270,32 +269,7 @@
# Project Task
# ------------------------------------------------------
-
- project.phase.task.form1
- project.task
- form
-
-
-
-
-
-
-
-
-
-
- project.phase.task.form2
- project.task
- form
-
-
-
-
-
-
-
-
-
-
-
diff --git a/addons/project_long_term/security/ir.model.access.csv b/addons/project_long_term/security/ir.model.access.csv
index 7a91ce257ed..b829675772e 100644
--- a/addons/project_long_term/security/ir.model.access.csv
+++ b/addons/project_long_term/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_project_phase","project.phase","model_project_phase",,1,1,1,1
-"access_project_resource_allocation","project.resource.allocation","model_project_resource_allocation",,1,1,1,1
+"access_project_phase","project.phase","model_project_phase",project.group_project_user,1,1,1,1
+"access_project_resource_allocation","project.resource.allocation","model_project_resource_allocation",project.group_project_user,1,1,1,1
diff --git a/addons/project_long_term/wizard/project_compute_tasks.py b/addons/project_long_term/wizard/project_compute_tasks.py
index 9f2eb707c60..0816bf3c3f1 100644
--- a/addons/project_long_term/wizard/project_compute_tasks.py
+++ b/addons/project_long_term/wizard/project_compute_tasks.py
@@ -108,7 +108,7 @@ class project_compute_tasks(osv.osv_memory):
# Dynamic Creation of tasks
i = 0
for each_task in tasks:
- hours = str(each_task.planned_hours / each_task.occupation_rate)+ 'H'
+ hours = str(each_task.planned_hours )+ 'H'
if each_task.priority in priority_dict.keys():
priorty = priority_dict[each_task.priority]
if each_task.user_id:
@@ -139,4 +139,4 @@ class project_compute_tasks(osv.osv_memory):
return {}
project_compute_tasks()
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project_long_term/wizard/project_schedule_tasks.py b/addons/project_long_term/wizard/project_schedule_tasks.py
index 8ec2d4c16e0..d4d2da82cec 100644
--- a/addons/project_long_term/wizard/project_schedule_tasks.py
+++ b/addons/project_long_term/wizard/project_schedule_tasks.py
@@ -127,7 +127,7 @@ class project_schedule_task(osv.osv_memory):
# Dynamic creation of tasks
i = 0
for each_task in tasks:
- hours = str(each_task.planned_hours / each_task.occupation_rate)+ 'H'
+ hours = str(each_task.planned_hours )+ 'H'
if each_task.priority in priority_dict.keys():
priorty = priority_dict[each_task.priority]
if each_task.user_id:
diff --git a/addons/project_messages/security/ir.model.access.csv b/addons/project_messages/security/ir.model.access.csv
index 96782d5fc82..b79a32fb2f5 100644
--- a/addons/project_messages/security/ir.model.access.csv
+++ b/addons/project_messages/security/ir.model.access.csv
@@ -1,2 +1,2 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
-"access_project_messages","project.messages","model_project_messages",,1,1,1,1
+"access_project_messages","project.messages","model_project_messages",project.group_project_user,1,1,1,1
diff --git a/addons/project_mrp/__openerp__.py b/addons/project_mrp/__openerp__.py
index ee5a94208aa..a51a95c5d16 100644
--- a/addons/project_mrp/__openerp__.py
+++ b/addons/project_mrp/__openerp__.py
@@ -47,12 +47,13 @@ automatically created via sale orders.
""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
- 'depends': ['project', 'mrp_procurement', 'sale', 'mrp_jit'],
+ 'depends': ['project', 'procurement', 'sale', 'mrp_jit'],
'init_xml': [],
'update_xml': ['project_mrp_workflow.xml',
#'process/project_mrp_process.xml',
],
'demo_xml': [],
+ 'test': ['test/project_task_procurement.yml'],
'installable': True,
'active': False,
'certificate': '0031976495453',
diff --git a/addons/project_mrp/mrp.py b/addons/project_mrp/mrp.py
index 6287ca3ad30..98b05248a66 100644
--- a/addons/project_mrp/mrp.py
+++ b/addons/project_mrp/mrp.py
@@ -22,9 +22,9 @@
from osv import fields, osv, orm
import tools
-class mrp_procurement(osv.osv):
- _name = "mrp.procurement"
- _inherit = "mrp.procurement"
+class procurement_order(osv.osv):
+ _name = "procurement.order"
+ _inherit = "procurement.order"
def action_produce_assign_service(self, cr, uid, ids, context={}):
for procurement in self.browse(cr, uid, ids):
@@ -91,7 +91,7 @@ class mrp_procurement(osv.osv):
'project_id': project_id,
},context=context)
return task_id
-mrp_procurement()
+procurement_order()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project_mrp/project_mrp.py b/addons/project_mrp/project_mrp.py
index 8029327022d..b606bbfe8fa 100644
--- a/addons/project_mrp/project_mrp.py
+++ b/addons/project_mrp/project_mrp.py
@@ -26,7 +26,7 @@ class project_task(osv.osv):
_name = "project.task"
_inherit = "project.task"
_columns = {
- 'procurement_id': fields.many2one('mrp.procurement', 'Procurement', ondelete='set null')
+ 'procurement_id': fields.many2one('procurement.order', 'Procurement', ondelete='set null')
}
def do_close(self, cr, uid, ids, *args):
@@ -35,7 +35,7 @@ class project_task(osv.osv):
for task in tasks:
if task.procurement_id:
wf_service = netsvc.LocalService("workflow")
- wf_service.trg_validate(uid, 'mrp.procurement', task.procurement_id.id, 'subflow.done', cr)
+ wf_service.trg_validate(uid, 'procurement.order', task.procurement_id.id, 'subflow.done', cr)
return res
def do_cancel(self, cr, uid, ids, *args):
@@ -44,7 +44,7 @@ class project_task(osv.osv):
for task in tasks:
if task.procurement_id:
wf_service = netsvc.LocalService("workflow")
- wf_service.trg_validate(uid, 'mrp.procurement', task.procurement_id.id, 'subflow.cancel', cr)
+ wf_service.trg_validate(uid, 'procurement.order', task.procurement_id.id, 'subflow.cancel', cr)
return True
project_task()
diff --git a/addons/project_mrp/project_mrp_workflow.xml b/addons/project_mrp/project_mrp_workflow.xml
index 43217d69f83..cd242e7f699 100644
--- a/addons/project_mrp/project_mrp_workflow.xml
+++ b/addons/project_mrp/project_mrp_workflow.xml
@@ -1,9 +1,9 @@
-
-
-
+
+
+ subflow.done
diff --git a/addons/project_mrp/security/ir.model.access.csv b/addons/project_mrp/security/ir.model.access.csv
index 407ab3716a0..7c6e2a7a30c 100644
--- a/addons/project_mrp/security/ir.model.access.csv
+++ b/addons/project_mrp/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_mrp_procurement_project_user","mrp.procurement project_user","model_mrp_procurement","project.group_project_user",1,1,1,1
-"access_mrp_procurement_project_manager","mrp.procurement project_manager","model_mrp_procurement","project.group_project_manager",1,1,1,1
+"access_procurement_project_user","procurement.order project_user","model_procurement_order","project.group_project_user",1,1,1,1
+"access_procurement_project_manager","procurement.order project_manager","model_procurement_order","project.group_project_manager",1,1,1,1
diff --git a/addons/project_mrp/test/project_task_procurement.yml b/addons/project_mrp/test/project_task_procurement.yml
new file mode 100644
index 00000000000..50bc74f82ae
--- /dev/null
+++ b/addons/project_mrp/test/project_task_procurement.yml
@@ -0,0 +1,75 @@
+-
+ In order to test project_mrp module with OpenERP I want to create sale orders
+ with product type 'service' so when procurement runs one task is created.
+-
+ I create record for a service type product.
+-
+ !record {model: product.product, id: product_product_partnerstraining0}:
+ categ_id: product.product_category_7
+ cost_method: standard
+ mes_type: fixed
+ name: Partners Training
+ procure_method: make_to_order
+ supply_method: produce
+ type: service
+ uom_id: product.uom_day
+ uom_po_id: product.uom_day
+ warranty: 0.0
+-
+ I create a sale order for product Partners Training which has type 'Service'.
+-
+ !record {model: sale.order, id: sale_order_so0}:
+ date_order: '2010-05-21'
+ invoice_quantity: order
+ name: SO006
+ order_policy: manual
+ partner_id: base.res_partner_asus
+ partner_invoice_id: base.res_partner_address_tang
+ partner_order_id: base.res_partner_address_tang
+ partner_shipping_id: base.res_partner_address_tang
+ order_line:
+ - state: draft
+ delay: 7.0
+ name: Partners Training
+ price_unit: 1.0
+ product_id: product_product_partnerstraining0
+ product_uom: product.uom_day
+ product_uom_qty: 5.0
+ th_weight: 0.0
+ type: make_to_order
+ picking_policy: direct
+ pricelist_id: product.list0
+ shop_id: sale.shop
+ user_id: base.user_demo
+-
+ I confirm this sale order.
+-
+ !workflow {model: sale.order, action: order_confirm, ref: sale_order_so0}
+-
+ I check the procurements.
+-
+ !python {model: procurement.order}: |
+ from tools.translate import _
+ orderline_obj = self.pool.get('sale.order.line')
+ line_ids = orderline_obj.search(cr, uid, [('order_id','=', ref('sale_order_so0'))])
+ orders = orderline_obj.browse(cr, uid, line_ids)
+ proc_ids = map(lambda x: x.procurement_id.id, orders)
+ assert proc_ids, _('No Procurements!')
+-
+ The scheduler runs.
+-
+ !function {model: procurement.order, name: run_scheduler}:
+ - model: procurement.order
+ search: "[('state','=','confirmed')]"
+-
+ Now I check the tasks.
+-
+ I see that one task is created for my sale order.
+-
+ !python {model: project.task}: |
+ from tools.translate import _
+ order_obj = self.pool.get('sale.order')
+ order = order_obj.browse(cr, uid, ref('sale_order_so0'))
+ task_id = self.search(cr, uid, [('project_id.name','=', order.name)])
+ assert task_id, _('No Task is created!')
+
\ No newline at end of file
diff --git a/addons/project_planning/project_planning_view.xml b/addons/project_planning/project_planning_view.xml
index fd9d586f21e..d7d2880714c 100644
--- a/addons/project_planning/project_planning_view.xml
+++ b/addons/project_planning/project_planning_view.xml
@@ -164,10 +164,10 @@
-
-
-
-
+
+
+
+
diff --git a/addons/purchase/__openerp__.py b/addons/purchase/__openerp__.py
index 46d7c3296b9..8d3d213a91d 100644
--- a/addons/purchase/__openerp__.py
+++ b/addons/purchase/__openerp__.py
@@ -31,10 +31,10 @@
""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
- 'depends': ['base', 'account', 'stock', 'process', 'mrp_procurement'],
+ 'depends': ['base', 'account', 'stock', 'process', 'procurement'],
'init_xml': [],
'update_xml': [
-
+
'security/purchase_security.xml',
'security/ir.model.access.csv',
'purchase_workflow.xml',
diff --git a/addons/purchase/i18n/et.po b/addons/purchase/i18n/et.po
index 5123b27b446..072ed95902f 100644
--- a/addons/purchase/i18n/et.po
+++ b/addons/purchase/i18n/et.po
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
-"PO-Revision-Date: 2009-11-18 06:10+0000\n"
-"Last-Translator: Fabien (Open ERP) \n"
+"PO-Revision-Date: 2010-06-09 22:18+0000\n"
+"Last-Translator: lyyser \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-04-17 03:58+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:42+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: purchase
@@ -606,7 +606,7 @@ msgstr "Kättetoimetamine ja arved"
#. module: purchase
#: field:purchase.order,date_order:0
msgid "Date"
-msgstr ""
+msgstr "Kuupäev"
#. module: purchase
#: help:purchase.order,origin:0
@@ -666,7 +666,7 @@ msgstr "Kui ostukorraldus on heaks kiidetud, loob see pakkimise nimekirja."
#. module: purchase
#: view:purchase.order.line:0
msgid "History"
-msgstr ""
+msgstr "Ajalugu"
#. module: purchase
#: field:purchase.order,state:0
@@ -893,4 +893,4 @@ msgstr "Peale ostukorralduse heaks kiitmist läheb see kliendiarveks"
#. module: purchase
#: view:purchase.order.line:0
msgid "Stock Moves"
-msgstr ""
+msgstr "Lao liikumised"
diff --git a/addons/purchase/i18n/pl.po b/addons/purchase/i18n/pl.po
index af8ed99ffbe..bc24632a606 100644
--- a/addons/purchase/i18n/pl.po
+++ b/addons/purchase/i18n/pl.po
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-05 03:35+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:42+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: purchase
diff --git a/addons/purchase/partner_view.xml b/addons/purchase/partner_view.xml
index 58594493643..06ba97079eb 100644
--- a/addons/purchase/partner_view.xml
+++ b/addons/purchase/partner_view.xml
@@ -9,8 +9,8 @@
36
-
-
+
+
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 443a279e3f2..3958743bfcf 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -65,7 +65,6 @@ class purchase_order(osv.osv):
res[order.id]['amount_tax']=cur_obj.round(cr, uid, cur, val)
res[order.id]['amount_untaxed']=cur_obj.round(cr, uid, cur, val1)
res[order.id]['amount_total']=res[order.id]['amount_untaxed'] + res[order.id]['amount_tax']
- print res
return res
def _set_minimum_planned_date(self, cr, uid, ids, name, value, arg, context):
@@ -168,7 +167,7 @@ class purchase_order(osv.osv):
'state': fields.selection([('draft', 'Request for Quotation'), ('wait', 'Waiting'), ('confirmed', 'Waiting Supplier Ack'), ('approved', 'Approved'),('except_picking', 'Shipping Exception'), ('except_invoice', 'Invoice Exception'), ('done', 'Done'), ('cancel', 'Cancelled')], 'State', readonly=True, help="The state of the purchase order or the quotation request. A quotation is a purchase order in a 'Draft' state. Then the order has to be confirmed by the user, the state switch to 'Confirmed'. Then the supplier must confirm the order to change the state to 'Approved'. When the purchase order is paid and received, the state becomes 'Done'. If a cancel action occurs in the invoice or in the reception of goods, the state becomes in exception.", select=True),
'order_line': fields.one2many('purchase.order.line', 'order_id', 'Order Lines', states={'approved':[('readonly',True)],'done':[('readonly',True)]}),
'validator' : fields.many2one('res.users', 'Validated by', readonly=True),
- 'notes': fields.text('Notes', translate=True),
+ 'notes': fields.text('Notes'),
'invoice_id': fields.many2one('account.invoice', 'Invoice', readonly=True),
'picking_ids': fields.one2many('stock.picking', 'purchase_id', 'Picking List', readonly=True, help="This is the list of picking list that have been generated for this purchase"),
'shipped':fields.boolean('Received', readonly=True, select=True),
@@ -273,6 +272,8 @@ class purchase_order(osv.osv):
todo.append(line.id)
current_name = self.name_get(cr, uid, ids)[0][1]
self.pool.get('purchase.order.line').action_confirm(cr, uid, todo, context)
+ message = _('confirm Order') + " ' " + po.name
+ self.log(cr,uid,po,message)
for id in ids:
self.write(cr, uid, [id], {'state' : 'confirmed', 'validator' : uid})
return True
@@ -428,6 +429,7 @@ class purchase_order(osv.osv):
'product_uom': order_line.product_uom.id,
'product_uos': order_line.product_uom.id,
'date_planned': order_line.date_planned,
+ 'date_expected': order_line.date_planned,
'location_id': loc_id,
'location_dest_id': dest,
'picking_id': picking_id,
@@ -591,7 +593,7 @@ class purchase_order_line(osv.osv):
'move_dest_id': fields.many2one('stock.move', 'Reservation Destination', ondelete='set null'),
'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Purchase Price')),
'price_subtotal': fields.function(_amount_line, method=True, string='Subtotal', digits_compute= dp.get_precision('Purchase Price')),
- 'notes': fields.text('Notes', translate=True),
+ 'notes': fields.text('Notes'),
'order_id': fields.many2one('purchase.order', 'Order Reference', select=True, required=True, ondelete='cascade'),
'account_analytic_id':fields.many2one('account.analytic.account', 'Analytic Account',),
'company_id': fields.related('order_id','company_id',type='many2one',relation='res.company',string='Company'),
@@ -633,7 +635,7 @@ class purchase_order_line(osv.osv):
prod= self.pool.get('product.product').browse(cr, uid,product)
lang=False
if partner_id:
- lang=self.pool.get('res.partner').read(cr, uid, partner_id)['lang']
+ lang=self.pool.get('res.partner').read(cr, uid, partner_id, ['lang'])['lang']
context={'lang':lang}
context['partner_id'] = partner_id
@@ -698,8 +700,8 @@ class purchase_order_line(osv.osv):
return True
purchase_order_line()
-class mrp_procurement(osv.osv):
- _inherit = 'mrp.procurement'
+class procurement_order(osv.osv):
+ _inherit = 'procurement.order'
_columns = {
'purchase_id': fields.many2one('purchase.order', 'Latest Requisition'),
}
@@ -728,6 +730,7 @@ class mrp_procurement(osv.osv):
res_id = procurement.move_id.id
partner = procurement.product_id.seller_ids[0].name
partner_id = partner.id
+ partner_rec = procurement.product_id.seller_ids[0]
address_id = partner_obj.address_get(cr, uid, [partner_id], ['delivery'])['delivery']
pricelist_id = partner.property_product_pricelist_purchase.id
@@ -735,13 +738,13 @@ class mrp_procurement(osv.osv):
qty = uom_obj._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, uom_id)
if procurement.product_id.seller_ids[0].qty:
- qty = max(qty,procurement.product_id.seller_ids[0].qty)
+ qty = max(qty,partner_rec.qty)
price = pricelist_obj.price_get(cr, uid, [pricelist_id], procurement.product_id.id, qty, False, {'uom': uom_id})[pricelist_id]
newdate = DateTime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S')
newdate = newdate - DateTime.RelativeDateTime(days=company.po_lead)
- newdate = newdate - procurement.product_id.seller_ids[0].delay
+ newdate = newdate - partner_rec.delay
#Passing partner_id to context for purchase order line integrity of Line name
context.update({'lang': partner.lang, 'partner_id': partner_id})
@@ -777,7 +780,7 @@ class mrp_procurement(osv.osv):
res[procurement.id] = purchase_id
self.write(cr, uid, [procurement.id], {'state': 'running', 'purchase_id': purchase_id})
return res
-mrp_procurement()
+procurement_order()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml
index 10c5ccd9749..8086a169d9d 100644
--- a/addons/purchase/purchase_view.xml
+++ b/addons/purchase/purchase_view.xml
@@ -3,7 +3,7 @@
-
@@ -21,8 +21,7 @@
parent="base.menu_purchase_root" sequence="4"/>
-
+
-
+
-
+
@@ -160,7 +159,7 @@
-
+
@@ -234,7 +233,13 @@
+
+
+
+
+
@@ -244,17 +249,14 @@
-
-
-
-
-
-
-
+
+
+
+
-
-
+
+
@@ -287,7 +289,7 @@
-
+
@@ -314,7 +316,7 @@
src_model="product.product"
groups="base.group_extended"/>
- mrp.procurement.form.inherit
- mrp.procurement
-
- form
-
-
-
-
-
+ procurement.order.form.inherit
+ procurement.order
+
+ form
+
+
+
+
+
diff --git a/addons/purchase/purchase_workflow.xml b/addons/purchase/purchase_workflow.xml
index d7684be1875..d14530e5f48 100644
--- a/addons/purchase/purchase_workflow.xml
+++ b/addons/purchase/purchase_workflow.xml
@@ -180,7 +180,7 @@
-
+ buysubflow
@@ -188,20 +188,20 @@
-
+ check_buy()
-
+ subflow.delivery_done
-
+ subflow.cancel
diff --git a/addons/purchase/report/purchase_report.py b/addons/purchase/report/purchase_report.py
index cf177319ea5..d5688e5bd22 100644
--- a/addons/purchase/report/purchase_report.py
+++ b/addons/purchase/report/purchase_report.py
@@ -31,7 +31,7 @@ class purchase_report(osv.osv):
_description = "Purchases Orders"
_auto = False
_columns = {
- 'date': fields.date('Date', readonly=True),
+ 'date': fields.date('Order Date', readonly=True),
'name': fields.char('Year',size=64,required=False, readonly=True),
'day': fields.char('Day', size=128, readonly=True),
'state': fields.selection([
@@ -44,28 +44,26 @@ class purchase_report(osv.osv):
('done','Done'),
('cancel','Cancel')
], 'Order State', readonly=True),
- 'invoice_method': fields.selection([
- ('manual','Manual'),
- ('order','From Order'),
- ('picking','From Picking')
- ],'Invoicing Control', readonly=True),
'product_id':fields.many2one('product.product', 'Product', readonly=True),
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', readonly=True),
'location_id': fields.many2one('stock.location', 'Destination', readonly=True),
- 'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position',readonly=True),
'partner_id':fields.many2one('res.partner', 'Partner', readonly=True),
'partner_address_id':fields.many2one('res.partner.address', 'Address Contact Name', readonly=True),
'dest_address_id':fields.many2one('res.partner.address', 'Dest. Address Contact Name',readonly=True),
'pricelist_id':fields.many2one('product.pricelist', 'Pricelist', readonly=True),
'date_approve':fields.date('Date Approved', readonly=True),
'expected_date':fields.date('Expected Date', readonly=True),
- 'validator' : fields.many2one('res.users', 'Validated by', readonly=True),
+ 'validator' : fields.many2one('res.users', 'Validated By', readonly=True),
'company_id':fields.many2one('res.company', 'Company', readonly=True),
'user_id':fields.many2one('res.users', 'Responsible', readonly=True),
+ 'delay':fields.float('Days to Validate', digits=(16,2), readonly=True, group_operator="avg"),
+ 'delay_pass':fields.float('Days to Deliver', digits=(16,2), readonly=True, group_operator="avg"),
'quantity': fields.float('# of Products', readonly=True),
'price_total': fields.float('Total Price', readonly=True),
- 'price_average': fields.float('Average Price', readonly=True),
- 'nbr': fields.integer('# of Lines', readonly=True),
+ 'price_average': fields.float('Unit Price', readonly=True, group_operator="avg"),
+ 'negociation': fields.float('Purchase-Standard Price', readonly=True, group_operator="avg"),
+ 'price_standard': fields.float('Products Value', readonly=True, group_operator="sum"),
+ 'nbr': fields.integer('# of PO Lines', readonly=True),
'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'), ('05','May'), ('06','June'),
('07','July'), ('08','August'), ('09','September'), ('10','October'), ('11','November'), ('12','December')],'Month',readonly=True),
@@ -90,26 +88,34 @@ class purchase_report(osv.osv):
s.validator,
s.warehouse_id as warehouse_id,
s.partner_id as partner_id,
- s.fiscal_position,
s.create_uid as user_id,
s.company_id as company_id,
- s.invoice_method,
l.product_id,
s.location_id as location_id,
sum(l.product_qty*u.factor) as quantity,
+ extract(epoch from age(s.date_approve,s.date_order))/(24*60*60)::decimal(16,2) as delay,
+ extract(epoch from age(l.date_planned,s.date_order))/(24*60*60)::decimal(16,2) as delay_pass,
count(*) as nbr,
- sum(l.product_qty*l.price_unit) as price_total,
+ (l.price_unit*l.product_qty*u.factor)::decimal(16,2) as price_total,
+ avg(100.0 * (l.price_unit*l.product_qty*u.factor) / (t.standard_price*l.product_qty*u.factor))::decimal(16,2) as negociation,
+ sum(t.standard_price*l.product_qty*u.factor)::decimal(16,2) as price_standard,
(sum(l.product_qty*l.price_unit)/sum(l.product_qty*u.factor))::decimal(16,2) as price_average
from purchase_order s
left join purchase_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)
where l.product_id is not null
group by
s.company_id,
s.create_uid,
s.partner_id,
+ l.product_qty,
+ u.factor,
s.location_id,
+ l.price_unit,
s.date_approve,
+ l.date_planned,
date_trunc('day',s.minimum_planned_date),
s.partner_address_id,
s.pricelist_id,
@@ -121,74 +127,8 @@ class purchase_report(osv.osv):
to_char(s.date_order, 'MM'),
to_char(s.date_order, 'YYYY-MM-DD'),
s.state,
- s.warehouse_id,
- s.fiscal_position,
- s.invoice_method
+ s.warehouse_id
)
""")
purchase_report()
-class purchase_order_qty_amount(osv.osv):
- _name = "purchase.order.qty.amount"
- _description = "Quantity and amount per month"
- _auto = False
- _columns = {
- 'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'), ('05','May'), ('06','June'),
- ('07','July'), ('08','August'), ('09','September'), ('10','October'), ('11','November'), ('12','December')],'Month',readonly=True),
- 'total_qty' : fields.float('Total Qty'),
- 'total_amount' : fields.float('Total Amount'),
-
- }
- def init(self, cr):
- tools.sql.drop_view_if_exists(cr, 'purchase_order_qty_amount')
- cr.execute("""
- create or replace view purchase_order_qty_amount as (
- select
- min(id) as id,
- to_char(create_date, 'MM') as month,
- sum(product_qty) as total_qty,
- sum(price_unit*product_qty) as total_amount
- from
- purchase_order_line
- where
- to_char(create_date,'YYYY') = to_char(current_date,'YYYY')
- group by
- to_char(create_date, 'MM')
-
- )
- """)
-purchase_order_qty_amount()
-
-class purchase_order_by_user(osv.osv):
- _name = "purchase.order.by.user"
- _description = "Purchase Order by user per month"
- _auto = False
- _columns = {
- 'name' : fields.char('User',size=64,required=True),
- 'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'), ('05','May'), ('06','June'),
- ('07','July'), ('08','August'), ('09','September'), ('10','October'), ('11','November'), ('12','December')],'Month',readonly=True),
- 'nbr' : fields.integer('Total Orders'),
-
- }
- _order = 'name desc'
- def init(self, cr):
- tools.sql.drop_view_if_exists(cr, 'purchase_order_by_user')
- cr.execute("""
- create or replace view purchase_order_by_user as (
- select
- min(po.id) as id,
- rs.name as name,
- count(po.id) as nbr,
- to_char(po.date_order, 'MM') as month
- from
- purchase_order as po,res_users as rs
- where
- po.create_uid = rs.id
- group by
- rs.name,po.date_order
-
- )
- """)
-purchase_order_by_user()
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
diff --git a/addons/purchase/report/purchase_report_view.xml b/addons/purchase/report/purchase_report_view.xml
index 8fb7836468d..b2bdf840c3d 100644
--- a/addons/purchase/report/purchase_report_view.xml
+++ b/addons/purchase/report/purchase_report_view.xml
@@ -1,14 +1,13 @@
-
+ product.month.graphpurchase.reportgraph
-
@@ -20,28 +19,28 @@
tree
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
-
-
-
-
+
+
+
+
+
+
+
+
@@ -53,87 +52,61 @@
-
-
-
+
+
-
-
-
-
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -144,77 +117,21 @@
purchase.reportformtree,graph
-
- {'search_default_month':1,'search_default_Responsible':1,'group_by_no_leaf':1,'group_by':[]}
+ {'search_default_month':1,'search_default_group_partner_id':1,'search_default_group_product_id': 1, 'search_default_orders': 1, 'group_by_no_leaf':1,'group_by':[]}
-
- purchase.order.qty.amount.graph
- purchase.order.qty.amount
- graph
-
-
-
-
-
-
-
-
+
+ Receptions Analysis
+ report.stock.move
+ form
+ tree,graph
+ {'search_default_month':1, 'search_default_group_product':1, 'search_default_group_partner':1, 'search_default_done':1, 'search_default_in': 1, 'group_by':[], 'group_by_no_leaf':1}
+
+
-
- purchase.order.qty.amount.tree
- purchase.order.qty.amount
- tree
-
-
-
-
-
-
-
-
-
- Total Qty and Amount by month
- purchase.order.qty.amount
- form
- graph,tree
-
-
-
- purchase.order.by.user.graph
- purchase.order.by.user
- graph
-
-
-
-
-
-
-
-
-
-
- purchase.order.by.user.tree
- purchase.order.by.user
- tree
-
-
-
-
-
-
-
-
-
-
- Total Orders by User per month
- purchase.order.by.user
- form
- graph,tree
-
diff --git a/addons/purchase/security/ir.model.access.csv b/addons/purchase/security/ir.model.access.csv
index 9b0f8bc184e..c6a09d5d728 100644
--- a/addons/purchase/security/ir.model.access.csv
+++ b/addons/purchase/security/ir.model.access.csv
@@ -17,3 +17,10 @@
"access_stock_picking_purchase_user_manager","stock.picking","stock.model_stock_picking","purchase.group_purchase_manager",1,1,1,1
"access_stock_move_purchase_user_manager","stock.move","stock.model_stock_move","purchase.group_purchase_manager",1,1,1,1
"access_account_tax_purchase_user_manager","account.tax","account.model_account_tax","purchase.group_purchase_manager",1,0,0,0
+"access_product_product_purchase_user","product.product.purchase.user","product.model_product_product","group_purchase_user",1,0,0,0
+"access_account_invoice_purchase","account_invoice purchase","account.model_account_invoice","group_purchase_user",1,1,1,1
+"access_account_invoice_line_purchase","account_invoice.line purchase","account.model_account_invoice_line","group_purchase_user",1,1,1,1
+"access_account_fiscal_position_purchase_user","account.fiscal.position purchase","account.model_account_fiscal_position","group_purchase_user",1,0,0,0
+"access_account_sequence_fiscalyear_purchase_user","account.sequence.fiscalyear purchase","account.model_account_sequence_fiscalyear","group_purchase_user",1,1,1,1
+"access_res_partner_purchase_user","res.partner purchase","base.model_res_partner","group_purchase_user",1,0,0,0
+"access_res_partner_address_purchase_user","res.partner.address purchase","base.model_res_partner_address","group_purchase_user",1,0,0,0
diff --git a/addons/purchase/test/purchase_from_manual.yml b/addons/purchase/test/purchase_from_manual.yml
index e0b1a8b806c..e7a608b7557 100644
--- a/addons/purchase/test/purchase_from_manual.yml
+++ b/addons/purchase/test/purchase_from_manual.yml
@@ -1,5 +1,5 @@
-
- In order to test the purchase flow,I start by creating a new product 'iPod'
+ In order to test the purchase flow,I start by creating a new product 'iPod'
-
!record {model: product.product, id: product_product_ipod0}:
categ_id: 'product.product_category_3'
@@ -22,14 +22,14 @@
weight: 0.0
weight_net: 0.0
-
- In order to test the purchase flow,I create a new record where "invoice_method" is From Manual
+ In order to test the purchase flow,I create a new record where "invoice_method" is From Manual
-
- Creating an purchase.order record
+ I create purchase order for iPod.
-
!record {model: purchase.order, id: purchase_order_po1}:
company_id: base.main_company
date_order: '2010-05-11'
- invoice_method: order
+ invoice_method: manual
location_id: stock.stock_location_stock
name: PO00010
order_line:
@@ -44,26 +44,21 @@
partner_id: base.res_partner_4
pricelist_id: purchase.list0
-
- Initially purchase order is in the draft state
+ Initially purchase order is in the draft state
-
!assert {model: purchase.order, id: purchase_order_po1}:
- state == 'draft'
-
- Then an order is confirmed by clicking on the "Confirm Purchase Order" button
--
- !python {model: purchase.order}: |
- self.wkf_confirm_order(cr, uid, [ref("purchase_order_po1")])
--
- Performing a workflow action purchase_confirm on module purchase.order
+ I confirm the purchase order.
-
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_po1}
-
- I check that the order which was initially in the draft state has transit to confirm state.
+ I check that the order which was initially in the draft state has transit to confirm state.
-
!assert {model: purchase.order, id: purchase_order_po1}:
- state == 'confirmed'
-
- I check that an entry gets created in the "Lines to Invoice" of Invoice Control on the basis of purchase order line
+ I check that an entry gets created in the "Lines to Invoice" of Invoice Control on the basis of purchase order line
-
!python {model: purchase.order}: |
from tools.translate import _
@@ -72,14 +67,14 @@
search_ids=pur_line.search(cr, uid, [('order_id', '=', pur_order_obj.name) ])
assert search_ids, _('Purchase order line is not created!')
-
- To check that wizard "Create Invoices" gets opened
+ To check that wizard "Create Invoices" gets opened
-
- Creating a purchase.order.line_invoice record
+ I create purchase order line invoice entry.
-
!record {model: purchase.order.line_invoice, id: purchase_order_line_invoice_0}:
{}
-
- Performing an osv_memory action makeInvoices on module purchase.order.line_invoice
+ I create invoice for products in the purchase order.
-
!python {model: purchase.order.line_invoice}: |
pur_obj=self.pool.get('purchase.order')
@@ -89,7 +84,7 @@
ids.append(line.id)
self.makeInvoices(cr, uid, [1], context={'active_ids': ids})
-
- I check that invoice gets created
+ I check that invoice gets created.
-
!python {model: purchase.order}: |
from tools.translate import _
@@ -98,7 +93,7 @@
search_ids=pur_line.search(cr, uid, [('order_id', '=', pur_order_obj.name),('invoiced', '=', '1') ])
assert search_ids, _('Invoice is not created!')
-
- I check that a record gets created in the Pending Invoices
+ I check that a record gets created in the Pending Invoices.
-
!python {model: purchase.order}: |
from tools.translate import _
@@ -107,33 +102,28 @@
ids = account_obj.search(cr, uid, [('origin', '=', pur_id1.name)])
assert ids, _('Pending Invoice is not created!')
-
- Then an order is approved by clicking on the "Approved by Supplier" button
--
- !python {model: purchase.order}: |
- self.wkf_approve_order(cr, uid, [ref("purchase_order_po1")])
--
- Performing a workflow action purchase_approve on module purchase.order
+ Supplier approve the purchase order.
-
!workflow {model: purchase.order, action: purchase_approve, ref: purchase_order_po1}
-
- I check that the order which was initially in the confirmed state has transit to approved state.
+ I check that the order which was initially in the confirmed state has transit to approved state.
-
!assert {model: purchase.order, id: purchase_order_po1}:
- state == 'approved'
-
- I check that date_approve field of Delivery&Invoices gets bind with the date on which it has been approved
+ I check that date_approve field of Delivery&Invoices gets bind with the date on which it has been approved.
-
!python {model: purchase.order}: |
pur_id=self.browse(cr, uid, ref("purchase_order_po1"))
assert(pur_id.date_approve)
-
- I check that an entry gets created in the stock.picking
+ I check that an entry gets created in the stock pickings.
-
!python {model: purchase.order}: |
pur_id=self.browse(cr, uid, ref("purchase_order_po1"))
assert(pur_id.picking_ids)
-
- I check that an entry gets created in the stock.move
+ I check that an entry gets created in the stock moves.
-
!python {model: purchase.order}: |
from tools.translate import _
@@ -145,4 +135,4 @@
search_id = move_obj.search(cr, uid, [('picking_id', '=', pick_id.name)])
assert search_id, _('No Incoming Product!')
-
- I check that Traceability moves are created
+ I check that Traceability moves are created.
diff --git a/addons/purchase/test/purchase_from_order.yml b/addons/purchase/test/purchase_from_order.yml
index 3e83fc7dfda..a13c687c4a5 100644
--- a/addons/purchase/test/purchase_from_order.yml
+++ b/addons/purchase/test/purchase_from_order.yml
@@ -1,5 +1,5 @@
-
- In order to test the purchase flow,I start by creating a new product 'iPod'
+ In order to test the purchase flow,I start by creating a new product 'iPod'
-
!record {model: product.product, id: product_product_ipod0}:
categ_id: 'product.product_category_3'
@@ -22,9 +22,9 @@
weight: 0.0
weight_net: 0.0
-
- In order to test the purchase flow,I create a new record where "invoice_method" is From Order
+ In order to test the purchase flow,I create a new record where "invoice_method" is From Order.
-
- Creating a purchase.order record
+ I create purchase order for iPod.
-
!record {model: purchase.order, id: purchase_order_po0}:
company_id: base.main_company
@@ -44,26 +44,21 @@
partner_id: base.res_partner_4
pricelist_id: purchase.list0
-
- Initially purchase order is in the draft state
+ Initially purchase order is in the draft state.
-
!assert {model: purchase.order, id: purchase_order_po0}:
- state == 'draft'
-
- Then an order is confirmed by clicking on the "Confirm Purchase Order" button
--
- !python {model: purchase.order}: |
- self.wkf_confirm_order(cr, uid, [ref("purchase_order_po0")])
--
- Performing a workflow action purchase_confirm on module purchase.order
+ I confirm the purchase order for iPod.
-
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_po0}
-
- I check that the order which was initially in the draft state has transit to confirm state.
+ I check that the order which was initially in the draft state has transit to confirm state.
-
!assert {model: purchase.order, id: purchase_order_po0}:
- state == 'confirmed'
-
- I check that an entry gets created in the "Lines to Invoice" of Invoice Control on the basis of purchase order line
+ I check that an entry gets created in the "Lines to Invoice" of Invoice Control on the basis of purchase order line.
-
!python {model: purchase.order}: |
from tools.translate import _
@@ -72,14 +67,14 @@
search_ids=pur_line.search(cr, uid, [('order_id', '=', pur_order_obj.name) ])
assert search_ids, _('Purchase order line is not created!')
-
- To check that wizard "Create Invoices" gets called
+ To check that wizard "Create Invoices" gets called.
-
- Creating a purchase.order.line_invoice record
+ I create purchase order line invoice entry.
-
!record {model: purchase.order.line_invoice, id: purchase_order_line_invoice_0}:
{}
-
- Performing an osv_memory action makeInvoices on module purchase.order.line_invoice
+ I create invoice for products in the purchase order.
-
!python {model: purchase.order.line_invoice}: |
pur_obj=self.pool.get('purchase.order')
@@ -89,7 +84,7 @@
ids.append(line.id)
self.makeInvoices(cr, uid, [1], context={'active_ids': ids})
-
- I check that invoice gets created
+ I check that invoice gets created.
-
!python {model: purchase.order}: |
from tools.translate import _
@@ -98,7 +93,7 @@
search_ids=pur_line.search(cr, uid, [('order_id', '=', pur_order_obj.name),('invoiced', '=', '1') ])
assert search_ids, _('Invoice is not created!')
-
- I check that a record gets created in the Pending Invoices
+ I check that a record gets created in the Pending Invoices.
-
!python {model: purchase.order}: |
from tools.translate import _
@@ -107,33 +102,28 @@
ids = account_obj.search(cr, uid, [('origin', '=', pur_id1.name)])
assert ids, _('Pending Invoice is not created!')
-
- Then an order is approved by clicking on the "Approved by Supplier" button
--
- !python {model: purchase.order}: |
- self.wkf_approve_order(cr, uid, [ref("purchase_order_po0")])
--
- Performing a workflow action purchase_approve on module purchase.order
+ Supplier approve the purchase order.
-
!workflow {model: purchase.order, action: purchase_approve, ref: purchase_order_po0}
-
- I check that the order which was initially in the confirmed state has transit to approved state.
+ I check that the order which was initially in the confirmed state has transit to approved state.
-
!assert {model: purchase.order, id: purchase_order_po0}:
- state == 'approved'
-
- I check that date_approve field of Delivery&Invoices gets bind with the date on which it has been approved
+ I check that date_approve field of Delivery&Invoices gets bind with the date on which it has been approved.
-
!python {model: purchase.order}: |
pur_id=self.browse(cr, uid, ref("purchase_order_po0"))
assert(pur_id.date_approve)
-
- I check that an entry gets created in the stock.picking
+ I check that an entry gets created in the pickings.
-
!python {model: purchase.order}: |
pur_id=self.browse(cr, uid, ref("purchase_order_po0"))
assert(pur_id.picking_ids)
-
- I check that an entry gets created in the stock.move
+ I check that an entry gets created in the stock moves.
-
!python {model: purchase.order}: |
from tools.translate import _
@@ -145,9 +135,9 @@
search_id = move_obj.search(cr, uid, [('picking_id', '=', pick_id.name)])
assert search_id, _('No Incoming Product!')
-
- I check that Traceability moves are created
+ I check that Traceability moves are created.
-
- I check that an invoice_id field of Delivery&Invoices gets bind with the value
+ I check that an invoice_id field of Delivery&Invoices gets bind with the value.
-
!python {model: purchase.order}: |
pur_id2=self.browse(cr, uid, ref("purchase_order_po0"))
diff --git a/addons/purchase/test/purchase_from_picking.yml b/addons/purchase/test/purchase_from_picking.yml
index f4e9628985d..6250772a872 100644
--- a/addons/purchase/test/purchase_from_picking.yml
+++ b/addons/purchase/test/purchase_from_picking.yml
@@ -1,5 +1,5 @@
-
- In order to test the purchase flow,I start by creating a new product 'iPod'
+ In order to test the purchase flow,I start by creating a new product 'iPod'
-
!record {model: product.product, id: product_product_ipod0}:
categ_id: 'product.product_category_3'
@@ -22,9 +22,9 @@
weight: 0.0
weight_net: 0.0
-
- In order to test the purchase flow,I create a new record where "invoice_method" is From Picking
+ In order to test the purchase flow,I create a new record where "invoice_method" is From Picking
-
- Creating an purchase.order record
+ I create purchase order for iPod.
-
!record {model: purchase.order, id: purchase_order_po2}:
company_id: base.main_company
@@ -44,17 +44,12 @@
partner_id: base.res_partner_4
pricelist_id: purchase.list0
-
- Initially purchase order is in the draft state
+ Initially purchase order is in the draft state.
-
!assert {model: purchase.order, id: purchase_order_po2}:
- state == 'draft'
-
- Then an order is confirmed by clicking on the "Confirm Purchase Order" button
--
- !python {model: purchase.order}: |
- self.wkf_confirm_order(cr, uid, [ref("purchase_order_po2")])
--
- Performing a workflow action purchase_confirm on module purchase.order
+ I confirm the purchase order for iPod.
-
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_po2}
-
@@ -63,7 +58,7 @@
!assert {model: purchase.order, id: purchase_order_po2}:
- state == 'confirmed'
-
- I check that an entry gets created in the "Lines to Invoice" of Invoice Control on the basis of purchase order line
+ I check that an entry gets created in the "Lines to Invoice" of Invoice Control on the basis of purchase order line.
-
!python {model: purchase.order}: |
from tools.translate import _
@@ -72,14 +67,14 @@
search_ids=pur_line.search(cr, uid, [('order_id', '=', pur_order_obj.name) ])
assert search_ids, _('Purchase order line is not created!')
-
- To check that wizard "Create Invoices" gets opened
+ To check that wizard "Create Invoices" gets opened.
-
- Creating a purchase.order.line_invoice record
+ I create purchase order line invoice entry.
-
!record {model: purchase.order.line_invoice, id: purchase_order_line_invoice_0}:
{}
-
- Performing an osv_memory action makeInvoices on module purchase.order.line_invoice
+ I create invoice for products in the purchase order.
-
!python {model: purchase.order.line_invoice}: |
pur_obj=self.pool.get('purchase.order')
@@ -89,7 +84,7 @@
ids.append(line.id)
self.makeInvoices(cr, uid, [1], context={'active_ids': ids})
-
- I check that invoice gets created
+ I check that invoice gets created.
-
!python {model: purchase.order}: |
from tools.translate import _
@@ -98,7 +93,7 @@
search_ids=pur_line.search(cr, uid, [('order_id', '=', pur_order_obj.name),('invoiced', '=', '1') ])
assert search_ids, _('Invoice is not created!')
-
- I check that a record gets created in the Pending Invoices
+ I check that a record gets created in the Pending Invoices.
-
!python {model: purchase.order}: |
from tools.translate import _
@@ -107,12 +102,7 @@
ids = account_obj.search(cr, uid, [('origin', '=', pur_id1.name)])
assert ids, _('Pending Invoice is not created!')
-
- Then an order is approved by clicking on the "Approved by Supplier" button
--
- !python {model: purchase.order}: |
- self.wkf_approve_order(cr, uid, [ref("purchase_order_po2")])
--
- Performing a workflow action purchase_approve on module purchase.order
+ Supplier approve the purchase order.
-
!workflow {model: purchase.order, action: purchase_approve, ref: purchase_order_po2}
-
@@ -121,19 +111,19 @@
!assert {model: purchase.order, id: purchase_order_po2}:
- state == 'approved'
-
- I check that date_approve field of Delivery&Invoices gets bind with the date on which it has been approved
+ I check that date_approve field of Delivery&Invoices gets bind with the date on which it has been approved.
-
!python {model: purchase.order}: |
pur_id=self.browse(cr, uid, ref("purchase_order_po2"))
assert(pur_id.date_approve)
-
- I check that an entry gets created in the stock.picking
+ I check that an entry gets created in the stock.picking.
-
!python {model: purchase.order}: |
pur_id=self.browse(cr, uid, ref("purchase_order_po2"))
assert(pur_id.picking_ids)
-
- I check that an entry gets created in the stock.move
+ I check that an entry gets created related to stock move.
-
!python {model: purchase.order}: |
from tools.translate import _
@@ -145,18 +135,18 @@
search_id = move_obj.search(cr, uid, [('picking_id', '=', pick_id.name)])
assert search_id, _('No Incoming Product!')
-
- I check that Traceability moves are created
+ I check that Traceability moves are created.
-
- Then I create an invoice from picking by clicking on "Create Invoice" wizard
+ Then I create an invoice from picking by clicking on "Create Invoice" wizard
-
- Creating a stock.invoice.onshipping record
+ I create stock invoice on shipping entry.
-
!record {model: stock.invoice.onshipping, id: stock_invoice_onshipping_0}:
invoice_date: '2010-05-11'
journal_id: account.bank_journal
type: in_invoice
-
- Performing an osv_memory action create_invoice on module stock.invoice.onshipping
+ I create Invoice.
-
!python {model: stock.invoice.onshipping}: |
pur_obj=self.pool.get('purchase.order')
@@ -167,7 +157,7 @@
"tz": False, "search_default_approved": 1, "active_model": "stock.picking",
"active_ids": ids, "active_id": ids[0], })
-
- I check that an invoice_id field of Delivery&Invoices gets bind with the value
+ I check that an invoice_id field of Delivery&Invoices gets bind with the value.
-
!python {model: purchase.order}: |
pur_id2=self.browse(cr, uid, ref("purchase_order_po2"))
diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py
index 85c35b277c5..5aaf3a995e2 100644
--- a/addons/purchase_requisition/purchase_requisition.py
+++ b/addons/purchase_requisition/purchase_requisition.py
@@ -136,11 +136,11 @@ class product_product(osv.osv):
product_product()
-class mrp_procurement(osv.osv):
- _inherit = 'mrp.procurement'
+class procurement_order(osv.osv):
+ _inherit = 'procurement.order'
def make_po(self, cr, uid, ids, context={}):
sequence_obj=self.pool.get('ir.sequence')
- res = super(mrp_procurement, self).make_po(cr, uid, ids, context)
+ res = super(procurement_order, self).make_po(cr, uid, ids, context)
for proc_id,po_id in res.items():
procurement = self.browse(cr, uid, proc_id)
if procurement.product_id.purchase_requisition:
@@ -157,4 +157,4 @@ class mrp_procurement(osv.osv):
'purchase_ids': [(6,0,[po_id])]
})
return res
-mrp_procurement()
+procurement_order()
diff --git a/addons/purchase_requisition/purchase_requisition_view.xml b/addons/purchase_requisition/purchase_requisition_view.xml
index 186815c9bc3..172be8c06e8 100644
--- a/addons/purchase_requisition/purchase_requisition_view.xml
+++ b/addons/purchase_requisition/purchase_requisition_view.xml
@@ -39,7 +39,7 @@
-
+
@@ -52,41 +52,41 @@
-
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -110,7 +110,7 @@
-
+ purchase.requisition.list.selectpurchase.requisitionsearch
@@ -118,22 +118,22 @@
-
+
-
+
-
+
-
+
@@ -145,8 +145,8 @@
ir.actions.act_windowpurchase.requisitionform
- tree,form
- {"search_default_user_id":uid}
+ tree,form
+ {"search_default_user_id":uid}
diff --git a/addons/purchase_requisition/test/purchase_requisition.yml b/addons/purchase_requisition/test/purchase_requisition.yml
index 8983d238e0e..0ace2312034 100644
--- a/addons/purchase_requisition/test/purchase_requisition.yml
+++ b/addons/purchase_requisition/test/purchase_requisition.yml
@@ -59,8 +59,8 @@
-
I launch he scheduler to compute all procurements, and specify all requisitions orders.
-
- !python {model: mrp.procurement.compute.all}: |
- proc_obj = self.pool.get('mrp.procurement')
+ !python {model: procurement.order.compute.all}: |
+ proc_obj = self.pool.get('procurement.order')
proc_obj._procure_confirm(cr,uid)
-
On the purchase tender, I create a new purchase order for the supplier 'DistriPC' by clicking on
diff --git a/addons/purchase_requisition/test/purchase_requisition_exclusive.yml b/addons/purchase_requisition/test/purchase_requisition_exclusive.yml
index e2cba67fca9..641fd740de3 100644
--- a/addons/purchase_requisition/test/purchase_requisition_exclusive.yml
+++ b/addons/purchase_requisition/test/purchase_requisition_exclusive.yml
@@ -52,8 +52,8 @@
-
I launch he scheduler to compute all procurements, and planify all requisitions orders.
-
- !python {model: mrp.procurement.compute.all}: |
- proc_obj = self.pool.get('mrp.procurement')
+ !python {model: procurement.order.compute.all}: |
+ proc_obj = self.pool.get('procurement.order')
proc_obj._procure_confirm(cr,uid)
-
I should find a purchase requisition with the origin 'TEST/TENDER/0002', that includes a request for
diff --git a/addons/purchase_requisition/wizard/purchase_requisition_partner.py b/addons/purchase_requisition/wizard/purchase_requisition_partner.py
index e886ba302b9..3f74e857035 100644
--- a/addons/purchase_requisition/wizard/purchase_requisition_partner.py
+++ b/addons/purchase_requisition/wizard/purchase_requisition_partner.py
@@ -82,15 +82,15 @@ class purchase_requisition_partner(osv.osv_memory):
purchase_order_line={}
for tender in tender_obj.browse(cr, uid, record_ids):
for line in tender.line_ids:
-
+ partner_list = sorted([(partner.sequence, partner) for partner in line.product_id.seller_ids if partner])
+ partner_rec = partner_list and partner_list[0] and partner_list[0][1] or False
uom_id = line.product_id.uom_po_id and line.product_id.uom_po_id.id or False
newdate = DateTime.strptime(tender.date_start, '%Y-%m-%d %H:%M:%S')
newdate = newdate - DateTime.RelativeDateTime(days=company.po_lead)
- newdate = newdate -(line.product_id.seller_ids and line.product_id.seller_ids[0].delay or DateTime.strptime(tender.date_start, '%Y-%m-%d %H:%M:%S') )
-
-
- partner = line.product_id.seller_ids and line.product_id.seller_ids[0].name or supplier_data
- pricelist_id = partner.property_product_pricelist_purchase and partner.property_product_pricelist_purchase.id
+ delay = partner_rec and partner_rec.delay or False
+ newdate = newdate -(delay or DateTime.strptime(tender.date_start, '%Y-%m-%d %H:%M:%S') )
+ partner = partner_rec and partner_rec.name or supplier_data
+ pricelist_id = partner.property_product_pricelist_purchase and partner.property_product_pricelist_purchase.id or False
price = pricelist_obj.price_get(cr, uid, [pricelist_id], line.product_id.id, line.product_qty, False, {'uom': uom_id})[pricelist_id]
product = prod_obj.browse(cr, uid, line.product_id.id, context=context)
diff --git a/addons/report_account/i18n/hr.po b/addons/report_account/i18n/hr.po
index 80572ec3975..cf3556f5c74 100644
--- a/addons/report_account/i18n/hr.po
+++ b/addons/report_account/i18n/hr.po
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-07 03:43+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:43+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"
diff --git a/addons/report_analytic/i18n/hr.po b/addons/report_analytic/i18n/hr.po
index 927bf538d9a..38a2e3a382a 100644
--- a/addons/report_analytic/i18n/hr.po
+++ b/addons/report_analytic/i18n/hr.po
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-07 03:43+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:42+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"
diff --git a/addons/report_analytic_planning/i18n/hr.po b/addons/report_analytic_planning/i18n/hr.po
index 8b91cf0c0a6..e8c68bf5c95 100644
--- a/addons/report_analytic_planning/i18n/hr.po
+++ b/addons/report_analytic_planning/i18n/hr.po
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-07 03:43+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:42+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"
diff --git a/addons/report_designer/security/ir.model.access.csv b/addons/report_designer/security/ir.model.access.csv
index 81d2854dc14..e6500199afe 100644
--- a/addons/report_designer/security/ir.model.access.csv
+++ b/addons/report_designer/security/ir.model.access.csv
@@ -1,2 +1,2 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
-"access_report_designer_installer","report_designer.installer","model_report_designer_installer",,1,1,1,1
+"access_report_designer_installer","report_designer.installer","model_report_designer_installer",base.group_system,1,1,1,1
diff --git a/addons/report_document/i18n/hr.po b/addons/report_document/i18n/hr.po
index 68c557c8f48..84ad5969b7f 100644
--- a/addons/report_document/i18n/hr.po
+++ b/addons/report_document/i18n/hr.po
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-07 03:43+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:43+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"
diff --git a/addons/report_intrastat/i18n/hr.po b/addons/report_intrastat/i18n/hr.po
index 8acb596f530..94f017514f4 100644
--- a/addons/report_intrastat/i18n/hr.po
+++ b/addons/report_intrastat/i18n/hr.po
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-07 03:43+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:43+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"
diff --git a/addons/report_project/i18n/hr.po b/addons/report_project/i18n/hr.po
index 9993f03eb9e..3f4f33b86c3 100644
--- a/addons/report_project/i18n/hr.po
+++ b/addons/report_project/i18n/hr.po
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-07 03:43+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:42+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"
diff --git a/addons/report_purchase/i18n/hr.po b/addons/report_purchase/i18n/hr.po
index 52a3fbf6ada..8d921c1f990 100644
--- a/addons/report_purchase/i18n/hr.po
+++ b/addons/report_purchase/i18n/hr.po
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-07 03:43+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:42+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"
diff --git a/addons/report_sale/i18n/hr.po b/addons/report_sale/i18n/hr.po
index 61af04b6fad..796a3eccf62 100644
--- a/addons/report_sale/i18n/hr.po
+++ b/addons/report_sale/i18n/hr.po
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-07 03:43+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:43+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"
diff --git a/addons/report_task/i18n/es.po b/addons/report_task/i18n/es.po
index 17a1ae549dd..5e5b4fc41ad 100644
--- a/addons/report_task/i18n/es.po
+++ b/addons/report_task/i18n/es.po
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
-"PO-Revision-Date: 2010-06-04 12:29+0000\n"
+"PO-Revision-Date: 2010-06-09 09:31+0000\n"
"Last-Translator: Jonay \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-05 03:36+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:43+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: report_task
@@ -205,7 +205,7 @@ msgstr "Cancelado"
#. module: report_task
#: view:report.timesheet.task.user:0
msgid "Timesheet/Task hours Report Per Month"
-msgstr ""
+msgstr "Horario / Informe de horas de trabajo por mes"
#. module: report_task
#: field:report.task.user.pipeline.open,task_progress:0
@@ -250,7 +250,7 @@ msgstr "Fecha límite"
#. module: report_task
#: field:report.timesheet.task.user,timesheet_hrs:0
msgid "Timesheet Hours"
-msgstr ""
+msgstr "Horas del horario"
#. module: report_task
#: view:report.closed.task:0
@@ -265,4 +265,4 @@ msgstr "Abrir"
#. module: report_task
#: field:report.closed.task,planned_hours:0
msgid "Planned Hours"
-msgstr ""
+msgstr "Horas planeadas"
diff --git a/addons/resource/resource_view.xml b/addons/resource/resource_view.xml
index df0974fd9ed..d00074cf54e 100644
--- a/addons/resource/resource_view.xml
+++ b/addons/resource/resource_view.xml
@@ -12,7 +12,7 @@
-
+
@@ -35,7 +35,7 @@
-
+
@@ -52,7 +52,7 @@
-
+
diff --git a/addons/resource/security/ir.model.access.csv b/addons/resource/security/ir.model.access.csv
index 796d29dcb94..f52b43adcaa 100644
--- a/addons/resource/security/ir.model.access.csv
+++ b/addons/resource/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_resource_calendar","resource.calendar","model_resource_calendar","base.group_user",1,0,0,0
-"access_resource_calendar_week","resource.calendar.week","model_resource_calendar_week","base.group_user",1,0,0,0
-"access_resource_resource","resource.resource","model_resource_resource","base.group_user",1,0,0,0
-"access_resource_calendar_leaves","resource.calendar.leaves","model_resource_calendar_leaves","base.group_user",1,0,0,0
\ No newline at end of file
+"access_resource_calendar","resource.calendar","model_resource_calendar","base.group_system",1,1,1,1
+"access_resource_calendar_week","resource.calendar.week","model_resource_calendar_week","base.group_system",1,1,1,1
+"access_resource_resource","resource.resource","model_resource_resource","base.group_system",1,1,1,1
+"access_resource_calendar_leaves","resource.calendar.leaves","model_resource_calendar_leaves","base.group_system",1,1,1,1
diff --git a/addons/sale/__init__.py b/addons/sale/__init__.py
index 71f33623c55..3ad30a6233e 100644
--- a/addons/sale/__init__.py
+++ b/addons/sale/__init__.py
@@ -26,7 +26,6 @@
import sale
import stock
import product
-#import mrp
import wizard
import report
import company
diff --git a/addons/sale/__openerp__.py b/addons/sale/__openerp__.py
index 651945752a7..2f265b3d6f7 100644
--- a/addons/sale/__openerp__.py
+++ b/addons/sale/__openerp__.py
@@ -42,7 +42,7 @@
""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
- 'depends': ['product', 'stock', 'mrp_procurement', 'process'],
+ 'depends': ['product', 'stock', 'procurement', 'process'],
'init_xml': [],
'update_xml': [
'wizard/sale_make_invoice_advance.xml',
@@ -65,6 +65,8 @@
'test/shipping_manual_sale_order.yml',
'test/prepaid_sale_order.yml',
'test/advance_invoice.yml',
+ 'test/so_make_line_invoice.yml',
+ 'test/so_make_invoice.yml',
'test/sale_procurement.yml',
],
'installable': True,
diff --git a/addons/sale/i18n/ca.po b/addons/sale/i18n/ca.po
index 90b6341eea9..ceaf026717a 100644
--- a/addons/sale/i18n/ca.po
+++ b/addons/sale/i18n/ca.po
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-05 03:36+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:43+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: sale
diff --git a/addons/sale/i18n/hr.po b/addons/sale/i18n/hr.po
index c17d591e485..a00233e6ac7 100644
--- a/addons/sale/i18n/hr.po
+++ b/addons/sale/i18n/hr.po
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-07 03:43+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:43+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"
diff --git a/addons/sale/i18n/ru.po b/addons/sale/i18n/ru.po
index d6858cc9f75..ce9c8c51095 100644
--- a/addons/sale/i18n/ru.po
+++ b/addons/sale/i18n/ru.po
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
-"PO-Revision-Date: 2009-02-04 05:56+0000\n"
-"Last-Translator: Fabien (Open ERP) \n"
+"PO-Revision-Date: 2010-06-11 16:29+0000\n"
+"Last-Translator: Sios \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-04-17 04:09+0000\n"
+"X-Launchpad-Export-Date: 2010-06-12 03:45+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: sale
@@ -117,7 +117,7 @@ msgstr ""
#. module: sale
#: model:ir.model,name:sale.model_sale_config_picking_policy
msgid "sale.config.picking_policy"
-msgstr ""
+msgstr "sale.config.picking_policy"
#. module: sale
#: model:process.transition.action,name:sale.process_transition_action_validate0
diff --git a/addons/sale/process/sale_process.xml b/addons/sale/process/sale_process.xml
index 58e4be14d84..1ebbc267de7 100644
--- a/addons/sale/process/sale_process.xml
+++ b/addons/sale/process/sale_process.xml
@@ -35,7 +35,7 @@
-
+
@@ -63,12 +63,12 @@
-
-
+
+
-
+
@@ -202,7 +202,7 @@
-
+
diff --git a/addons/sale/report/sale_report.py b/addons/sale/report/sale_report.py
index d9be5f49274..b47d59e5400 100644
--- a/addons/sale/report/sale_report.py
+++ b/addons/sale/report/sale_report.py
@@ -41,8 +41,12 @@ class sale_report(osv.osv):
('10','October'), ('11','November'), ('12','December')], 'Month',readonly=True),
'day': fields.char('Day', size=128, readonly=True),
'product_id':fields.many2one('product.product', 'Product', readonly=True),
+
+ 'uom_id': fields.many2one('product.uom', 'Default Unit Of Measure', readonly=True),
+ 'product_qty':fields.float('# of Qty', readonly=True),
'uom_name': fields.char('Default UoM', size=128, readonly=True),
'product_uom_qty':fields.float('# of Qty', readonly=True),
+
'partner_id':fields.many2one('res.partner', 'Partner', readonly=True),
'shop_id':fields.many2one('sale.shop', 'Shop', readonly=True),
'company_id':fields.many2one('res.company', 'Company', readonly=True),
@@ -71,7 +75,8 @@ class sale_report(osv.osv):
cr.execute("""
create or replace view sale_report as (
select el.*,
- (select count(1) from sale_order_line where order_id = s.id) as nbr,
+ -- (select count(1) from sale_order_line where order_id = s.id) as nbr,
+ (select 1) as nbr,
s.date_order as date,
s.date_confirm as date_confirm,
to_char(s.date_order, 'YYYY') as year,
@@ -101,7 +106,7 @@ class sale_report(osv.osv):
sale_order_line l
left join product_uom u on (u.id=l.product_uom)
left join product_template pt on (pt.id=l.product_id)
- group by l.id, l.order_id, l.product_id, u.name, pt.categ_id) el
+ group by l.id, l.order_id, l.product_id, u.name, pt.categ_id) el
where s.id = el.order_id
)
""")
diff --git a/addons/sale/report/sale_report_view.xml b/addons/sale/report/sale_report_view.xml
index 75dd9d55642..9b8ed32ede4 100644
--- a/addons/sale/report/sale_report_view.xml
+++ b/addons/sale/report/sale_report_view.xml
@@ -19,7 +19,7 @@
-
+
@@ -85,19 +85,19 @@
-
+
-
-
+
-
+
+
+
-
-
-
+
+
@@ -109,7 +109,6 @@
-
@@ -129,6 +128,16 @@
+
+ Shipments Analysis
+ report.stock.move
+ form
+ tree,graph
+ {'search_default_month':1, 'search_default_group_product':1, 'search_default_group_partner':1, 'search_default_done':1, 'search_default_out': 1, 'group_by':[], 'group_by_no_leaf':1}
+
+
+
+
sale.order.by.clients.tree
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index 07c66ef91dc..07cb7e34b50 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -112,7 +112,7 @@ class sale_order(osv.osv):
LEFT JOIN
stock_picking p on (p.id=m.picking_id)
LEFT JOIN
- mrp_procurement mp on (mp.move_id=m.id)
+ procurement_order mp on (mp.move_id=m.id)
WHERE
p.sale_id = ANY(%s) GROUP BY mp.state, p.sale_id''',(ids,))
for oid, nbr, mp_state in cr.fetchall():
@@ -253,7 +253,7 @@ class sale_order(osv.osv):
'invoiced_rate': fields.function(_invoiced_rate, method=True, string='Invoiced', type='float'),
'invoiced': fields.function(_invoiced, method=True, string='Paid',
fnct_search=_invoiced_search, type='boolean'),
- 'note': fields.text('Notes', translate=True),
+ 'note': fields.text('Notes'),
'amount_untaxed': fields.function(_amount_all, method=True, digits_compute= dp.get_precision('Sale Price'), string='Untaxed Amount',
store = {
@@ -642,6 +642,7 @@ class sale_order(osv.osv):
'picking_id': picking_id,
'product_id': line.product_id.id,
'date_planned': date_planned,
+ 'date_expected': date_planned,
'product_qty': line.product_uom_qty,
'product_uom': line.product_uom.id,
'product_uos_qty': line.product_uos_qty,
@@ -658,7 +659,7 @@ class sale_order(osv.osv):
'note': line.notes,
'company_id': order.company_id.id,
})
- proc_id = self.pool.get('mrp.procurement').create(cr, uid, {
+ proc_id = self.pool.get('procurement.order').create(cr, uid, {
'name': order.name,
'origin': order.name,
'date_planned': date_planned,
@@ -676,10 +677,10 @@ class sale_order(osv.osv):
'company_id': order.company_id.id,
})
wf_service = netsvc.LocalService("workflow")
- wf_service.trg_validate(uid, 'mrp.procurement', proc_id, 'button_confirm', cr)
+ wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_confirm', cr)
self.pool.get('sale.order.line').write(cr, uid, [line.id], {'procurement_id': proc_id})
elif line.product_id and line.product_id.product_tmpl_id.type == 'service':
- proc_id = self.pool.get('mrp.procurement').create(cr, uid, {
+ proc_id = self.pool.get('procurement.order').create(cr, uid, {
'name': line.name,
'origin': order.name,
'date_planned': date_planned,
@@ -693,7 +694,7 @@ class sale_order(osv.osv):
})
self.pool.get('sale.order.line').write(cr, uid, [line.id], {'procurement_id': proc_id})
wf_service = netsvc.LocalService("workflow")
- wf_service.trg_validate(uid, 'mrp.procurement', proc_id, 'button_confirm', cr)
+ wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_confirm', cr)
else:
#
# No procurement because no product in the sale.order.line.
@@ -807,7 +808,7 @@ class sale_order_line(osv.osv):
'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('mrp.procurement', 'Procurement'),
+ '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, method=True, 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)]}),
@@ -822,7 +823,7 @@ class sale_order_line(osv.osv):
'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, method=True, type='integer', string='Number Packages'),
- 'notes': fields.text('Notes', translate=True),
+ 'notes': fields.text('Notes'),
'th_weight': fields.float('Weight'),
'state': fields.selection([('draft', 'Draft'),('confirmed', 'Confirmed'),('done', 'Done'),('cancel', 'Cancelled'),('exception', 'Exception')], 'State', required=True, readonly=True,
help=' * The \'Draft\' state is set automatically when sale order in draft state. \
@@ -856,7 +857,7 @@ class sale_order_line(osv.osv):
return line.product_uos_qty or 0.0
return line.product_uom_qty
else:
- return self.pool.get('mrp.procurement').quantity_get(cr, uid,
+ return self.pool.get('procurement.order').quantity_get(cr, uid,
line.procurement_id.id, context=context)
def _get_line_uom(line):
@@ -865,7 +866,7 @@ class sale_order_line(osv.osv):
return line.product_uos.id
return line.product_uom.id
else:
- return self.pool.get('mrp.procurement').uom_get(cr, uid,
+ return self.pool.get('procurement.order').uom_get(cr, uid,
line.procurement_id.id, context=context)
create_ids = []
diff --git a/addons/sale/sale_demo.xml b/addons/sale/sale_demo.xml
index d6ab6a7bc0c..0920cdeebb2 100644
--- a/addons/sale/sale_demo.xml
+++ b/addons/sale/sale_demo.xml
@@ -206,7 +206,7 @@
-
+
diff --git a/addons/sale/sale_unit_test.xml b/addons/sale/sale_unit_test.xml
index dc507edb4a0..95a23024412 100644
--- a/addons/sale/sale_unit_test.xml
+++ b/addons/sale/sale_unit_test.xml
@@ -112,7 +112,7 @@
-
+ done
diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml
index c236b669580..b61ba5a0f23 100644
--- a/addons/sale/sale_view.xml
+++ b/addons/sale/sale_view.xml
@@ -91,6 +91,15 @@
+
+
+
sale.order.formsale.order
@@ -111,7 +120,7 @@
-
+
@@ -130,6 +139,7 @@
name="product_uom_qty"
on_change="product_id_change(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, 'lang' in context and context['lang'], False, parent.date_order, product_packaging, parent.fiscal_position, True)"
/>
+
-
+
+
@@ -186,12 +197,12 @@
-
+
-
+
@@ -257,7 +268,7 @@
-
+
@@ -367,6 +378,7 @@
+
@@ -424,7 +436,7 @@
-
+
@@ -510,16 +522,16 @@
Sales Configuration
- Configure Sale Order Logistic
-
-
- Setup your sales workflow and default values.
-
+
+
+ Setup your sales workflow and default values.
+
- 15
-
-
+ 15
+
+
diff --git a/addons/sale/sale_workflow.xml b/addons/sale/sale_workflow.xml
index 213605929ba..effe7cb6fff 100644
--- a/addons/sale/sale_workflow.xml
+++ b/addons/sale/sale_workflow.xml
@@ -218,7 +218,7 @@
- mrp.procurement
+ procurement.orderprocurement_lines_get()test_state('finished')
@@ -226,7 +226,7 @@
test_state('canceled')
diff --git a/addons/sale/security/ir.model.access.csv b/addons/sale/security/ir.model.access.csv
index 7af8c1e74a7..7328793e2f3 100644
--- a/addons/sale/security/ir.model.access.csv
+++ b/addons/sale/security/ir.model.access.csv
@@ -11,17 +11,17 @@
"access_account_analytic_account_salesman","account_analytic_account salesman","analytic.model_account_analytic_account","group_sale_user",1,1,1,1
"access_stock_picking_salesman","stock_picking salesman","stock.model_stock_picking","group_sale_user",1,1,1,1
"access_stock_move_salesman","stock_move salesman","stock.model_stock_move","group_sale_user",1,1,1,0
-"access_mrp_procurement_salesman","mrp.procurement salesman","mrp_procurement.model_mrp_procurement","group_sale_user",1,1,1,1
+"access_procurement_salesman","procurement.order salesman","procurement.model_procurement_order","group_sale_user",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","group_sale_manager",1,1,1,1
"access_sale_order_line_manager","sale.order.line.manager","model_sale_order_line","group_sale_manager",1,1,1,1
-"access_sale_report","sale.report","model_sale_report","group_sale_user",1,1,1,0
-"access_sale_report_manager","sale.report","model_sale_report","group_sale_manager",1,1,1,1
+"access_sale_report_manager","sale.report","model_sale_report","group_sale_manager",1,0,0,0
"access_sale_order_line_make_invoice","sale.order.line.make.invoice","model_sale_order_line_make_invoice","group_sale_user",1,1,1,0
"access_sale_order_line_make_invoice_manager","sale.order.line.make.invoice","model_sale_order_line_make_invoice","group_sale_manager",1,1,1,1
"access_sale_advance_payment_inv","sale.advance.payment.inv","model_sale_advance_payment_inv","group_sale_user",1,1,1,0
"access_sale_advance_payment_inv_manager","sale.advance.payment.inv","model_sale_advance_payment_inv","group_sale_manager",1,1,1,1
"access_sale_open_invoice","sale.open.invoice","model_sale_open_invoice","group_sale_user",1,1,1,0
"access_sale_open_invoice_manager","sale.open.invoice","model_sale_open_invoice","group_sale_manager",1,1,1,1
-
+"access_product_product_sale_user","product.product.sale.user","model_product_product","group_sale_user",1,0,0,0
+"access_sale_account_journal","account.journal sale order.user","account.model_account_journal","group_sale_user",1,0,0,0
diff --git a/addons/sale/security/sale_security.xml b/addons/sale/security/sale_security.xml
index fd8b3e0d3c7..8e5c8360d07 100644
--- a/addons/sale/security/sale_security.xml
+++ b/addons/sale/security/sale_security.xml
@@ -14,14 +14,14 @@
- Sale Order multi-company
+ Sale Order multi-company['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
- Sale Order Line multi-company
+ Sale Order Line multi-company['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
diff --git a/addons/sale/test/sale_procurement.yml b/addons/sale/test/sale_procurement.yml
index c9d26baec9f..33ba22667ec 100644
--- a/addons/sale/test/sale_procurement.yml
+++ b/addons/sale/test/sale_procurement.yml
@@ -3,6 +3,8 @@
products with different supply method and procurement method.
-
I create two products.
+-
+ I create one product Table.
-
!record {model: product.product, id: product_product_table0}:
categ_id: product.cat1
@@ -12,6 +14,8 @@
type: product
uom_id: product.product_uom_unit
uom_po_id: product.product_uom_unit
+-
+ I create another product Wood.
-
!record {model: product.product, id: product_product_wood0}:
categ_id: product.cat1
@@ -68,21 +72,21 @@
-
I check that one procurement is generated.
-
- !python {model: mrp.procurement}: |
+ !python {model: procurement.order}: |
from tools.translate import _
proc_ids = self.search(cr, uid, [('state','=','confirmed')])
assert proc_ids, _('No Procurements!')
-
The scheduler runs.
-
- !function {model: mrp.procurement, name: run_scheduler}:
- - model: mrp.procurement
+ !function {model: procurement.order, name: run_scheduler}:
+ - model: procurement.order
search: "[('state','=','confirmed')]"
-
I check that the procurement for the product table is in exception state.
As my product's supply method is produce and mrp module is yet not installed.
-
- !python {model: mrp.procurement}: |
+ !python {model: procurement.order}: |
from tools.translate import _
proc_ids = self.search(cr, uid, [('state','=','exception')])
assert proc_ids, _('No Procurements are in exception state!')
diff --git a/addons/sale/test/shipping_manual_sale_order.yml b/addons/sale/test/shipping_manual_sale_order.yml
index 4bbbbb74dc5..c030a80c64a 100644
--- a/addons/sale/test/shipping_manual_sale_order.yml
+++ b/addons/sale/test/shipping_manual_sale_order.yml
@@ -211,7 +211,7 @@
!record {model: product.category, id: product_category_services0}:
name: Mobile Services
-
- I define LG Viewty Smart product template.
+ I define New Chocolate Slider Mobile template.
-
!record {model: product.template, id: product_template_newchocolateslidermobile0}:
categ_id: product_category_allproductssellable0
@@ -226,7 +226,7 @@
uom_id: product.product_uom_unit
uom_po_id: product.product_uom_unit
-
- I define LG Viewty Smart product.
+ I define New Chocolate Slider Mobile.
-
!record {model: product.product, id: product_product_newchocolateslidermobile0}:
categ_id: product_category_allproductssellable0
diff --git a/addons/sale/test/so_make_invoice.yml b/addons/sale/test/so_make_invoice.yml
new file mode 100644
index 00000000000..e34b11ffb2b
--- /dev/null
+++ b/addons/sale/test/so_make_invoice.yml
@@ -0,0 +1,341 @@
+-
+ In order to test the sale module in the Open-ERP, I need to configure details regarding product & customer.
+-
+ I am going to sell my Mobile products to the customer with name Cleartrail
+-
+ I create View Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_view0}:
+ close_method: none
+ code: View
+ name: View
+ sign: 1
+-
+ I create Income Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_income0}:
+ close_method: unreconciled
+ code: Income
+ name: Income
+ sign: 1
+-
+ I create Expense Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_expense0}:
+ close_method: unreconciled
+ code: Expense
+ name: Expense
+ sign: 1
+-
+ I create Cash Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_cash0}:
+ close_method: balance
+ code: Cash
+ name: Cash
+ sign: 1
+-
+ I create Minimal Chart Account.
+-
+ !record {model: account.account, id: account_account_minimalchart0}:
+ code: '0'
+ company_id: base.main_company
+ currency_mode: current
+ name: Minimal Chart
+ parent_left: 1
+ parent_right: 12
+ type: view
+ user_type: account_account_type_view0
+-
+ I create Payable Account.
+-
+ !record {model: account.account, id: account_account_payable1}:
+ code: AP
+ company_id: base.main_company
+ currency_mode: current
+ name: Payable
+ parent_id: account_account_minimalchart0
+ parent_left: 2
+ parent_right: 3
+ reconcile: true
+ type: payable
+ user_type: account_account_type_expense0
+-
+ I create Receivable Account.
+-
+ !record {model: account.account, id: account_account_receivable0}:
+ code: AR
+ company_id: base.main_company
+ currency_mode: current
+ name: Receivable
+ parent_id: account_account_minimalchart0
+ parent_left: 4
+ parent_right: 5
+ reconcile: true
+ type: receivable
+ user_type: account_account_type_income0
+-
+ I create Cash Account.
+-
+ !record {model: account.account, id: account_account_cash0}:
+ code: C
+ company_id: base.main_company
+ currency_mode: current
+ name: Cash
+ parent_id: account_account_minimalchart0
+ parent_left: 6
+ parent_right: 7
+ type: other
+ user_type: account_account_type_cash0
+-
+ I create Purchases Account.
+-
+ !record {model: account.account, id: account_account_purchases0}:
+ code: P
+ company_id: base.main_company
+ currency_mode: current
+ name: Purchases
+ parent_id: account_account_minimalchart0
+ parent_left: 8
+ parent_right: 9
+ type: other
+ user_type: account_account_type_expense0
+-
+ I create Sales Account.
+-
+ !record {model: account.account, id: account_account_sales0}:
+ code: S
+ company_id: base.main_company
+ currency_mode: current
+ name: Sales
+ parent_id: account_account_minimalchart0
+ parent_left: 10
+ parent_right: 11
+ type: other
+ user_type: account_account_type_income0
+-
+ I create Purchase Journal.
+-
+ !record {model: account.journal, id: account_journal_purchasejournal0}:
+ code: PUJ
+ company_id: base.main_company
+ default_credit_account_id: account_account_purchases0
+ default_debit_account_id: account_account_purchases0
+ name: Purchase Journal
+ sequence_id: account.sequence_purchase_journal
+ type: purchase
+ view_id: account.account_journal_view
+-
+ I create Sale Journal.
+-
+ !record {model: account.journal, id: account_journal_salejournal0}:
+ code: SAJ
+ company_id: base.main_company
+ default_credit_account_id: account_account_sales0
+ default_debit_account_id: account_account_sales0
+ name: Sale Journal
+ sequence_id: account.sequence_sale_journal
+ type: sale
+ view_id: account.account_journal_view
+-
+ I create Bank Journal.
+-
+ !record {model: account.journal, id: account_journal_bankjournal0}:
+ code: BNK
+ company_id: base.main_company
+ default_credit_account_id: account_account_cash0
+ default_debit_account_id: account_account_cash0
+ name: Bank Journal
+ sequence_id: account.sequence_journal
+ type: cash
+ view_id: account.account_journal_bank_view
+-
+ I create ir.property for account payable.
+-
+ !record {model: ir.property, id: ir_property_propertyaccountexpensecateg0}:
+ company_id: base.main_company
+ fields_id: account.field_res_partner_property_account_payable
+ name: property_account_expense_categ
+ value_reference: account.account,5
+-
+ I create ir.property for account receivable.
+-
+ !record {model: ir.property, id: ir_property_propertyaccountincomecateg0}:
+ company_id: base.main_company
+ fields_id: account.field_res_partner_property_account_receivable
+ name: property_account_income_categ
+ value_reference: account.account,6
+-
+ I create Partner category Customers.
+-
+ !record {model: res.partner.category, id: res_partner_category_customers0}:
+ name: Customers
+-
+ I create Cleartrail Customer.
+-
+ !record {model: res.partner, id: res_partner_cleartrail0}:
+ category_id:
+ - res_partner_category_customers0
+ name: Cleartrail
+-
+ I create contact address for Cleartrail.
+-
+ !record {model: res.partner.address, id: res_partner_address_1}:
+ partner_id: res_partner_cleartrail0
+ street: onam plaza, 14 B palasia A B Road
+ type: contact
+-
+ I create invoice address for Cleartrail.
+-
+ !record {model: res.partner.address, id: res_partner_address_2}:
+ partner_id: res_partner_cleartrail0
+ street: sarda house 24 B palasia, A B Road
+ type: invoice
+-
+ I create delivery address for Cleartrail.
+-
+ !record {model: res.partner.address, id: res_partner_address_3}:
+ partner_id: res_partner_cleartrail0
+ street: sangam house 15 B palasia, A B Road
+ type: delivery
+-
+ Customer Cleartrail has specific instrument requirement regarding the stockable products.
+-
+ I define product category Mobile Products Sellable.
+-
+ !record {model: product.category, id: product_category_allproductssellable0}:
+ name: Mobile Products Sellable
+-
+ I define product category Mobile Services.
+-
+ !record {model: product.category, id: product_category_services0}:
+ name: Mobile Services
+-
+ I define LG Viewty Smart product template.
+-
+ !record {model: product.template, id: product_template_lgviewtysmart0}:
+ categ_id: product_category_allproductssellable0
+ cost_method: standard
+ list_price: 170.0
+ mes_type: fixed
+ name: LG Viewty Smart
+ procure_method: make_to_order
+ standard_price: 160.0
+ supply_method: produce
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+-
+ I define LG Viewty Smart product.
+-
+ !record {model: product.product, id: product_product_lgviewtysmart0}:
+ categ_id: product_category_allproductssellable0
+ cost_method: standard
+ list_price: 170.0
+ mes_type: fixed
+ name: LG Viewty Smart
+ pricelist_purchase: 'Default Purchase Pricelist (0.00) : 160.00\n'
+ pricelist_sale: 'Public Pricelist (0.00) : 170.00\n'
+ procure_method: make_to_order
+ property_account_expense: sale.account_account_payable1
+ property_account_income: sale.account_account_receivable0
+ seller_delay: '1'
+ standard_price: 160.0
+ supply_method: produce
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+-
+ I define New Chocolate Slider Mobile template.
+-
+ !record {model: product.template, id: product_template_newchocolateslidermobile0}:
+ categ_id: product_category_allproductssellable0
+ cost_method: standard
+ list_price: 200.0
+ mes_type: fixed
+ name: New Chocolate Slider Mobile
+ procure_method: make_to_order
+ standard_price: 189.0
+ supply_method: buy
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+-
+ I define New Chocolate Slider Mobile.
+-
+ !record {model: product.product, id: product_product_newchocolateslidermobile0}:
+ categ_id: product_category_allproductssellable0
+ cost_method: standard
+ list_price: 200.0
+ mes_type: fixed
+ name: New Chocolate Slider Mobile
+ pricelist_purchase: 'Default Purchase Pricelist (0.00) : 189.00\n'
+ pricelist_sale: 'Public Pricelist (0.00) : 200.00\n'
+ procure_method: make_to_order
+ property_account_expense: sale.account_account_payable1
+ property_account_income: sale.account_account_receivable0
+ seller_delay: '1'
+ standard_price: 189.0
+ supply_method: buy
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+-
+ I create a Sale Order for LG Viewty Smart for qty 500 having order_policy manual.
+-
+ !record {model: sale.order, id: sale_order_so4}:
+ date_order: '2010-05-12'
+ invoice_quantity: order
+ name: Test_SO004
+ order_line:
+ - name: New Chocolate Slider Mobile
+ price_unit: 200.0
+ product_uom: product.product_uom_unit
+ product_uom_qty: 500.0
+ state: draft
+ delay: 7.0
+ product_id: sale.product_product_newchocolateslidermobile0
+ product_uos_qty: 500.0
+ type: make_to_order
+ - name: LG Viewty Smart
+ price_unit: 170.0
+ product_uom: product.product_uom_unit
+ product_uom_qty: 500.0
+ state: draft
+ delay: 7.0
+ product_id: sale.product_product_lgviewtysmart0
+ product_uos_qty: 500.0
+ th_weight: 0.0
+ type: make_to_order
+ order_policy: manual
+ partner_id: sale.res_partner_cleartrail0
+ partner_invoice_id: sale.res_partner_address_2
+ partner_order_id: sale.res_partner_address_1
+ partner_shipping_id: sale.res_partner_address_3
+ picking_policy: direct
+ pricelist_id: product.list0
+ shop_id: sale.shop
+-
+ I confirm the Sale Order.
+-
+ !workflow {model: sale.order, action: order_confirm, ref: sale_order_so4}
+-
+ I create an invoice on sale order.
+-
+ !record {model: sale.make.invoice, id: sale_make_invoice_1}:
+ {}
+-
+ Invoice is created for specific sale order.
+-
+ !python {model: sale.make.invoice}: |
+ self.make_invoices(cr, uid, [ref("sale_make_invoice_1")], {"lang": 'en_US', "search_default_user_id":
+ 1, "tz": False, "active_model": 'sale.order', "active_ids": [ref("sale_order_so4")], "active_id":
+ ref("sale_order_so4"), })
+-
+ I verify that invoice regarding sale order has been created.
+-
+ !python {model: sale.order}: |
+ so = self.browse(cr, uid, ref("sale_order_so4"))
+ assert so.invoice_ids, "Invoices has not been generated for sale_order_so0"
+
+
\ No newline at end of file
diff --git a/addons/sale/test/so_make_line_invoice.yml b/addons/sale/test/so_make_line_invoice.yml
new file mode 100644
index 00000000000..de5782c8517
--- /dev/null
+++ b/addons/sale/test/so_make_line_invoice.yml
@@ -0,0 +1,342 @@
+-
+ In order to test the sale module in the Open-ERP, I need to configure details regarding product & customer.
+-
+ I am going to sell my Mobile products to the customer with name Cleartrail
+-
+ I create View Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_view0}:
+ close_method: none
+ code: View
+ name: View
+ sign: 1
+-
+ I create Income Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_income0}:
+ close_method: unreconciled
+ code: Income
+ name: Income
+ sign: 1
+-
+ I create Expense Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_expense0}:
+ close_method: unreconciled
+ code: Expense
+ name: Expense
+ sign: 1
+-
+ I create Cash Account Type.
+-
+ !record {model: account.account.type, id: account_account_type_cash0}:
+ close_method: balance
+ code: Cash
+ name: Cash
+ sign: 1
+-
+ I create Minimal Chart Account.
+-
+ !record {model: account.account, id: account_account_minimalchart0}:
+ code: '0'
+ company_id: base.main_company
+ currency_mode: current
+ name: Minimal Chart
+ parent_left: 1
+ parent_right: 12
+ type: view
+ user_type: account_account_type_view0
+-
+ I create Payable Account.
+-
+ !record {model: account.account, id: account_account_payable1}:
+ code: AP
+ company_id: base.main_company
+ currency_mode: current
+ name: Payable
+ parent_id: account_account_minimalchart0
+ parent_left: 2
+ parent_right: 3
+ reconcile: true
+ type: payable
+ user_type: account_account_type_expense0
+-
+ I create Receivable Account.
+-
+ !record {model: account.account, id: account_account_receivable0}:
+ code: AR
+ company_id: base.main_company
+ currency_mode: current
+ name: Receivable
+ parent_id: account_account_minimalchart0
+ parent_left: 4
+ parent_right: 5
+ reconcile: true
+ type: receivable
+ user_type: account_account_type_income0
+-
+ I create Cash Account.
+-
+ !record {model: account.account, id: account_account_cash0}:
+ code: C
+ company_id: base.main_company
+ currency_mode: current
+ name: Cash
+ parent_id: account_account_minimalchart0
+ parent_left: 6
+ parent_right: 7
+ type: other
+ user_type: account_account_type_cash0
+-
+ I create Purchases Account.
+-
+ !record {model: account.account, id: account_account_purchases0}:
+ code: P
+ company_id: base.main_company
+ currency_mode: current
+ name: Purchases
+ parent_id: account_account_minimalchart0
+ parent_left: 8
+ parent_right: 9
+ type: other
+ user_type: account_account_type_expense0
+-
+ I create Sales Account.
+-
+ !record {model: account.account, id: account_account_sales0}:
+ code: S
+ company_id: base.main_company
+ currency_mode: current
+ name: Sales
+ parent_id: account_account_minimalchart0
+ parent_left: 10
+ parent_right: 11
+ type: other
+ user_type: account_account_type_income0
+-
+ I create Purchase Journal.
+-
+ !record {model: account.journal, id: account_journal_purchasejournal0}:
+ code: PUJ
+ company_id: base.main_company
+ default_credit_account_id: account_account_purchases0
+ default_debit_account_id: account_account_purchases0
+ name: Purchase Journal
+ sequence_id: account.sequence_purchase_journal
+ type: purchase
+ view_id: account.account_journal_view
+-
+ I create Sale Journal.
+-
+ !record {model: account.journal, id: account_journal_salejournal0}:
+ code: SAJ
+ company_id: base.main_company
+ default_credit_account_id: account_account_sales0
+ default_debit_account_id: account_account_sales0
+ name: Sale Journal
+ sequence_id: account.sequence_sale_journal
+ type: sale
+ view_id: account.account_journal_view
+-
+ I create Bank Journal.
+-
+ !record {model: account.journal, id: account_journal_bankjournal0}:
+ code: BNK
+ company_id: base.main_company
+ default_credit_account_id: account_account_cash0
+ default_debit_account_id: account_account_cash0
+ name: Bank Journal
+ sequence_id: account.sequence_journal
+ type: cash
+ view_id: account.account_journal_bank_view
+-
+ I create ir.property for account payable.
+-
+ !record {model: ir.property, id: ir_property_propertyaccountexpensecateg0}:
+ company_id: base.main_company
+ fields_id: account.field_res_partner_property_account_payable
+ name: property_account_expense_categ
+ value_reference: account.account,5
+-
+ I create ir.property for account receivable.
+-
+ !record {model: ir.property, id: ir_property_propertyaccountincomecateg0}:
+ company_id: base.main_company
+ fields_id: account.field_res_partner_property_account_receivable
+ name: property_account_income_categ
+ value_reference: account.account,6
+-
+ I create Partner category Customers.
+-
+ !record {model: res.partner.category, id: res_partner_category_customers0}:
+ name: Customers
+-
+ I create Cleartrail Customer.
+-
+ !record {model: res.partner, id: res_partner_cleartrail0}:
+ category_id:
+ - res_partner_category_customers0
+ name: Cleartrail
+-
+ I create contact address for Cleartrail.
+-
+ !record {model: res.partner.address, id: res_partner_address_1}:
+ partner_id: res_partner_cleartrail0
+ street: onam plaza, 14 B palasia A B Road
+ type: contact
+-
+ I create invoice address for Cleartrail.
+-
+ !record {model: res.partner.address, id: res_partner_address_2}:
+ partner_id: res_partner_cleartrail0
+ street: sarda house 24 B palasia, A B Road
+ type: invoice
+-
+ I create delivery address for Cleartrail.
+-
+ !record {model: res.partner.address, id: res_partner_address_3}:
+ partner_id: res_partner_cleartrail0
+ street: sangam house 15 B palasia, A B Road
+ type: delivery
+-
+ Customer Cleartrail has specific instrument requirement regarding the stockable products.
+-
+ I define product category Mobile Products Sellable.
+-
+ !record {model: product.category, id: product_category_allproductssellable0}:
+ name: Mobile Products Sellable
+-
+ I define product category Mobile Services.
+-
+ !record {model: product.category, id: product_category_services0}:
+ name: Mobile Services
+-
+ I define LG Viewty Smart product template.
+-
+ !record {model: product.template, id: product_template_lgviewtysmart0}:
+ categ_id: product_category_allproductssellable0
+ cost_method: standard
+ list_price: 170.0
+ mes_type: fixed
+ name: LG Viewty Smart
+ procure_method: make_to_order
+ standard_price: 160.0
+ supply_method: produce
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+-
+ I define LG Viewty Smart product.
+-
+ !record {model: product.product, id: product_product_lgviewtysmart0}:
+ categ_id: product_category_allproductssellable0
+ cost_method: standard
+ list_price: 170.0
+ mes_type: fixed
+ name: LG Viewty Smart
+ pricelist_purchase: 'Default Purchase Pricelist (0.00) : 160.00\n'
+ pricelist_sale: 'Public Pricelist (0.00) : 170.00\n'
+ procure_method: make_to_order
+ property_account_expense: sale.account_account_payable1
+ property_account_income: sale.account_account_receivable0
+ seller_delay: '1'
+ standard_price: 160.0
+ supply_method: produce
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+-
+ I define New Chocolate Slider Mobile template.
+-
+ !record {model: product.template, id: product_template_newchocolateslidermobile0}:
+ categ_id: product_category_allproductssellable0
+ cost_method: standard
+ list_price: 200.0
+ mes_type: fixed
+ name: New Chocolate Slider Mobile
+ procure_method: make_to_order
+ standard_price: 189.0
+ supply_method: buy
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+-
+ I define New Chocolate Slider Mobile.
+-
+ !record {model: product.product, id: product_product_newchocolateslidermobile0}:
+ categ_id: product_category_allproductssellable0
+ cost_method: standard
+ list_price: 200.0
+ mes_type: fixed
+ name: New Chocolate Slider Mobile
+ pricelist_purchase: 'Default Purchase Pricelist (0.00) : 189.00\n'
+ pricelist_sale: 'Public Pricelist (0.00) : 200.00\n'
+ procure_method: make_to_order
+ property_account_expense: sale.account_account_payable1
+ property_account_income: sale.account_account_receivable0
+ seller_delay: '1'
+ standard_price: 189.0
+ supply_method: buy
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+-
+ I create a Sale Order for LG Viewty Smart for qty 500 having order_policy manual.
+-
+ !record {model: sale.order, id: sale_order_so3}:
+ date_order: '2010-05-12'
+ invoice_quantity: order
+ name: Test_SO003
+ order_line:
+ - name: New Chocolate Slider Mobile
+ price_unit: 200.0
+ product_uom: product.product_uom_unit
+ product_uom_qty: 500.0
+ state: draft
+ delay: 7.0
+ product_id: sale.product_product_newchocolateslidermobile0
+ product_uos_qty: 500.0
+ type: make_to_order
+ - name: LG Viewty Smart
+ price_unit: 170.0
+ product_uom: product.product_uom_unit
+ product_uom_qty: 500.0
+ state: draft
+ delay: 7.0
+ product_id: sale.product_product_lgviewtysmart0
+ product_uos_qty: 500.0
+ th_weight: 0.0
+ type: make_to_order
+ order_policy: manual
+ partner_id: sale.res_partner_cleartrail0
+ partner_invoice_id: sale.res_partner_address_2
+ partner_order_id: sale.res_partner_address_1
+ partner_shipping_id: sale.res_partner_address_3
+ picking_policy: direct
+ pricelist_id: product.list0
+ shop_id: sale.shop
+-
+ I confirm the Sale Order.
+-
+ !workflow {model: sale.order, action: order_confirm, ref: sale_order_so3}
+-
+ I create an invoice on sale order line.
+-
+ !record {model: sale.order.line.make.invoice, id: sale_order_line_make_invoice_0}:
+ {}
+-
+ invoice is created for specific sale order line.
+-
+ !python {model: sale.order.line.make.invoice}: |
+ sale_order_obj = self.pool.get('sale.order')
+ so = sale_order_obj.browse(cr, uid, ref("sale_order_so3"))
+ sol = so.order_line[0]
+ self.make_invoices(cr, uid, [ref("sale_order_line_make_invoice_0")], {"lang":
+ 'en_US', "active_model": "sale.order.line", "active_ids": [ref(sol.id)], "tz":
+ False, "active_id": ref(sol.id), })
+-
+ I verify that invoice regarding sale order line has been created.
+-
+ !python {model: sale.order}: |
+ so = self.browse(cr, uid, ref("sale_order_so3"))
+ assert so.invoice_ids, "Invoices has not been generated for sale_order_so0"
diff --git a/addons/sale/wizard/sale_make_invoice_advance.py b/addons/sale/wizard/sale_make_invoice_advance.py
index 2861a046205..34e996973d2 100644
--- a/addons/sale/wizard/sale_make_invoice_advance.py
+++ b/addons/sale/wizard/sale_make_invoice_advance.py
@@ -35,23 +35,23 @@ class sale_advance_payment_inv(osv.osv_memory):
'qtty' : lambda *a: 1
}
def create_invoices(self, cr, uid, ids, context={}):
- """
+ """
To create invoices.
-
+
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
- @param ids: the ID or list of IDs if we want more than one
- @param context: A standard dictionary
-
- @return:
-
- """
+ @param ids: the ID or list of IDs if we want more than one
+ @param context: A standard dictionary
+
+ @return:
+
+ """
list_inv = []
obj_sale = self.pool.get('sale.order')
obj_lines = self.pool.get('account.invoice.line')
inv_obj = self.pool.get('account.invoice')
-
+
for sale_adv_obj in self.browse(cr, uid, ids):
for sale in obj_sale.browse(cr, uid, context['active_ids']):
address_contact = False
@@ -93,7 +93,7 @@ class sale_advance_payment_inv(osv.osv_memory):
'payment_term':sale.payment_term.id,
'fiscal_position': sale.fiscal_position.id or sale.partner_id.property_account_position.id
}
-
+
inv_id = inv_obj.create(cr, uid, inv)
for inv in sale.invoice_ids:
@@ -119,6 +119,8 @@ class sale_advance_payment_inv(osv.osv_memory):
'tax_id': [(6, 0, val['value']['invoice_line_tax_id'])],
}, context)
+ context.update({'invoice_id':list_inv})
+
return {#'invoice_ids':list_inv,
'name': 'Open Invoice',
'view_type': 'form',
@@ -126,7 +128,7 @@ class sale_advance_payment_inv(osv.osv_memory):
'res_model': 'sale.open.invoice',
'type': 'ir.actions.act_window',
'target': 'new',
- 'context': "{'invoice_ids'=%s}" % (list_inv)
+ 'context':context
}
sale_advance_payment_inv()
@@ -138,39 +140,49 @@ class sale_open_invoice(osv.osv_memory):
}
def open_invoice(self, cr, uid, ids, context):
- """
+
+ """
To open invoice.
-
+
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
- @param ids: the ID or list of IDs if we want more than one
- @param context: A standard dictionary
-
- @return:
-
- """
+ @param ids: the ID or list of IDs if we want more than one
+ @param context: A standard dictionary
+
+ @return:
+
+ """
+ record_id = context and context.get('active_id', False) or False
+
mod_obj = self.pool.get('ir.model.data')
+ obj_inv = self.pool.get('account.invoice')
invoices = []
- #TODO: Can not get invoice ids here
+ invoice = obj_inv.browse(cr, uid, record_id, context=context)
+
for advance_pay in self.browse(cr, uid, ids):
result = mod_obj._get_id(cr, uid, 'account', 'view_account_invoice_filter')
id = mod_obj.read(cr, uid, result, ['res_id'])
- model_data_ids = mod_obj.search(cr, uid,
- [('model', '=', 'ir.ui.view'), ('name', '=', 'invoice_form')])
- resource_id = mod_obj.read(cr, uid, model_data_ids,
- fields=['res_id'])[0]['res_id']
+ form_id = mod_obj._get_id(cr, uid, 'account', 'invoice_form')
+ form_res = mod_obj.browse(cr, uid, form_id, context=context).res_id
+ tree_id = mod_obj._get_id(cr, uid, 'account', 'invoice_tree')
+ tree_res = mod_obj.browse(cr, uid, tree_id, context=context).res_id
return {
# 'domain': "[('id','in', ["+','.join(map(str, invoices))+"])]", # TODO
'name': 'Invoices',
'view_type': 'form',
- 'view_mode': 'tree,form',
+ 'view_mode': 'form,tree',
'res_model': 'account.invoice',
- 'views': [(False, 'tree'), (resource_id, 'form')],
+ 'res_id': int(context['invoice_id'][0]),
+ 'view_id': False,
+ 'views': [(form_res, 'form'), (tree_res, 'tree')],
'context': "{'type':'out_invoice'}",
'type': 'ir.actions.act_window',
- 'search_view_id': id['res_id']
}
+
+
+
+
sale_open_invoice()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/sale/wizard/sale_make_invoice_advance.xml b/addons/sale/wizard/sale_make_invoice_advance.xml
index 5fc8b993921..a4f48554166 100644
--- a/addons/sale/wizard/sale_make_invoice_advance.xml
+++ b/addons/sale/wizard/sale_make_invoice_advance.xml
@@ -1,59 +1,50 @@
-
- Sale Advance Payment Invoive
+
+ Deposit Invoicesale.advance.payment.invform
-
+
+
-
- sale_journal.picking.journal.tree
- sale_journal.picking.journal
- tree
-
-
-
-
-
-
-
-
-
-
+
+ sale_journal.picking.journal.tree
+ sale_journal.picking.journal
+ tree
+
+
+
+
+
+
+
+
+
+
-
- sale_journal.picking.journal.search
- sale_journal.picking.journal
- search
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ sale_journal.picking.journal.search
+ sale_journal.picking.journal
+ search
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
- Picking Journals
- sale_journal.picking.journal
- form
- tree,form
-
-
+
+ Picking Journals
+ sale_journal.picking.journal
+ form
+ tree,form
+
+
-
+
-
- Picking by invoice_method
- sale_journal.invoice.type
- ir.actions.act_window
- tree
-
+
+ Picking by invoice_method
+ sale_journal.invoice.type
+ ir.actions.act_window
+ tree
+
-
- Picking to invoice
- stock.picking
- ir.actions.act_window
- form
- tree,form
- [('state','=','done'),('invoice_state','=','2binvoiced'),('invoice_type_id','=',active_id)]
-
+
+ Picking to invoice
+ stock.picking
+ ir.actions.act_window
+ form
+ tree,form
+ [('state','=','done'),('invoice_state','=','2binvoiced'),('invoice_type_id','=',active_id)]
+
-
- tree_but_open
- sale_journal.invoice.type
- Picking to invoice
-
-
-
+
+ tree_but_open
+ sale_journal.invoice.type
+ Picking to invoice
+
+
+
diff --git a/addons/sale_mrp/__init__.py b/addons/sale_mrp/__init__.py
new file mode 100644
index 00000000000..c47eb12b3f3
--- /dev/null
+++ b/addons/sale_mrp/__init__.py
@@ -0,0 +1,24 @@
+# -*- 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_mrp
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/sale_mrp/__openerp__.py b/addons/sale_mrp/__openerp__.py
new file mode 100644
index 00000000000..9ac55911983
--- /dev/null
+++ b/addons/sale_mrp/__openerp__.py
@@ -0,0 +1,44 @@
+# -*- 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': 'Sales and MRP Management',
+ 'version': '1.0',
+ 'category': 'Generic Modules/Sales & MRP',
+ 'description': """
+ This module provides facility to the user to install mrp and sale modules
+ at a time. It is basically used when we want to keep track of production
+ orders generated from sale orders.
+ """,
+ 'author': 'Tiny',
+ 'website': 'http://www.openerp.com',
+ 'depends': ['mrp', 'sale'],
+ 'init_xml': [],
+ 'update_xml': [
+ 'sale_mrp_view.xml',
+ ],
+ 'demo_xml': [],
+ 'installable': True,
+ 'active': False,
+ 'certificate': '',
+}
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/sale/mrp.py b/addons/sale_mrp/sale_mrp.py
similarity index 81%
rename from addons/sale/mrp.py
rename to addons/sale_mrp/sale_mrp.py
index bb16a65425a..4f52cb7dd9b 100644
--- a/addons/sale/mrp.py
+++ b/addons/sale_mrp/sale_mrp.py
@@ -23,10 +23,14 @@
from osv import osv, fields
class mrp_production(osv.osv):
-
_inherit = 'mrp.production'
def _ref_calc(self, cr, uid, ids, field_names=None, arg=False, context={}):
+ """ Finds reference of sale order for production order.
+ @param field_names: Names of fields.
+ @param arg: User defined arguments
+ @return: Dictionary of values.
+ """
if not field_names:
field_names=[]
res = {}
@@ -65,4 +69,11 @@ class mrp_production(osv.osv):
res[production['id']] = move.sale_line_id and move.sale_line_id.order_id.client_order_ref or False
return res
-mrp_production()
\ No newline at end of file
+ _columns = {
+ 'sale_name': fields.function(_ref_calc, method=True, multi='sale_name', type='char', string='Sale Name', help='Indicate the name of sale order.'),
+ 'sale_ref': fields.function(_ref_calc, method=True, multi='sale_ref', type='char', string='Sale Reference', help='Indicate the Customer Reference from sale order.'),
+ }
+
+mrp_production()
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/sale_mrp/sale_mrp_view.xml b/addons/sale_mrp/sale_mrp_view.xml
new file mode 100644
index 00000000000..a595e9471be
--- /dev/null
+++ b/addons/sale_mrp/sale_mrp_view.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ mrp.production.form
+ mrp.production
+
+ form
+
+
+
+
+
+
+
+
+
diff --git a/addons/scrum/scrum.py b/addons/scrum/scrum.py
index 2e3a0ca3fcb..698b490f1a2 100644
--- a/addons/scrum/scrum.py
+++ b/addons/scrum/scrum.py
@@ -28,8 +28,8 @@ import re
class scrum_project(osv.osv):
_inherit = 'project.project'
_columns = {
- 'product_owner_id': fields.many2one('res.users', 'Product Owner'),
- 'sprint_size': fields.integer('Sprint Days',help="Number of days allocated for sprint"),
+ 'product_owner_id': fields.many2one('res.users', 'Product Owner', help="The person who is responsible for the product"),
+ 'sprint_size': fields.integer('Sprint Days', help="Number of days allocated for sprint"),
'scrum': fields.integer('Is a Scrum Project'),
}
_defaults = {
diff --git a/addons/scrum/scrum_view.xml b/addons/scrum/scrum_view.xml
index be16ecfa7e5..70c3e82ee56 100644
--- a/addons/scrum/scrum_view.xml
+++ b/addons/scrum/scrum_view.xml
@@ -137,8 +137,8 @@
-
-
+
+
-
+
@@ -184,7 +184,7 @@
scrum.sprinttree
-
+
@@ -266,8 +266,8 @@
-
-
+
+
@@ -352,10 +352,10 @@
-
+
-
+
diff --git a/addons/scrum/security/ir.model.access.csv b/addons/scrum/security/ir.model.access.csv
index a52a9c2f3f2..76ba229e952 100644
--- a/addons/scrum/security/ir.model.access.csv
+++ b/addons/scrum/security/ir.model.access.csv
@@ -1,7 +1,9 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
-"access_scrum_sprint","scrum.sprint","model_scrum_sprint","project.group_project_user",1,,,
+"access_scrum_sprint","scrum.sprint","model_scrum_sprint","project.group_project_user",1,0,0,0
"access_scrum_product_backlog","scrum.product.backlog","model_scrum_product_backlog","project.group_project_user",1,1,1,1
-"access_scrum_meeting","scrum.meeting","model_scrum_meeting","project.group_project_user",1,,,
+"access_scrum_meeting","scrum.meeting","model_scrum_meeting","project.group_project_user",1,0,0,0
"access_scrum_meeting_manager","scrum.meeting.manager","model_scrum_meeting","project.group_project_manager",1,1,1,1
"access_scrum_sprint_manager","scrum.sprint.manager","model_scrum_sprint","project.group_project_manager",1,1,1,1
"access_scrum_product_backlog_manager","scrum.product.backlog manager","model_scrum_product_backlog","project.group_project_manager",1,1,1,1
+"access_product_uom_project_manager","product.uom project manager","product.model_product_uom","project.group_project_manager",1,1,1,1
+"access_product_uom_project_user","product.uom project user","product.model_product_uom","project.group_project_user",1,0,0,0
diff --git a/addons/share/__init__.py b/addons/share/__init__.py
new file mode 100644
index 00000000000..eff88be137d
--- /dev/null
+++ b/addons/share/__init__.py
@@ -0,0 +1,22 @@
+# -*- 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 share
+import wizard
diff --git a/addons/share/__openerp__.py b/addons/share/__openerp__.py
new file mode 100644
index 00000000000..e6762e91ef2
--- /dev/null
+++ b/addons/share/__openerp__.py
@@ -0,0 +1,44 @@
+# -*- 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" : "Share Management",
+ "version" : "1.1",
+ "depends" : ["base"],
+ "author" : "Tiny",
+ "category": 'Generic Modules',
+ "description": """The goal is to implement a generic sharing mechanism, where user of OpenERP
+can share data from OpenERP to their colleagues, customers, or friends.
+The system will work by creating new users and groups on the fly, and by
+combining the appropriate access rights and ir.rules to ensure that the /shared
+users/ will only have access to the correct data.
+ """,
+ 'website': 'http://www.openerp.com',
+ 'init_xml': [],
+ 'update_xml': [
+ 'share_view.xml',
+ 'wizard/share_wizard_view.xml'
+ ],
+ 'installable': True,
+ 'active': False,
+}
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/share/share.py b/addons/share/share.py
new file mode 100644
index 00000000000..6e3c4932a1e
--- /dev/null
+++ b/addons/share/share.py
@@ -0,0 +1,36 @@
+# -*- 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, orm
+class res_groups(osv.osv):
+ _name = "res.groups"
+ _inherit = 'res.groups'
+ _columns = {
+ 'share': fields.boolean('Share')
+ }
+res_groups()
+
+class res_users(osv.osv):
+ _name = 'res.users'
+ _inherit = 'res.users'
+ _columns = {
+ 'share': fields.boolean('Share')
+ }
+res_users()
diff --git a/addons/share/share_view.xml b/addons/share/share_view.xml
new file mode 100644
index 00000000000..24736b3d53a
--- /dev/null
+++ b/addons/share/share_view.xml
@@ -0,0 +1,27 @@
+
+
+
+
+ res.groups.form
+ res.groups
+ form
+
+
+
+
+
+
+
+
+ res.users.form
+ res.users
+ form
+
+
+
+
+
+
+
+
+
diff --git a/addons/share/wizard/__init__.py b/addons/share/wizard/__init__.py
new file mode 100644
index 00000000000..b906abf5e56
--- /dev/null
+++ b/addons/share/wizard/__init__.py
@@ -0,0 +1,22 @@
+# -*- 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 share_wizard
diff --git a/addons/share/wizard/share_wizard.py b/addons/share/wizard/share_wizard.py
new file mode 100644
index 00000000000..722fa9809b0
--- /dev/null
+++ b/addons/share/wizard/share_wizard.py
@@ -0,0 +1,495 @@
+# -*- 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, fields
+from tools.translate import _
+import tools
+
+def _generate_random_number():
+ import random
+ RANDOM_PASS_CHARACTERS = [chr(x) for x in range(48,58) + range(97,123) + range(65,91)]
+ RANDOM_PASS_CHARACTERS.remove('l') #lowercase l, easily mistaken as one or capital i
+ RANDOM_PASS_CHARACTERS.remove('I') #uppercase i, easily mistaken as one or lowercase l
+ RANDOM_PASS_CHARACTERS.remove('O') #uppercase o, mistaken with zero
+ RANDOM_PASS_CHARACTERS.remove('o') #lowercase o, mistaken with zero
+ RANDOM_PASS_CHARACTERS.remove('0') #zero, mistaken with o-letter
+ def generate_random_pass():
+ pass_chars = RANDOM_PASS_CHARACTERS[:]
+ random.shuffle(pass_chars)
+ return ''.join(pass_chars[0:10])
+ return generate_random_pass()
+
+class share_create(osv.osv_memory):
+ _name = 'share.create'
+ _description = 'Create share'
+
+ def _access(self, cr, uid, ids, field_name, arg, context=None):
+ if context is None:
+ context = {}
+ res = {}
+ action_id = context.get('action_id', False)
+ access_obj = self.pool.get('ir.model.access')
+ action_obj = self.pool.get('ir.actions.act_window')
+ model_obj = self.pool.get('ir.model')
+ user_obj = self.pool.get('res.users')
+ current_user = user_obj.browse(cr, uid, uid)
+ access_ids = []
+ if action_id:
+ action = action_obj.browse(cr, uid, action_id, context=context)
+ active_model_ids = model_obj.search(cr, uid, [('model','=',action.res_model)])
+ active_model_id = active_model_ids and active_model_ids[0] or False
+ access_ids = access_obj.search(cr, uid, [
+ ('group_id','in',map(lambda x:x.id, current_user.groups_id)),
+ ('model_id','',active_model_id)])
+ for rec_id in ids:
+ write_access = False
+ read_access = False
+ for access in access_obj.browse(cr, uid, access_ids, context=context):
+ if access.perm_write:
+ write_access = True
+ if access.perm_read:
+ read_access = True
+ res[rec_id]['write_access'] = write_access
+ res[rec_id]['read_access'] = read_access
+ return res
+
+ _columns = {
+ 'action_id': fields.many2one('ir.actions.act_window', 'Action', required=True),
+ 'domain': fields.char('Domain', size=64),
+ 'user_type': fields.selection( [ ('existing','Existing'),('new','New')],'User Type'),
+ 'user_ids': fields.many2many('res.users', 'share_user_rel', 'share_id','user_id', 'Share Users'),
+ 'new_user': fields.text("New user"),
+ 'access_mode': fields.selection([('readwrite','READ & WRITE'),('readonly','READ ONLY')],'Access Mode'),
+ 'write_access': fields.function(_access, method=True, string='Write Access',type='boolean', multi='write_access'),
+ 'read_access': fields.function(_access, method=True, string='Write Access',type='boolean', multi='read_access'),
+ }
+ _defaults = {
+ 'user_type' : 'existing',
+ 'domain': '[]',
+ 'access_mode': 'readonly'
+
+ }
+
+ def default_get(self, cr, uid, fields, context=None):
+ """
+ To get default values for the object.
+ """
+
+ res = super(share_create, self).default_get(cr, uid, fields, context=context)
+ if not context:
+ context={}
+ action_id = context.get('action_id', False)
+ domain = context.get('domain', '[]')
+
+
+ if 'action_id' in fields:
+ res['action_id'] = action_id
+ if 'domain' in fields:
+ res['domain'] = domain
+ return res
+
+ def do_step_1(self, cr, uid, ids, context=None):
+ """
+ This action to excute step 1
+
+ """
+ if not context:
+ context = {}
+
+ data_obj = self.pool.get('ir.model.data')
+
+ step1_form_view = data_obj._get_id(cr, uid, 'share', 'share_step1_form')
+
+ if step1_form_view:
+ step1_form_view_id = data_obj.browse(cr, uid, step1_form_view, context=context).res_id
+
+ step1_id = False
+ for this in self.browse(cr, uid, ids, context=context):
+ vals ={
+ 'domain': this.domain,
+ 'action_id': this.action_id and this.action_id.id or False,
+ }
+ step1_id = this.id
+
+ context.update(vals)
+ value = {
+ 'name': _('Step:2 Sharing Wizard'),
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'share.create',
+ 'view_id': False,
+ 'res_id': step1_id,
+ 'views': [(step1_form_view_id, 'form'), (False, 'tree'), (False, 'calendar'), (False, 'graph')],
+ 'type': 'ir.actions.act_window',
+ 'context': context,
+ 'target': 'new'
+ }
+ return value
+
+
+ def do_step_2(self, cr, uid, ids, context=None):
+ """
+ This action to excute step 2
+
+ """
+ if not context:
+ context = {}
+
+ data_obj = self.pool.get('ir.model.data')
+
+ step2_form_view = data_obj._get_id(cr, uid, 'share', 'share_step2_form')
+
+ if step2_form_view:
+ step2_form_view_id = data_obj.browse(cr, uid, step2_form_view, context=context).res_id
+
+ step1_id = False
+ for this in self.browse(cr, uid, ids, context=context):
+ vals ={
+ 'user_type': this.user_type,
+ 'existing_user_ids': map(lambda x:x.id, this.user_ids),
+ 'new_user': this.new_user,
+ }
+
+ context.update(vals)
+ value = {
+ 'name': _('Step:3 Sharing Wizard'),
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'share.create',
+ 'view_id': False,
+ 'views': [(step2_form_view_id, 'form'), (False, 'tree'), (False, 'calendar'), (False, 'graph')],
+ 'type': 'ir.actions.act_window',
+ 'context': context,
+ 'target': 'new'
+ }
+ return value
+
+
+ def do_step_3(self, cr, uid, ids, context=None):
+ """
+ This action to excute step 3
+
+ """
+ if not context:
+ context = {}
+
+ for this in self.browse(cr, uid, ids, context=context):
+ vals ={
+ 'access_mode': this.access_mode,
+ }
+
+ context.update(vals)
+
+ group_obj = self.pool.get('res.groups')
+ user_obj = self.pool.get('res.users')
+ fields_obj = self.pool.get('ir.model.fields')
+ model_access_obj = self.pool.get('ir.model.access')
+ model_obj = self.pool.get('ir.model')
+ rule_obj = self.pool.get('ir.rule')
+ action_obj = self.pool.get('ir.actions.act_window')
+
+ new_users = context.get('new_user', False)
+ action_id = context.get('action_id', False)
+ user_type = context.get('user_type', False)
+ access_mode = context.get('access_mode', False)
+ action = action_obj.browse(cr, uid, action_id, context=context)
+ active_model = action.res_model
+
+ active_id = False #TODO: Pass record id of res_model of action
+ existing_user_ids = context.get('existing_user_ids', False)
+ domain = eval(context.get('domain', '[]'))
+
+ # Create Share Group
+ share_group_name = '%s: %s' %('Sharing', active_model)
+ group_ids = group_obj.search(cr, uid, [('name','=',share_group_name)])
+ group_id = group_ids and group_ids[0] or False
+ if not group_id:
+ group_id = group_obj.create(cr, uid, {'name': share_group_name, 'share': True})
+ else:
+ group = group_obj.browse(cr, uid, group_id, context=context)
+ if not group.share:
+ raise osv.except_osv(_('Error'), _("Share Group is exits without sharing !"))
+
+ # Create new user
+
+ current_user = user_obj.browse(cr, uid, uid)
+ user_ids = []
+ if user_type == 'new' and new_users:
+ for new_user in new_users.split('\n'):
+ password = _generate_random_number()
+ user_id = user_obj.create(cr, uid, {
+ 'login': new_user,
+ 'password': password,
+ 'name': new_user,
+ 'user_email': new_user,
+ 'groups_id': [(6,0,[group_id])],
+ 'action_id': action_id,
+ 'share': True,
+ 'company_id': current_user.company_id and current_user.company_id.id})
+ user_ids.append(user_id)
+ context['new_user_ids'] = user_ids
+
+ # Modify existing user
+ if user_type == 'existing':
+ user_obj.write(cr, uid, existing_user_ids , {
+ 'groups_id': [(4,group_id)],
+ 'action_id': action_id
+ })
+
+
+ #ACCESS RIGHTS / IR.RULES COMPUTATION
+
+ active_model_ids = model_obj.search(cr, uid, [('model','=',active_model)])
+ active_model_id = active_model_ids and active_model_ids[0] or False
+
+ def _get_relation(model_id, ttypes, new_obj=[]):
+ obj = []
+ models = map(lambda x:x[1].model, new_obj)
+ field_ids = fields_obj.search(cr, uid, [('model_id','=',model_id),('ttype','in', ttypes)])
+ for field in fields_obj.browse(cr, uid, field_ids, context=context):
+ if field.relation not in models:
+ relation_model_ids = model_obj.search(cr, uid, [('model','=',field.relation)])
+ relation_model_id = relation_model_ids and relation_model_ids[0] or False
+ relation_model = model_obj.browse(cr, uid, relation_model_id, context=context)
+ obj.append((field.relation_field, relation_model))
+
+ if relation_model_id != model_id and field.ttype in ['one2many', 'many2many']:
+ obj += _get_relation(relation_model_id, [field.ttype], obj)
+
+ return obj
+
+ active_model = model_obj.browse(cr, uid, active_model_id, context=context)
+ obj0 = [(None, active_model)]
+ obj1 = _get_relation(active_model_id, ['one2many'])
+ obj2 = _get_relation(active_model_id, ['one2many', 'many2many'])
+ obj3 = _get_relation(active_model_id, ['many2one'])
+ for rel_field, model in obj1:
+ obj3 += _get_relation(model.id, ['many2one'])
+
+ current_user = user_obj.browse(cr, uid, uid, context=context)
+ if access_mode == 'readonly':
+ res = []
+ # intersect with read access rights of user running the
+ # wizard, to avoid adding more access than current
+ for group in current_user.groups_id:
+ for access_control in group.model_access:
+ if access_control.model_id.id in res:
+ continue
+ if access_control.perm_read:
+ res.append(access_control.model_id.id)
+ model_access_obj.create(cr, uid, {
+ 'name': 'Read Access of group %s on %s model'%(share_group_name, access_control.model_id.name),
+ 'model_id' : access_control.model_id.id,
+ 'group_id' : group_id,
+ 'perm_read' : True
+ })
+ res = []
+ for rel_field, model in obj0+obj1+obj2+obj3:
+ if model.id in res:
+ continue
+ res.append(model.id)
+ model_access_obj.create(cr, uid, {
+ 'name': 'Read Access of group %s on %s model'%(share_group_name, model.name),
+ 'model_id' : model.id,
+ 'group_id' : group_id,
+ 'perm_read' : True
+ })
+ if access_mode == 'readwrite':
+ res = []
+ for rel_field, model in obj0+obj1:
+ if model.id in res:
+ continue
+ res.append(model.id)
+ model_access_obj.create(cr, uid, {
+ 'name': 'Write Access of group %s on %s model'%(share_group_name, model.name),
+ 'model_id' : model.id,
+ 'group_id' : group_id,
+ 'perm_read' : True,
+ 'perm_write' : True,
+ 'perm_unlink' : True,
+ 'perm_create' : True,
+ })
+ # intersect with access rights of user
+ # running the wizard, to avoid adding more access than current
+
+ for group in current_user.groups_id:
+ for access_control in group.model_access:
+ if access_control.model_id.id in res:
+ continue
+ if access_control.perm_read:
+ res.append(access_control.model_id.id)
+ model_access_obj.create(cr, uid, {
+ 'name': 'Read Access of group %s on %s model'%(share_group_name, access_control.model_id.name),
+ 'model_id' : access_control.model_id.id,
+ 'group_id' : group_id,
+ 'perm_read' : True
+ })
+ for rel_field, model in obj2+obj3:
+ if model.id in res:
+ continue
+ res.append(model.id)
+ model_access_obj.create(cr, uid, {
+ 'name': 'Read Access of group %s on %s model'%(share_group_name, model.name),
+ 'model_id' : model.id,
+ 'group_id' : group_id,
+ 'perm_read' : True
+ })
+ #
+ # And on OBJ0, OBJ1, OBJ2, OBJ3: add all rules from groups of the user
+ # that is sharing in the many2many of the rules on the new group
+ # (rule must be copied instead of adding it if it contains a reference to uid
+ # or user.xxx so it can be replaced correctly)
+
+ for group in current_user.groups_id:
+ res = []
+ for rel_field, model in obj0+obj1+obj2+obj3:
+ if model.id in res:
+ continue
+ res.append(model.id)
+ for rule in group.rule_groups:
+ if rule.model_id == model.id:
+ rule_obj.copy(cr, uid, rule.id, default={
+ 'name': '%s-%s'%(share_group_name, model.model),
+ 'groups': [(6,0,[group_id])]}, context=context)
+
+ rule_obj.create(cr, uid, {
+ 'name': '%s-%s'%(share_group_name, active_model.model),
+ 'model_id': active_model.id,
+ 'domain_force': domain,
+ 'groups': [(6,0,[group_id])]
+ })
+ for rel_field, model in obj1:
+ obj1_domain = []
+ for opr1, opt, opr2 in domain:
+ new_opr1 = '%s.%s'%(rel_field, opr1)
+ obj1_domain.append((new_opr1, opt, opr2))
+
+ rule_obj.create(cr, uid, {
+ 'name': '%s-%s'%(share_group_name, model.model),
+ 'model_id': model.id,
+ 'domain_force': obj1_domain,
+ 'groups': [(6,0,[group_id])]
+ })
+ context['share_model'] = active_model.model
+ context['share_rec_id'] = active_id
+
+
+ data_obj = self.pool.get('ir.model.data')
+
+ form_view = data_obj._get_id(cr, uid, 'share', 'share_result_form')
+ form_view_id = False
+ if form_view:
+ form_view_id = data_obj.browse(cr, uid, form_view, context=context).res_id
+
+
+ value = {
+ 'name': _('Step:4 Share Users Detail'),
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'share.result',
+ 'view_id': False,
+ 'views': [(form_view_id, 'form'), (False, 'tree'), (False, 'calendar'), (False, 'graph')],
+ 'type': 'ir.actions.act_window',
+ 'context': context,
+ 'target': 'new'
+ }
+ return value
+share_create()
+
+
+class share_result(osv.osv_memory):
+ _name = "share.result"
+ _columns = {
+ 'users': fields.text("Users", readonly=True),
+ }
+
+
+
+ def do_send_email(self, cr, uid, ids, context=None):
+ user_obj = self.pool.get('res.users')
+ if not context:
+ context={}
+ existing_user_ids = context.get('existing_user_ids', [])
+ new_user_ids = context.get('new_user_ids', [])
+ share_url = tools.config.get('share_root_url', False)
+ user = user_obj.browse(cr, uid, uid, context=context)
+ for share_user in user_obj.browse(cr, uid, new_user_ids+existing_user_ids, context=context):
+ email_to = share_user.user_email
+ subject = '%s wants to share private data with you' %(user.name)
+ body = """
+ Dear,
+
+ %s wants to share private data from OpenERP with you!
+ """%(user.name)
+ if share_url:
+ body += """
+ To view it, you can access the following URL:
+ %s
+ """%(user.name, share_url)
+ if share_user.id in new_user_ids:
+ body += """
+ You may use the following login and password to get access to this
+ protected area:
+ login: %s
+ password: %s
+ """%(user.login, user.password)
+ elif share_user.id in existing_user_ids:
+ body += """
+ You may use your existing login and password to get access to this
+ additional data. As a reminder, your login is %s.
+ """%(user.name)
+
+ flag = tools.email_send(
+ user.user_email,
+ email_to,
+ subject,
+ body
+ )
+ return flag
+
+
+ def default_get(self, cr, uid, fields, context=None):
+ """
+ To get default values for the object.
+ """
+
+ res = super(share_result, self).default_get(cr, uid, fields, context=context)
+ user_obj = self.pool.get('res.users')
+ if not context:
+ context={}
+ existing_user_ids = context.get('existing_user_ids', [])
+ new_user_ids = context.get('new_user_ids', [])
+ share_url = tools.config.get('share_root_url', False)
+ if 'users' in fields:
+ users = []
+ for user in user_obj.browse(cr, uid, new_user_ids):
+ txt = 'Login: %s Password: %s' %(user.login, user.password)
+ if share_url:
+ txt += ' Share URL: %s' %(share_url)
+ users.append(txt)
+ for user in user_obj.browse(cr, uid, existing_user_ids):
+ txt = 'Login: %s' %(user.login)
+ if share_url:
+ txt += ' Share URL: %s' %(share_url)
+ users.append(txt)
+ res['users'] = '\n'.join(users)
+ return res
+
+share_result()
diff --git a/addons/share/wizard/share_wizard_view.xml b/addons/share/wizard/share_wizard_view.xml
new file mode 100644
index 00000000000..159583eecbb
--- /dev/null
+++ b/addons/share/wizard/share_wizard_view.xml
@@ -0,0 +1,106 @@
+
+
+
+
+
+ share.step0.form
+ share.create
+ form
+
+
@@ -1041,14 +1035,15 @@
-
-
+
+
+
+
-
-
-
+
+
@@ -1118,7 +1113,7 @@
-
+
@@ -1181,10 +1176,7 @@
-
-
-
-
+
@@ -1304,7 +1296,7 @@
{'contact_display': 'partner',"search_default_confirmed":1}
-
+ stock.move.tree
@@ -1317,7 +1309,15 @@
+
+
@@ -1344,7 +1344,8 @@
-
+
+
@@ -1374,9 +1375,6 @@
-
-
-
@@ -1447,19 +1445,25 @@
-
+
-
-
+
+
+
+
-
-
@@ -1479,7 +1483,8 @@
-
+
+
@@ -1510,9 +1515,6 @@
-
-
-
@@ -1526,25 +1528,26 @@
-
-
-
+
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
-
-
+
@@ -1556,7 +1559,7 @@
ir.actions.act_windowformtree,form
- [('picking_id','!=',False),('picking_id.type','=','in')]
+ [('picking_id.type','=','in')]{"search_default_receive":1}
@@ -1734,5 +1737,60 @@
+
+ Customers Packings
+ stock.picking
+ ir.actions.act_window
+ form
+ tree,form,calendar
+ [('type','=','out')]
+ {'contact_display': 'partner',"search_default_available":1}
+
+
+
+
+ tree
+
+
+
+
+
+ form
+
+
+
+
+
+ calendar
+
+
+
+
+ Outgoing Products
+ stock.move
+ ir.actions.act_window
+ form
+ tree,form
+ [('picking_id','!=',False),('picking_id.type','=','out')]
+
+ {"search_default_receive":1}
+
+
+
+
+
+ tree
+
+
+
+
+
+ form
+
+
+
+
+
+
diff --git a/addons/stock/test/stock_test.yml b/addons/stock/test/stock_test.yml
index 6a9bf3ff9f3..38ecddffb91 100644
--- a/addons/stock/test/stock_test.yml
+++ b/addons/stock/test/stock_test.yml
@@ -288,6 +288,7 @@
In Order to test the picking I create picking with move lines.
-
!record {model: stock.picking, id: stock_picking_0}:
+ name: test_picking
address_id: res_partner_address_0
company_id: base.main_company
date: '2010-05-11 15:18:52'
diff --git a/addons/stock/wizard/stock_change_standard_price.py b/addons/stock/wizard/stock_change_standard_price.py
index d83b2c1d140..149b0b04e84 100644
--- a/addons/stock/wizard/stock_change_standard_price.py
+++ b/addons/stock/wizard/stock_change_standard_price.py
@@ -34,17 +34,13 @@ class change_standard_price(osv.osv_memory):
}
def default_get(self, cr, uid, fields, context):
- """
- To get default values for the object.
-
+ """ To get default values for the object.
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param fields: List of fields for which we want default values
@param context: A standard dictionary
-
@return: A dictionary which of fields with values.
-
"""
product_pool = self.pool.get('product.product')
product_obj = product_pool.browse(cr, uid, context.get('active_id', False))
@@ -68,6 +64,16 @@ class change_standard_price(osv.osv_memory):
return res
def onchange_price(self, cr, uid, ids, new_price, context = {}):
+ """ Sets stock input and output account according to the difference
+ of old price and new price.
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: List of IDs selected
+ @param new_price: Changed price
+ @param context: A standard dictionary
+ @return: Dictionary of values
+ """
product_obj = self.pool.get('product.product').browse(cr, uid, context.get('active_id', False))
price = product_obj.standard_price
diff = price - new_price
@@ -77,18 +83,14 @@ class change_standard_price(osv.osv_memory):
return {'value' : {'enable_stock_in_out_acc':False}}
def change_price(self, cr, uid, ids, context):
- """
- Changes the Standard Price of Product.
- And creates an account move accordingly.
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param ids: List of IDs selected
- @param context: A standard dictionary
-
- @return:
-
+ """ Changes the Standard Price of Product.
+ And creates an account move accordingly.
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: List of IDs selected
+ @param context: A standard dictionary
+ @return:
"""
rec_id = context and context.get('active_id', False)
assert rec_id, _('Active ID is not set in Context')
diff --git a/addons/stock/wizard/stock_fill_inventory.py b/addons/stock/wizard/stock_fill_inventory.py
index 3247628657a..3742349425c 100644
--- a/addons/stock/wizard/stock_fill_inventory.py
+++ b/addons/stock/wizard/stock_fill_inventory.py
@@ -34,21 +34,17 @@ class stock_fill_inventory(osv.osv_memory):
_description = "Fill Inventory"
_columns = {
'location_id': fields.many2one('stock.location', 'Location', required=True),
- 'recursive': fields.boolean("Include all childs for the location"),
- }
+ 'recursive': fields.boolean("Include all children for the location"),
+ }
def fill_inventory(self, cr, uid, ids, context):
- """
- To fill stock inventory according to products available in the selected locations..
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param ids: the ID or list of IDs if we want more than one
- @param context: A standard dictionary
-
- @return:
-
+ """ To fill stock inventory according to products available in the selected locations.
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: the ID or list of IDs if we want more than one
+ @param context: A standard dictionary
+ @return:
"""
inventory_line_obj = self.pool.get('stock.inventory.line')
location_obj = self.pool.get('stock.location')
diff --git a/addons/stock/wizard/stock_inventory_line_split.py b/addons/stock/wizard/stock_inventory_line_split.py
index 9fe71582c7f..9f91a47c9a5 100644
--- a/addons/stock/wizard/stock_inventory_line_split.py
+++ b/addons/stock/wizard/stock_inventory_line_split.py
@@ -35,17 +35,13 @@ class stock_inventory_line_split(osv.osv_memory):
def default_get(self, cr, uid, fields, context):
- """
- To check the availability of production lot.
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param fields: List of fields for which we want default values
- @param context: A standard dictionary
-
- @return: A dictionary which of fields with values.
-
+ """ To check the availability of production lot.
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param fields: List of fields for which we want default values
+ @param context: A standard dictionary
+ @return: A dictionary which of fields with values.
"""
record_id = context and context.get('active_id',False)
res = super(stock_inventory_line_split, self).default_get(cr, uid, fields, context=context)
@@ -55,18 +51,14 @@ class stock_inventory_line_split(osv.osv_memory):
return res
def split(self, cr, uid, ids, line_ids, context=None):
- """
- To split stock inventory lines according to production lot
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param ids: the ID or list of IDs if we want more than one
- @param line_ids: the ID or list of IDs of inventory lines we want to split
- @param context: A standard dictionary
-
- @return:
-
+ """ To split stock inventory lines according to production lot.
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: the ID or list of IDs if we want more than one
+ @param line_ids: the ID or list of IDs of inventory lines we want to split
+ @param context: A standard dictionary
+ @return:
"""
prodlot_obj = self.pool.get('stock.production.lot')
ir_sequence_obj = self.pool.get('ir.sequence')
diff --git a/addons/stock/wizard/stock_inventory_merge.py b/addons/stock/wizard/stock_inventory_merge.py
index 1c11ad8e2ad..30450e4d253 100644
--- a/addons/stock/wizard/stock_inventory_merge.py
+++ b/addons/stock/wizard/stock_inventory_merge.py
@@ -31,22 +31,15 @@ import wizard
class stock_inventory_merge(osv.osv_memory):
_name = "stock.inventory.merge"
_description = "Merge Inventory"
- _columns = {
-
- }
def do_merge(self, cr, uid, ids, context):
- """
- To merge selected Inventories.
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param ids: List of IDs selected
- @param context: A standard dictionary
-
- @return:
-
+ """ To merge selected Inventories.
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: List of IDs selected
+ @param context: A standard dictionary
+ @return:
"""
invent_obj = self.pool.get('stock.inventory')
invent_line_obj = self.pool.get('stock.inventory.line')
diff --git a/addons/stock/wizard/stock_inventory_set_stock_zero.py b/addons/stock/wizard/stock_inventory_set_stock_zero.py
index 63296b69875..f72e4f088b0 100644
--- a/addons/stock/wizard/stock_inventory_set_stock_zero.py
+++ b/addons/stock/wizard/stock_inventory_set_stock_zero.py
@@ -32,22 +32,19 @@ import wizard
class inventory_set_stock_zero(osv.osv_memory):
_name = "stock.inventory.set.stock.zero"
_description = "Set Stock to 0"
+
_columns = {
'location_id': fields.many2one('stock.location', 'Location', required=True),
- }
+ }
def do_merge(self, cr, uid, ids, context):
- """
- To set stock to Zero
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param ids: the ID or list of IDs if we want more than one
- @param context: A standard dictionary
-
- @return:
-
+ """ To set stock to Zero
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: the ID or list of IDs if we want more than one
+ @param context: A standard dictionary
+ @return:
"""
invent_obj = pooler.get_pool(cr.dbname).get('stock.inventory')
invent_line_obj = pooler.get_pool(cr.dbname).get('stock.inventory.line')
diff --git a/addons/stock/wizard/stock_invoice_onshipping.py b/addons/stock/wizard/stock_invoice_onshipping.py
index d2b671e9571..377a40f3cb9 100644
--- a/addons/stock/wizard/stock_invoice_onshipping.py
+++ b/addons/stock/wizard/stock_invoice_onshipping.py
@@ -39,20 +39,16 @@ class stock_invoice_onshipping(osv.osv_memory):
('out_refund', 'Customer Refund'),
('in_refund', 'Supplier Refund')] , 'Type', required=True),
'invoice_date': fields.date('Invoiced date'),
- }
+ }
def _get_type(self, cr, uid, context=None):
- """
- To get invoice type
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param ids: the ID or list of IDs if we want more than one
- @param context: A standard dictionary
-
- @return: invoice type
-
+ """ To get invoice type.
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: The ID or list of IDs if we want more than one
+ @param context: A standard dictionary
+ @return: Invoice type
"""
if context is None:
context = {}
@@ -80,20 +76,16 @@ class stock_invoice_onshipping(osv.osv_memory):
_defaults = {
'type': _get_type,
- }
+ }
def create_invoice(self, cr, uid, ids, context):
- """
- To create invoice
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param ids: the ID or list of IDs if we want more than one
- @param context: A standard dictionary
-
- @return: invoice ids
-
+ """ To create invoice
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: the ID or list of IDs if we want more than one
+ @param context: A standard dictionary
+ @return: Invoice ids
"""
result = []
picking_obj = self.pool.get('stock.picking')
diff --git a/addons/stock/wizard/stock_location_product.py b/addons/stock/wizard/stock_location_product.py
index b41809b67bd..9fe800bb0fe 100644
--- a/addons/stock/wizard/stock_location_product.py
+++ b/addons/stock/wizard/stock_location_product.py
@@ -30,16 +30,13 @@ class stock_location_product(osv.osv_memory):
}
def action_open_window(self, cr, uid, ids, context):
- """
- To open location wise product information specific to given duration
-
+ """ To open location wise product information specific to given duration
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
- @param ids: the ID or list of IDs if we want more than one
+ @param ids: An ID or list of IDs if we want more than one
@param context: A standard dictionary
-
- @return: invoice type
+ @return: Invoice type
"""
mod_obj = self.pool.get('ir.model.data')
for location_obj in self.read(cr, uid, ids, ['from_date', 'to_date']):
diff --git a/addons/stock/wizard/stock_move.py b/addons/stock/wizard/stock_move.py
index 00b7b616aa5..0e670ee3e5d 100644
--- a/addons/stock/wizard/stock_move.py
+++ b/addons/stock/wizard/stock_move.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL ().
#
@@ -15,7 +15,7 @@
# 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 .
+# along with this program. If not, see .
#
##############################################################################
@@ -25,29 +25,25 @@ from tools.translate import _
class stock_move_track(osv.osv_memory):
_name = "stock.move.track"
_description = "Track moves"
-
+
_columns = {
- 'tracking_prefix': fields.char('Tracking prefix', size=64),
+ 'tracking_prefix': fields.char('Tracking prefix', size=64),
'quantity': fields.float("Quantity per lot")
- }
+ }
_defaults = {
'quantity': lambda *x: 1
- }
-
+ }
+
def track_lines(self, cr, uid, ids, context={}):
- """
- To track stock moves lines
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param ids: the ID or list of IDs if we want more than one
- @param context: A standard dictionary
-
- @return:
-
- """
+ """ To track stock moves lines
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: An ID or list of IDs if we want more than one
+ @param context: A standard dictionary
+ @return:
+ """
datas = self.read(cr, uid, ids)[0]
move_obj = self.pool.get('stock.move')
move_obj._track_lines(cr, uid, context['active_id'], datas, context=context)
@@ -58,58 +54,50 @@ stock_move_track()
class stock_move_consume(osv.osv_memory):
_name = "stock.move.consume"
_description = "Consume Products"
-
+
_columns = {
- 'product_id': fields.many2one('product.product', 'Product', required=True, select=True),
- 'product_qty': fields.float('Quantity', required=True),
- 'product_uom': fields.many2one('product.uom', 'Product UOM', required=True),
+ 'product_id': fields.many2one('product.product', 'Product', required=True, select=True),
+ 'product_qty': fields.float('Quantity', required=True),
+ 'product_uom': fields.many2one('product.uom', 'Product UOM', required=True),
'location_id': fields.many2one('stock.location', 'Location', required=True)
}
def default_get(self, cr, uid, fields, context=None):
- """
- Get default values
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param fields: List of fields for default value
- @param context: A standard dictionary
-
- @return: default values of fields
-
+ """ Get default values
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param fields: List of fields for default value
+ @param context: A standard dictionary
+ @return: default values of fields
"""
- res = super(stock_move_consume, self).default_get(cr, uid, fields, context=context)
+ res = super(stock_move_consume, self).default_get(cr, uid, fields, context=context)
move = self.pool.get('stock.move').browse(cr, uid, context['active_id'], context=context)
if 'product_id' in fields:
- res.update({'product_id': move.product_id.id})
+ res.update({'product_id': move.product_id.id})
if 'product_uom' in fields:
- res.update({'product_uom': move.product_uom.id})
+ res.update({'product_uom': move.product_uom.id})
if 'product_qty' in fields:
res.update({'product_qty': move.product_qty})
if 'location_id' in fields:
res.update({'location_id': move.location_id.id})
-
- return res
-
+
+ return res
+
def do_move_consume(self, cr, uid, ids, context={}):
- """
- To move consumed products
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param ids: the ID or list of IDs if we want more than one
- @param context: A standard dictionary
-
- @return:
-
- """
+ """ To move consumed products
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: the ID or list of IDs if we want more than one
+ @param context: A standard dictionary
+ @return:
+ """
move_obj = self.pool.get('stock.move')
move_ids = context['active_ids']
- for data in self.read(cr, uid, ids):
- move_obj.action_consume(cr, uid, move_ids,
- data['product_qty'], data['location_id'],
+ for data in self.read(cr, uid, ids):
+ move_obj.action_consume(cr, uid, move_ids,
+ data['product_qty'], data['location_id'],
context=context)
return {}
@@ -120,33 +108,29 @@ class stock_move_scrap(osv.osv_memory):
_name = "stock.move.scrap"
_description = "Scrap Products"
_inherit = "stock.move.consume"
-
+
_defaults = {
'location_id': lambda *x: False
}
def default_get(self, cr, uid, fields, context=None):
- """
- Get default values
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param fields: List of fields for default value
- @param context: A standard dictionary
-
- @return: default values of fields
-
+ """ Get default values
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param fields: List of fields for default value
+ @param context: A standard dictionary
+ @return: default values of fields
"""
- res = super(stock_move_consume, self).default_get(cr, uid, fields, context=context)
+ res = super(stock_move_consume, self).default_get(cr, uid, fields, context=context)
move = self.pool.get('stock.move').browse(cr, uid, context['active_id'], context=context)
location_obj = self.pool.get('stock.location')
scrpaed_location_ids = location_obj.search(cr, uid, [('scrap_location','=',True)])
-
+
if 'product_id' in fields:
- res.update({'product_id': move.product_id.id})
+ res.update({'product_id': move.product_id.id})
if 'product_uom' in fields:
- res.update({'product_uom': move.product_uom.id})
+ res.update({'product_uom': move.product_uom.id})
if 'product_qty' in fields:
res.update({'product_qty': move.product_qty})
if 'location_id' in fields:
@@ -154,27 +138,23 @@ class stock_move_scrap(osv.osv_memory):
res.update({'location_id': scrpaed_location_ids[0]})
else:
res.update({'location_id': False})
-
+
return res
-
+
def move_scrap(self, cr, uid, ids, context={}):
- """
- To move scraped products
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param ids: the ID or list of IDs if we want more than one
- @param context: A standard dictionary
-
- @return:
-
- """
- move_obj = self.pool.get('stock.move')
+ """ To move scraped products
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: the ID or list of IDs if we want more than one
+ @param context: A standard dictionary
+ @return:
+ """
+ move_obj = self.pool.get('stock.move')
move_ids = context['active_ids']
for data in self.read(cr, uid, ids):
- move_obj.action_scrap(cr, uid, move_ids,
- data['product_qty'], data['location_id'],
+ move_obj.action_scrap(cr, uid, move_ids,
+ data['product_qty'], data['location_id'],
context=context)
return {}
@@ -184,128 +164,146 @@ stock_move_scrap()
class split_in_production_lot(osv.osv_memory):
_name = "stock.move.split"
_description = "Split in Production lots"
-
+
def default_get(self, cr, uid, fields, context=None):
- """
- Get default values
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param fields: List of fields for default value
- @param context: A standard dictionary
-
- @return: default values of fields
-
+ """ Get default values
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param fields: List of fields for default value
+ @param context: A standard dictionary
+ @return: Default values of fields
"""
-
- res = super(split_in_production_lot, self).default_get(cr, uid, fields, context=context)
- move = self.pool.get('stock.move').browse(cr, uid, context['active_id'], context=context)
+
+ res = super(split_in_production_lot, self).default_get(cr, uid, fields, context=context)
+ move = self.pool.get('stock.move').browse(cr, uid, context['active_id'], context=context)
if 'product_id' in fields:
- res.update({'product_id': move.product_id.id})
+ res.update({'product_id': move.product_id.id})
+ if 'qty' in fields:
+ res.update({'qty': move.product_qty})
return res
-
+
_columns = {
+ 'qty': fields.integer('Quantity'),
'product_id': fields.many2one('product.product', 'Product', required=True, select=True),
- 'line_ids': fields.one2many('stock.move.split.lines', 'lot_id', 'Lots Number')
+ 'line_ids': fields.one2many('stock.move.split.lines', 'lot_id', 'Lots Number'),
+ 'line_exist_ids': fields.one2many('stock.move.split.lines.exist', 'lot_id', 'Lots Existing Numbers'),
+ 'use_exist' : fields.boolean('Use Exist'),
}
+
def split_lot(self, cr, uid, ids, context=None):
- """
- To split a lot
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param ids: the ID or list of IDs if we want more than one
- @param context: A standard dictionary
-
- @return:
-
- """
+ """ To split a lot
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: An ID or list of IDs if we want more than one
+ @param context: A standard dictionary
+ @return:
+ """
self.split(cr, uid, ids, context.get('active_ids'), context=context)
return {}
def split(self, cr, uid, ids, move_ids, context=None):
- """
- To split stock moves into production lot
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param ids: the ID or list of IDs if we want more than one
- @param move_ids: the ID or list of IDs of stock move we want to split
- @param context: A standard dictionary
-
- @return:
-
- """
+ """ To split stock moves into production lot
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: the ID or list of IDs if we want more than one
+ @param move_ids: the ID or list of IDs of stock move we want to split
+ @param context: A standard dictionary
+ @return:
+ """
prodlot_obj = self.pool.get('stock.production.lot')
ir_sequence_obj = self.pool.get('ir.sequence')
move_obj = self.pool.get('stock.move')
- new_move = []
+ new_move = []
for data in self.browse(cr, uid, ids):
for move in move_obj.browse(cr, uid, move_ids):
move_qty = move.product_qty
quantity_rest = move.product_qty
uos_qty_rest = move.product_uos_qty
- new_move = []
- for line in data.line_ids:
+ new_move = []
+ if data.use_exist:
+ lines = [l for l in data.line_exist_ids if l]
+ else:
+ lines = [l for l in data.line_ids if l]
+ for line in lines:
quantity = line.quantity
-
-
if quantity <= 0 or move_qty == 0:
continue
quantity_rest -= quantity
uos_qty = quantity / move_qty * move.product_uos_qty
uos_qty_rest = quantity_rest / move_qty * move.product_uos_qty
- if quantity_rest <= 0:
+ if quantity_rest < 0:
quantity_rest = quantity
break
default_val = {
- 'product_qty': quantity,
- 'product_uos_qty': uos_qty,
- 'state': move.state
+ 'product_qty': quantity,
+ 'product_uos_qty': uos_qty,
+ 'state': 'draft'
}
- current_move = move_obj.copy(cr, uid, move.id, default_val)
- new_move.append(current_move)
+ if quantity_rest > 0:
+ current_move = move_obj.copy(cr, uid, move.id, default_val)
+ move_obj.action_confirm(cr, uid, [current_move])
+ if move.state=='assigned':
+ move_obj.force_assign(cr, uid, [current_move])
+ elif move.state<>'confirmed':
+ move_obj.write(cr, uid, [current_move], {'state': move.state})
+ new_move.append(current_move)
+ if quantity_rest == 0:
+ current_move = move.id
prodlot_id = False
- if line.use_exist and line.name:
- prodlot_id = prodlot_obj.search(cr, uid, [('prefix','=',line.name),('product_id','=',data.product_id.id)])
+ if data.use_exist and line.prodlot_id:
+ prodlot_id = prodlot_obj.search(cr, uid, [('id','=',line.prodlot_id.id)])
if prodlot_id:
- prodlot_id = prodlot_id[0]
+ prodlot_id = prodlot_id[0]
if not prodlot_id:
- sequence = ir_sequence_obj.get(cr, uid, 'stock.lot.serial')
- prodlot_id = prodlot_obj.create(cr, uid, {'name': sequence, 'prefix' : line.name},
- {'product_id': move.product_id.id})
+ # sequence = ir_sequence_obj.get(cr, uid, 'stock.lot.serial')
+ prodlot_id = prodlot_obj.create(cr, uid, {'name': line.name},
+ # 'prefix' : line.name},
+ {'product_id': move.product_id.id})
move_obj.write(cr, uid, [current_move], {'prodlot_id': prodlot_id})
- prodlot = prodlot_obj.browse(cr, uid, prodlot_id)
- ref = '%d' % (move.id)
- if prodlot.ref:
- ref = '%s, %s' % (prodlot.ref, ref)
- prodlot_obj.write(cr, uid, [prodlot_id], {'ref': ref})
-
+ prodlot = prodlot_obj.browse(cr, uid, prodlot_id)
+ # ref = '%d' % (move.id)
+ # if prodlot.ref:
+ # ref = '%s, %s' % (prodlot.ref, ref)
+ # prodlot_obj.write(cr, uid, [prodlot_id], {'ref': ref})
+
update_val = {}
- if quantity_rest > 0:
+ if quantity_rest > 0:
update_val['product_qty'] = quantity_rest
- update_val['product_uos_qty'] = uos_qty_rest
+ update_val['product_uos_qty'] = uos_qty_rest
move_obj.write(cr, uid, [move.id], update_val)
return new_move
split_in_production_lot()
+class stock_move_split_lines_exist(osv.osv_memory):
+ _name = "stock.move.split.lines.exist"
+ _description = "Exist Split lines"
+ _columns = {
+ 'name': fields.char('Tracking serial', size=64),
+ 'quantity': fields.integer('Quantity'),
+ 'lot_id': fields.many2one('stock.move.split', 'Lot'),
+ 'prodlot_id': fields.many2one('stock.production.lot', 'Production Lot'),
+ }
+ _defaults = {
+ 'quantity': lambda *x: 1,
+ }
+
+stock_move_split_lines_exist()
+
class stock_move_split_lines(osv.osv_memory):
_name = "stock.move.split.lines"
_description = "Split lines"
-
_columns = {
- 'name': fields.char('Tracking serial', size=64),
- 'quantity': fields.integer('Quantity'),
+ 'name': fields.char('Tracking serial', size=64),
+ 'quantity': fields.integer('Quantity'),
'use_exist' : fields.boolean('Use Exist'),
'lot_id': fields.many2one('stock.move.split', 'Lot'),
'action': fields.selection([('split','Split'),('keepinone','Keep in one lot')],'Action'),
}
_defaults = {
'quantity': lambda *x: 1,
- 'action' : lambda *x: 'split',
+ 'action' : lambda *x: 'split',
}
-
stock_move_split_lines()
diff --git a/addons/stock/wizard/stock_move_view.xml b/addons/stock/wizard/stock_move_view.xml
index 5f58072f17a..bba27bfe9c7 100644
--- a/addons/stock/wizard/stock_move_view.xml
+++ b/addons/stock/wizard/stock_move_view.xml
@@ -106,18 +106,32 @@
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
"""
result['arch'] = _moves_arch_lst
- result['fields'] = _moves_fields
+ result['fields'] = _moves_fields
return result
def default_get(self, cr, uid, fields, context=None):
- """
- To get default values for the object.
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param fields: List of fields for which we want default values
- @param context: A standard dictionary
-
- @return: A dictionary which of fields with values.
-
- """
+ """ To get default values for the object.
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param fields: List of fields for which we want default values
+ @param context: A standard dictionary
+ @return: A dictionary which of fields with values.
+ """
res = super(stock_partial_move, self).default_get(cr, uid, fields, context=context)
- move_obj = self.pool.get('stock.move')
+ move_obj = self.pool.get('stock.move')
if not context:
context={}
moveids = []
if 'date' in fields:
res.update({'date': time.strftime('%Y-%m-%d %H:%M:%S')})
- for m in move_obj.browse(cr, uid, context.get('active_ids', [])):
+ move_ids = context.get('active_ids', [])
+ move_ids = move_obj.search(cr, uid, [('id','in',move_ids)])
+ for m in move_obj.browse(cr, uid, context.get('active_ids', [])):
if m.state in ('done', 'cancel'):
continue
if 'move%s_product_id'%(m.id) in fields:
@@ -170,6 +163,20 @@ class stock_partial_move(osv.osv_memory):
if 'move%s_product_uom'%(m.id) in fields:
res['move%s_product_uom'%(m.id)] = m.product_uom.id
+ if (m.picking_id.type == 'out') and (m.product_id.cost_method == 'average'):
+ price = 0
+ if hasattr(m, 'sale_line_id') and m.sale_line_id:
+ price = m.sale_line_id.price_unit
+
+ currency = False
+ if hasattr(m.picking_id, 'sale_id') and m.picking_id.sale_id:
+ currency = m.picking_id.sale_id.pricelist_id.currency_id.id
+
+ if 'move%s_product_price'%(m.id) in fields:
+ res['move%s_product_price'%(m.id)] = price
+ if 'move%s_product_currency'%(m.id) in fields:
+ res['move%s_product_currency'%(m.id)] = currency
+
if (m.picking_id.type == 'in') and (m.product_id.cost_method == 'average'):
price = 0
if hasattr(m, 'purchase_line_id') and m.purchase_line_id:
@@ -178,29 +185,37 @@ class stock_partial_move(osv.osv_memory):
currency = False
if hasattr(m.picking_id, 'purchase_id') and m.picking_id.purchase_id:
currency = m.picking_id.purchase_id.pricelist_id.currency_id.id
-
+
if 'move%s_product_price'%(m.id) in fields:
res['move%s_product_price'%(m.id)] = price
if 'move%s_product_currency'%(m.id) in fields:
res['move%s_product_currency'%(m.id)] = currency
- return res
+ print res
+ return res
+
+ def do_partial(self, cr, uid, ids, context):
+ """ Makes partial moves and pickings done.
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param fields: List of fields for which we want default values
+ @param context: A standard dictionary
+ @return: A dictionary which of fields with values.
+ """
- def do_partial(self, cr, uid, ids, context):
rec_id = context and context.get('active_id', False)
tracking_lot = context.get('tracking_lot', False)
if tracking_lot:
tracking = self.pool.get('stock.tracking')
- tracking_lot = tracking.get_create_tracking_lot(cr, uid,[rec_id], tracking_lot)
- context ['tracking_lot'] = tracking_lot
- move_obj = self.pool.get('stock.move')
+ tracking_lot = tracking.get_create_tracking_lot(cr, uid,[rec_id], tracking_lot)
+ context ['tracking_lot'] = tracking_lot
+ move_obj = self.pool.get('stock.move')
move_ids = context.get('active_ids', False)
partial = self.browse(cr, uid, ids[0], context)
partial_datas = {
- 'partner_id' : partial.partner_id and partial.partner_id.id or False,
- 'address_id' : partial.address_id and partial.address_id.id or False,
- 'delivery_date' : partial.date
+ 'delivery_date' : partial.date
}
- for m in move_obj.browse(cr, uid, move_ids):
+ for m in move_obj.browse(cr, uid, move_ids):
if m.state in ('done', 'cancel'):
continue
partial_datas['move%s'%(m.id)] = {
@@ -209,14 +224,15 @@ class stock_partial_move(osv.osv_memory):
'product_uom' : getattr(partial, 'move%s_product_uom'%(m.id)).id
}
- if (m.picking_id.type == 'in') and (m.product_id.cost_method == 'average'):
- partial_datas['move%s'%(m.id)].update({
+ if (m.picking_id.type == 'in') and (m.product_id.cost_method == 'average'):
+ partial_datas['move%s'%(m.id)].update({
'product_price' : getattr(partial, 'move%s_product_price'%(m.id)),
'product_currency': getattr(partial, 'move%s_product_currency'%(m.id)).id
- })
+ })
res = move_obj.do_partial(cr, uid, move_ids, partial_datas, context=context)
return {}
-
-stock_partial_move()
+
+stock_partial_move()
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/stock/wizard/stock_partial_move_view.xml b/addons/stock/wizard/stock_partial_move_view.xml
index 30b7f3fca0e..a7b4271a5b2 100644
--- a/addons/stock/wizard/stock_partial_move_view.xml
+++ b/addons/stock/wizard/stock_partial_move_view.xml
@@ -1,25 +1,14 @@
-
+
-
- Delivery Product
- stock.partial.move
- form
-
-
-
-
-
-
-
-
+
diff --git a/addons/stock/wizard/stock_partial_picking.py b/addons/stock/wizard/stock_partial_picking.py
index eba095718cd..595215c2a49 100644
--- a/addons/stock/wizard/stock_partial_picking.py
+++ b/addons/stock/wizard/stock_partial_picking.py
@@ -29,19 +29,16 @@ class stock_partial_picking(osv.osv_memory):
_name = "stock.partial.picking"
_description = "Partial Picking"
_columns = {
- 'date': fields.datetime('Date', required=True),
- 'partner_id': fields.many2one('res.partner',string="Partner", required=True),
- 'address_id': fields.many2one('res.partner.address', 'Delivery Address', help="Address where goods are to be delivered", required=True),
-
+ 'date': fields.datetime('Date', required=True),
}
def view_init(self, cr, uid, fields_list, context=None):
res = super(stock_partial_picking, self).view_init(cr, uid, fields_list, context=context)
- pick_obj = self.pool.get('stock.picking')
+ pick_obj = self.pool.get('stock.picking')
if not context:
context={}
moveids = []
- for pick in pick_obj.browse(cr, uid, context.get('active_ids', [])):
+ for pick in pick_obj.browse(cr, uid, context.get('active_ids', [])):
for m in pick.move_lines:
if m.state in ('done', 'cancel'):
continue
@@ -52,26 +49,23 @@ class stock_partial_picking(osv.osv_memory):
if 'move%s_product_uom'%(m.id) not in self._columns:
self._columns['move%s_product_uom'%(m.id)] = fields.many2one('product.uom',string="Product UOM")
- if (pick.type == 'in') and (m.product_id.cost_method == 'average'):
+ if (m.product_id.cost_method == 'average'):
if 'move%s_product_price'%(m.id) not in self._columns:
self._columns['move%s_product_price'%(m.id)] = fields.float("Price")
if 'move%s_product_currency'%(m.id) not in self._columns:
self._columns['move%s_product_currency'%(m.id)] = fields.many2one('res.currency',string="Currency")
- return res
+ return res
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False,submenu=False):
- result = super(stock_partial_picking, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu)
+ result = super(stock_partial_picking, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu)
pick_obj = self.pool.get('stock.picking')
- picking_ids = context.get('active_ids', False)
- picking_ids = pick_obj.search(cr, uid, [('id', 'in', picking_ids)])
- _moves_arch_lst = """
"""
result['arch'] = _moves_arch_lst
- result['fields'] = _moves_fields
+ result['fields'] = _moves_fields
return result
def default_get(self, cr, uid, fields, context=None):
- """
- To get default values for the object.
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param fields: List of fields for which we want default values
- @param context: A standard dictionary
-
- @return: A dictionary which of fields with values.
-
- """
+ """ To get default values for the object.
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param fields: List of fields for which we want default values
+ @param context: A standard dictionary
+ @return: A dictionary which of fields with values.
+ """
res = super(stock_partial_picking, self).default_get(cr, uid, fields, context=context)
- pick_obj = self.pool.get('stock.picking')
+ pick_obj = self.pool.get('stock.picking')
if not context:
context={}
moveids = []
if 'date' in fields:
res.update({'date': time.strftime('%Y-%m-%d %H:%M:%S')})
for pick in pick_obj.browse(cr, uid, context.get('active_ids', [])):
- if 'partner_id' in fields:
- res.update({'partner_id': pick.address_id.partner_id.id})
- if 'address_id' in fields:
- res.update({'address_id': pick.address_id.id})
for m in pick.move_lines:
if m.state in ('done', 'cancel'):
continue
@@ -176,29 +162,39 @@ class stock_partial_picking(osv.osv_memory):
if 'move%s_product_uom'%(m.id) in fields:
res['move%s_product_uom'%(m.id)] = m.product_uom.id
- if (pick.type == 'in') and (m.product_id.cost_method == 'average'):
- price = 0
- if hasattr(m, 'purchase_line_id') and m.purchase_line_id:
- price = m.purchase_line_id.price_unit
-
+ if (m.product_id.cost_method == 'average'):
currency = False
- if hasattr(pick, 'purchase_id') and pick.purchase_id:
- currency = pick.purchase_id.pricelist_id.currency_id.id
-
+ price = 0
+ if (pick.type == 'in'):
+ if hasattr(m, 'purchase_line_id') and m.purchase_line_id:
+ price = m.purchase_line_id.price_unit
+ if hasattr(pick, 'purchase_id') and pick.purchase_id:
+ currency = pick.purchase_id.pricelist_id.currency_id.id
+ if (pick.type == 'out'):
+ if hasattr(m, 'sale_line_id') and m.sale_line_id:
+ price = m.sale_line_id.price_unit
+ if hasattr(pick, 'sale_id') and pick.sale_id:
+ currency = pick.sale_id.pricelist_id.currency_id.id
if 'move%s_product_price'%(m.id) in fields:
res['move%s_product_price'%(m.id)] = price
if 'move%s_product_currency'%(m.id) in fields:
res['move%s_product_currency'%(m.id)] = currency
- return res
+ return res
- def do_partial(self, cr, uid, ids, context):
- pick_obj = self.pool.get('stock.picking')
+ def do_partial(self, cr, uid, ids, context):
+ """ Makes partial moves and pickings done.
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param fields: List of fields for which we want default values
+ @param context: A standard dictionary
+ @return: A dictionary which of fields with values.
+ """
+ pick_obj = self.pool.get('stock.picking')
picking_ids = context.get('active_ids', False)
partial = self.browse(cr, uid, ids[0], context)
partial_datas = {
- 'partner_id' : partial.partner_id and partial.partner_id.id or False,
- 'address_id' : partial.address_id and partial.address_id.id or False,
- 'delivery_date' : partial.date
+ 'delivery_date' : partial.date
}
for pick in pick_obj.browse(cr, uid, picking_ids):
for m in pick.move_lines:
@@ -210,26 +206,13 @@ class stock_partial_picking(osv.osv_memory):
'product_uom' : getattr(partial, 'move%s_product_uom'%(m.id)).id
}
- if (pick.type == 'in') and (m.product_id.cost_method == 'average'):
- partial_datas['move%s'%(m.id)].update({
+ if (m.product_id.cost_method == 'average'):
+ partial_datas['move%s'%(m.id)].update({
'product_price' : getattr(partial, 'move%s_product_price'%(m.id)),
'product_currency': getattr(partial, 'move%s_product_currency'%(m.id)).id
- })
+ })
res = pick_obj.do_partial(cr, uid, picking_ids, partial_datas, context=context)
return {}
-
-stock_partial_picking()
-
-
-#_moves_arch_end = '''
-#
-#
-#
-#
'''
-
-#_moves_fields_end = {
-# 'back_order_notification': {'string':'Back Order' ,'type':'text', 'readonly':True}
-# }
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+stock_partial_picking()
diff --git a/addons/stock/wizard/stock_partial_picking_view.xml b/addons/stock/wizard/stock_partial_picking_view.xml
index 2f901b9884d..b399576c83d 100644
--- a/addons/stock/wizard/stock_partial_picking_view.xml
+++ b/addons/stock/wizard/stock_partial_picking_view.xml
@@ -1,13 +1,13 @@
-
-
+
+ Making Picking
- stock.partial.picking
- form
- form
+ stock.partial.picking
+ form
+ formnew
-
+
diff --git a/addons/stock/wizard/stock_replacement.py b/addons/stock/wizard/stock_replacement.py
index a6f39212ef8..8b6c36f0f21 100644
--- a/addons/stock/wizard/stock_replacement.py
+++ b/addons/stock/wizard/stock_replacement.py
@@ -38,20 +38,17 @@ class stock_replacement(osv.osv_memory):
return {}
def replace_composant(self, cr, uid, ids, context = {}):
- """
- to open a new wizard that acknowledge, a replacement task
-
- @return: it returns the replacement acknowledgement form
-
+ """ To open a new wizard that acknowledge, a replacement task
+ @return: It returns the replacement acknowledgement form
"""
return {
- 'name': False,
- 'view_type': 'form',
- 'view_mode': 'form',
- 'res_model': 'stock.replacement.result',
- 'type': 'ir.actions.act_window',
- 'target':'new',
- }
+ 'name': False,
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'stock.replacement.result',
+ 'type': 'ir.actions.act_window',
+ 'target':'new',
+ }
stock_replacement()
diff --git a/addons/stock/wizard/stock_split_move.py b/addons/stock/wizard/stock_split_move.py
index c1354e21578..f3e72bfdc11 100644
--- a/addons/stock/wizard/stock_split_move.py
+++ b/addons/stock/wizard/stock_split_move.py
@@ -26,8 +26,7 @@ class stock_split_move_line(osv.osv_memory):
_description = "Split Moves"
def default_get(self, cr, uid, fields, context):
- """
- To get default values for the object.
+ """ To get default values for the object.
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@@ -44,8 +43,7 @@ class stock_split_move_line(osv.osv_memory):
return res
def view_init(self, cr, uid, fields_list, context=None):
- """
- Creates view dynamically and adding fields at runtime.
+ """ Creates view dynamically and adding fields at runtime.
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@@ -67,8 +65,7 @@ class stock_split_move_line(osv.osv_memory):
def fields_view_get(self, cr, uid, view_id=None, view_type='form',
context=None, toolbar=False, submenu=False):
- """
- Changes the view dynamically
+ """ Changes the view dynamically
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@@ -94,8 +91,7 @@ class stock_split_move_line(osv.osv_memory):
return res
def split_lines(self, cr, uid, ids, context):
- """
- Splits moves in quantity given in the wizard.
+ """ Splits moves in quantity given in the wizard.
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
diff --git a/addons/stock/wizard/stock_traceability.py b/addons/stock/wizard/stock_traceability.py
index 120fa658b1c..d2fadb1d89c 100644
--- a/addons/stock/wizard/stock_traceability.py
+++ b/addons/stock/wizard/stock_traceability.py
@@ -34,18 +34,15 @@ class action_traceability(osv.osv_memory):
_description = "Action traceability "
def action_traceability(self, cr, uid, ids, context={}):
- """
- It traces the information of a product
-
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param ids: List of IDs selected
- @param context: A standard dictionary
-
- @return: A dictionary of values
-
+ """ It traces the information of a product
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: List of IDs selected
+ @param context: A standard dictionary
+ @return: A dictionary of values
"""
+
type1 = context['type'] or 'move_history_ids'
field = context['field'] or 'tracking_id'
obj = self.pool.get('stock.move')
diff --git a/addons/stock/wizard/stock_ups.py b/addons/stock/wizard/stock_ups.py
index 5bde686402f..aeefcd0d106 100644
--- a/addons/stock/wizard/stock_ups.py
+++ b/addons/stock/wizard/stock_ups.py
@@ -31,25 +31,25 @@ class stock_ups(osv.osv_memory):
_description = "Stock ups"
def ups_save(self, cr, uid, ids, context = {}):
-
return {
- 'name': False,
- 'view_type': 'form',
- 'view_mode': 'form',
- 'res_model': 'stock.ups.final',
- 'type': 'ir.actions.act_window',
- 'target':'new',
- }
+ 'name': False,
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'stock.ups.final',
+ 'type': 'ir.actions.act_window',
+ 'target':'new',
+ }
+
def ups_upload(self, cr, uid, ids, context = {}):
-
return {
- 'name': False,
- 'view_type': 'form',
- 'view_mode': 'form',
- 'res_model': 'stock.ups.upload',
- 'type': 'ir.actions.act_window',
- 'target':'new',
- }
+ 'name': False,
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'stock.ups.upload',
+ 'type': 'ir.actions.act_window',
+ 'target':'new',
+ }
+
_columns = {
'weight': fields.float('Lot weight', required=True),
}
@@ -64,6 +64,9 @@ class stock_ups_final(osv.osv_memory):
_description = "Stock ups final"
def create_xmlfile(self, cr, uid, ids, context = {}):
+ """ Creates xml report file.
+ @return: xml file
+ """
report = netsvc._group['report']['report.stock.move.lot.ups_xml']
data['report_type'] = 'raw'
return {'xmlfile' : report.create(uid, context['active_id'], ids, {})}
@@ -79,6 +82,9 @@ class stock_ups_upload(osv.osv_memory):
_description = "Stock ups upload"
def upload_xmlfile(self, cr, uid, ids, context = {}):
+ """ Uploads xml report file.
+ @return:
+ """
report = netsvc._group['report']['report.stock.move.lot.ups_xml']
data['report_type'] = 'raw'
#FIXME: this seems unfinished
diff --git a/addons/stock_location/__init__.py b/addons/stock_location/__init__.py
index 1b86a7eb0c3..7a3970f9f44 100644
--- a/addons/stock_location/__init__.py
+++ b/addons/stock_location/__init__.py
@@ -20,5 +20,6 @@
##############################################################################
import stock
+import mrp_pull
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/stock_location/__openerp__.py b/addons/stock_location/__openerp__.py
index b13769b3458..8c58fcc2c13 100644
--- a/addons/stock_location/__openerp__.py
+++ b/addons/stock_location/__openerp__.py
@@ -37,9 +37,9 @@ This module may be useful for different purposes:
* Manage products to be rent.
""",
'author': 'Tiny',
- 'depends': ['stock'],
+ 'depends': ['procurement','stock'],
'init_xml': [],
- 'update_xml': ['stock_view.xml', 'security/ir.model.access.csv'],
+ 'update_xml': ['stock_view.xml', 'security/ir.model.access.csv', 'mrp_pull_workflow.xml'],
'demo_xml': [],
'installable': True,
'test':[
diff --git a/addons/stock_location/mrp_pull.py b/addons/stock_location/mrp_pull.py
new file mode 100644
index 00000000000..e20f75f07f5
--- /dev/null
+++ b/addons/stock_location/mrp_pull.py
@@ -0,0 +1,131 @@
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 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
+import ir
+import pooler
+import netsvc
+from mx import DateTime
+import time
+from tools.translate import _
+
+class procurement_order(osv.osv):
+ _inherit = 'procurement.order'
+ def check_buy(self, cr, uid, ids, context=None):
+ for procurement in self.browse(cr, uid, ids):
+ for line in procurement.product_id.flow_pull_ids:
+ print line.location_src_id.name, line.location_id.name, line.type_proc
+ if line.location_id==procurement.location_id:
+ return line.type_proc=='buy'
+ return super(procurement_order, self).check_buy(cr, uid, ids)
+
+ def check_produce(self, cr, uid, ids, context=None):
+ for procurement in self.browse(cr, uid, ids):
+ for line in procurement.product_id.flow_pull_ids:
+ if line.location_id==procurement.location_id:
+ return line.type_proc=='produce'
+ return super(procurement_order, self).check_produce(cr, uid, ids)
+
+ def check_move(self, cr, uid, ids, context=None):
+ for procurement in self.browse(cr, uid, ids):
+ for line in procurement.product_id.flow_pull_ids:
+ if line.location_id==procurement.location_id:
+ if not line.location_src_id:
+ self.write(cr, uid, procurement.id, {'message': _('No source location defined to generate the picking !')})
+ return (line.type_proc=='move') and (line.location_src_id)
+ return False
+
+ def action_move_create(self, cr, uid, ids,context=None):
+ proc_obj = self.pool.get('procurement.order')
+ move_obj = self.pool.get('stock.move')
+ location_obj = self.pool.get('stock.location')
+ wf_service = netsvc.LocalService("workflow")
+
+ for proc in proc_obj.browse(cr, uid, ids, context=context):
+ line = None
+ for line in proc.product_id.flow_pull_ids:
+ if line.location_id==proc.location_id:
+ break
+ assert line, 'Line can not be False if we are on this state of the workflow'
+ origin = (proc.origin or proc.name or '').split(':')[0] +':'+line.name
+ picking_id = self.pool.get('stock.picking').create(cr, uid, {
+ 'origin': origin,
+ 'company_id': line.company_id and line.company_id.id or False,
+ 'type': line.picking_type,
+ 'move_type': 'one',
+ 'address_id': line.partner_address_id.id,
+ 'note': line.name, # TODO: note on procurement ?
+ 'invoice_state': line.invoice_state,
+ })
+ move_id = self.pool.get('stock.move').create(cr, uid, {
+ 'name': line.name,
+ 'picking_id': picking_id,
+ 'company_id': line.company_id and line.company_id.id or False,
+ 'product_id': proc.product_id.id,
+ 'date_planned': proc.date_planned,
+ 'product_qty': proc.product_qty,
+ 'product_uom': proc.product_uom.id,
+ 'product_uos_qty': (proc.product_uos and proc.product_uos_qty)\
+ or proc.product_qty,
+ 'product_uos': (proc.product_uos and proc.product_uos.id)\
+ or proc.product_uom.id,
+ 'address_id': line.partner_address_id.id,
+ 'location_id': line.location_src_id.id,
+ 'location_dest_id': line.location_id.id,
+ 'move_dest_id': proc.move_id and proc.move_id.id or False, # to verif, about history ?
+ 'tracking_id': False,
+ 'cancel_cascade': line.cancel_cascade,
+ 'state': 'confirmed',
+ 'note': line.name, # TODO: same as above
+ })
+ if proc.move_id and proc.move_id.state in ('confirmed'):
+ self.pool.get('stock.move').write(cr,uid, [proc.move_id.id], {
+ 'state':'waiting'
+ }, context=context)
+ proc_id = self.pool.get('procurement.order').create(cr, uid, {
+ 'name': line.name,
+ 'origin': origin,
+ 'company_id': line.company_id and line.company_id.id or False,
+ 'date_planned': proc.date_planned,
+ 'product_id': proc.product_id.id,
+ 'product_qty': proc.product_qty,
+ 'product_uom': proc.product_uom.id,
+ 'product_uos_qty': (proc.product_uos and proc.product_uos_qty)\
+ or proc.product_qty,
+ 'product_uos': (proc.product_uos and proc.product_uos.id)\
+ or proc.product_uom.id,
+ 'location_id': line.location_src_id.id,
+ 'procure_method': line.procure_method,
+ 'move_id': move_id,
+ })
+ wf_service = netsvc.LocalService("workflow")
+ wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr)
+ wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_confirm', cr)
+ if proc.move_id:
+ self.pool.get('stock.move').write(cr, uid, [proc.move_id.id],
+ {'location_id':proc.location_id.id})
+
+ self.write(cr, uid, [proc.id], {'state':'running','message':_('Moved from other location')})
+
+ return False
+
+
+procurement_order()
diff --git a/addons/stock_location/mrp_pull_workflow.xml b/addons/stock_location/mrp_pull_workflow.xml
new file mode 100644
index 00000000000..d45942ae5a6
--- /dev/null
+++ b/addons/stock_location/mrp_pull_workflow.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+ move
+ function
+ action_move_create()
+
+
+
+
+
+ check_move()
+
+
+
+
+
+
+
diff --git a/addons/stock_location/security/ir.model.access.csv b/addons/stock_location/security/ir.model.access.csv
index e87f65004bb..188218b6e26 100644
--- a/addons/stock_location/security/ir.model.access.csv
+++ b/addons/stock_location/security/ir.model.access.csv
@@ -1,4 +1,7 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
+"access_product_pulled_flow_user","product_pulled_flow user","model_product_pulled_flow","stock.group_stock_user",1,0,0,0
+"access_product_pulled_flow_manager","product_pulled_flow manager","model_product_pulled_flow","stock.group_stock_manager",1,1,1,1
+"access_product_pulled_flow_partner_manager","product_pulled_flow partner manager","model_product_pulled_flow","product.group_product_manager",1,1,1,1
"access_stock_location_path_user","stock location path user","model_stock_location_path","stock.group_stock_user",1,0,0,0
"access_stock_location_path_manager","stock location path manager","model_stock_location_path","stock.group_stock_manager",1,1,1,1
"access_stock_location_path_partner_manager","stock.location.path partner manager","model_stock_location_path","product.group_product_manager",1,1,1,1
diff --git a/addons/stock_location/stock.py b/addons/stock_location/stock.py
index 3249dbef255..4aa4a1999ed 100644
--- a/addons/stock_location/stock.py
+++ b/addons/stock_location/stock.py
@@ -28,10 +28,17 @@ class stock_location_path(osv.osv):
_name = "stock.location.path"
_columns = {
'name': fields.char('Operation', size=64),
+ 'company_id': fields.many2one('res.company', 'Company'),
'product_id' : fields.many2one('product.product', 'Products', ondelete='cascade', select=1),
'location_from_id' : fields.many2one('stock.location', 'Source Location', ondelete='cascade', select=1),
'location_dest_id' : fields.many2one('stock.location', 'Destination Location', ondelete='cascade', select=1),
'delay': fields.integer('Delay (days)', help="Number of days to do this transition"),
+ 'invoice_state': fields.selection([
+ ("invoiced", "Invoiced"),
+ ("2binvoiced", "To Be Invoiced"),
+ ("none", "Not from Picking")], "Invoice Status",
+ required=True,),
+ 'picking_type': fields.selection([('out','Sending Goods'),('in','Getting Goods'),('internal','Internal'),('delivery','Delivery')], 'Shipping Type', required=True, select=True, help="Depending on the company, choose whatever you want to receive or send products"),
'auto': fields.selection(
[('auto','Automatic Move'), ('manual','Manual Operation'),('transparent','Automatic No Step Added')],
'Automatic Move',
@@ -44,20 +51,64 @@ class stock_location_path(osv.osv):
}
_defaults = {
'auto': lambda *arg: 'auto',
- 'delay': lambda *arg: 1
+ 'delay': lambda *arg: 1,
+ 'invoice_state': lambda *args: 'none',
}
stock_location_path()
+class product_pulled_flow(osv.osv):
+ _name = 'product.pulled.flow'
+ _description = "Pulled Flows"
+ _columns = {
+ 'name': fields.char('Name', size=64, required=True, help="This field will fill the packing Origin and the name of its moves"),
+ 'cancel_cascade': fields.boolean('Cancel Cascade', help="Allow you to cancel moves related to the product pull flow"),
+ 'location_id': fields.many2one('stock.location','Location', required=True, help="Is the destination location that needs supplying"),
+ 'location_src_id': fields.many2one('stock.location','Location Source', help="Location used by Destination Location to supply"),
+ 'procure_method': fields.selection([('make_to_stock','Make to Stock'),('make_to_order','Make to Order')], 'Procure Method', required=True, help="'Make to Stock': When needed, take from the stock or wait until re-supplying. 'Make to Order': When needed, purchase or produce for the procurement request."),
+ 'type_proc': fields.selection([('produce','Produce'),('buy','Buy'),('move','Move')], 'Type of Procurement', required=True),
+ 'company_id': fields.many2one('res.company', 'Company', help="Is used to know to which company belong packings and moves"),
+ 'partner_address_id': fields.many2one('res.partner.address', 'Partner Address'),
+ 'picking_type': fields.selection([('out','Sending Goods'),('in','Getting Goods'),('internal','Internal'),('delivery','Delivery')], 'Shipping Type', required=True, select=True, help="Depending on the company, choose whatever you want to receive or send products"),
+ 'product_id':fields.many2one('product.product','Product'),
+ 'invoice_state': fields.selection([
+ ("invoiced", "Invoiced"),
+ ("2binvoiced", "To Be Invoiced"),
+ ("none", "Not from Picking")], "Invoice Status",
+ required=True,),
+ }
+ _defaults = {
+ 'cancel_cascade': lambda *arg: False,
+ 'procure_method': lambda *args: 'make_to_stock',
+ 'type_proc': lambda *args: 'move',
+ 'picking_type':lambda *args:'out',
+ 'invoice_state': lambda *args: 'none',
+ }
+product_pulled_flow()
+
class product_product(osv.osv):
_inherit = 'product.product'
_columns = {
+ 'flow_pull_ids': fields.one2many('product.pulled.flow', 'product_id', 'Pulled Flows'),
'path_ids': fields.one2many('stock.location.path', 'product_id',
- 'Location Paths',
+ 'Pushed Flow',
help="These rules set the right path of the product in the "\
"whole location tree.")
}
product_product()
+class stock_move(osv.osv):
+ _inherit = 'stock.move'
+ _columns = {
+ 'cancel_cascade': fields.boolean('Cancel Cascade', help='If checked, when this move is cancelled, cancel the linked move too')
+ }
+ def action_cancel(self,cr,uid,ids,context={ }):
+ for m in self.browse(cr, uid, ids, context=context):
+ if m.cancel_cascade and m.move_dest_id:
+ self.action_cancel(cr, uid, [m.move_dest_id.id], context=context)
+ res = super(stock_move,self).action_cancel(cr,uid,ids,context)
+ return res
+stock_move()
+
class stock_location(osv.osv):
_inherit = 'stock.location'
def chained_location_get(self, cr, uid, location, partner=None, product=None, context={}):
diff --git a/addons/stock_location/stock_view.xml b/addons/stock_location/stock_view.xml
index f7ba12fe480..bac4164289f 100644
--- a/addons/stock_location/stock_view.xml
+++ b/addons/stock_location/stock_view.xml
@@ -8,7 +8,6 @@
tree
-
@@ -24,7 +23,7 @@
@@ -156,13 +160,19 @@
search
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -176,7 +186,7 @@
formtree,form
- {'section':'1','search_default_create_uid':uid}
+
diff --git a/addons/wiki_sale_faq/wiki_sale_faq_data.xml b/addons/wiki_sale_faq/wiki_sale_faq_data.xml
index 4a8eea1cb38..576e9e8f4b0 100644
--- a/addons/wiki_sale_faq/wiki_sale_faq_data.xml
+++ b/addons/wiki_sale_faq/wiki_sale_faq_data.xml
@@ -21,6 +21,47 @@
-
+
+ Sales Management ?
+ Sales
+
+ 0
+ 0
+ 1
+ 2
+ Initial Page
+ == Question ==
+
+What's Sales Management ?
+
+== Answer ==
+
+Sales modules allow you to manage and classify your sales orders on a structural and hierarchical system. It gives you
+the ability to create new orders and to review the existing orders in their various states. Confirmation of an order can
+triggers delivery of the goods, and invoicing timing is defined by a setting in each individual order.
+
+Key Points:
+
+* Get all information needed by the salesman to do his quote in one screen
+* Complete follow-up and control of sales orders, deliveries and invoicing
+* Traceability of all customers operations
+
+
+Integration Benefits:
+
+* Automatic accounting (financial and analytic) entries creation,
+* Integrated with contracts, projects, master production shedule,
+* Integrated with different eCommerce platforms for online selling.
+* Design templates of re-useable offers with the report designer
+
+
+== External Links ==
+
+* The Open ERP Website: [http://openerp.com]
+* The Sale Documentation: [http://openerp.com]
+
+
+
+