+
+
-
+
-
- Event Tree
- calendar.event
- tree
-
-
-
-
-
-
-
-
-
-
-
+
+ Event Tree
+ calendar.event
+ tree
+
+
+
+
+
+
+
+
+
+
+
-
+
-
- Events Calendar
- calendar.event
- calendar
-
-
-
-
-
-
-
-
-
+
+ Events Calendar
+ calendar.event
+ calendar
+
+
+
+
+
+
+
+
+
-
+
-
- Calendar Events Search
- calendar.event
- search
-
+
+ Calendar Events Search
+ calendar.event
+ search
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
+
-
- Events
- ir.actions.act_window
- calendar.event
- form
- tree,form,calendar
-
-
+
+ Events
+ ir.actions.act_window
+ calendar.event
+ form
+ tree,form,calendar
+
+
-
+
-
diff --git a/addons/base_calendar/security/ir.model.access.csv b/addons/base_calendar/security/ir.model.access.csv
old mode 100755
new mode 100644
index eba4e092f14..a95b1e1a129
--- a/addons/base_calendar/security/ir.model.access.csv
+++ b/addons/base_calendar/security/ir.model.access.csv
@@ -1,9 +1,9 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
-"access_calendar_attendee","calendar.attendee","model_calendar_attendee",,1,1,1,1
-"access_calendar_alarm","calendar.alarm","model_calendar_alarm",,1,1,1,1
-"access_res_alarm","res.alarm","model_res_alarm",,1,1,1,1
-"access_calendar_event_all","calendar.event","model_calendar_event",,1,1,1,1
-"access_calendar_todo","calendar.todo","model_calendar_todo",,1,1,1,1
-"access_base_calendar_invite_attendee","base_calendar.invite.attendee","model_base_calendar_invite_attendee",,1,1,1,1
-"access_calendar_event_edit_all","calendar_event_edit_all","model_calendar_event_edit_all",,1,1,1,1
-"access_base_calendar_set_exrule","base.calendar.set.exrule","model_base_calendar_set_exrule",,1,1,1,1
+"access_calendar_attendee","calendar.attendee","model_calendar_attendee",base.group_user,1,1,1,1
+"access_calendar_alarm","calendar.alarm","model_calendar_alarm",base.group_user,1,1,1,1
+"access_res_alarm","res.alarm","model_res_alarm",base.group_user,1,1,1,1
+"access_calendar_event_all","calendar.event","model_calendar_event",base.group_user,1,1,1,1
+"access_calendar_todo","calendar.todo","model_calendar_todo",base.group_user,1,1,1,1
+"access_base_calendar_invite_attendee","base_calendar.invite.attendee","model_base_calendar_invite_attendee",base.group_user,1,1,1,1
+"access_calendar_event_edit_all","calendar_event_edit_all","model_calendar_event_edit_all",base.group_user,1,1,1,1
+"access_base_calendar_set_exrule","base.calendar.set.exrule","model_base_calendar_set_exrule",base.group_user,1,1,1,1
diff --git a/addons/base_module_quality/i18n/zh_CN.po b/addons/base_module_quality/i18n/zh_CN.po
index 63aa756e8d6..f9b78c86564 100644
--- a/addons/base_module_quality/i18n/zh_CN.po
+++ b/addons/base_module_quality/i18n/zh_CN.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-10 03:36+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:43+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base_module_quality
diff --git a/addons/base_report_designer/i18n/hr.po b/addons/base_report_designer/i18n/hr.po
index 8b4c87f5583..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-09 03:35+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 2cf88ec82e1..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-09 03:35+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/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 7f7ab94616f..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,
@@ -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,
@@ -177,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']}
@@ -195,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,\
@@ -209,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
@@ -265,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'))
@@ -317,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):
"""
@@ -350,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:
@@ -381,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={}):
"""
@@ -428,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"),
@@ -445,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 = [
@@ -463,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()))
@@ -509,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):
@@ -541,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
@@ -572,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):
@@ -594,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
}
@@ -619,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()
@@ -627,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_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 @@
-
@@ -66,6 +66,7 @@
states="open,pending" type="object"
icon="gtk-go-forward" />
+
@@ -297,7 +298,7 @@
-
+
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_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 cd3b7866a89..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 @@
+
+
+
+
+
-
- project.task.caldav.form1
- project.task
-
- form
-
-
-
-
-
-
+
+ project.task.caldav.form1
+ project.task
+
+ form
+
+
+
+
+
+
-
- project.task.caldav.form2
- project.task
-
- form
-
-
-
-
-
-
-
-
-
+
+ project.task.caldav.form2
+ project.task
+
+ form
+
+
+
+
+
+
+
+
+
-
- project.task.caldav.form3
- project.task
-
- form
-
-
-
-
-
-
-
-
-
-
+
+ project.task.caldav.form3
+ project.task
+
+ form
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/project_gtd/security/ir.model.access.csv b/addons/project_gtd/security/ir.model.access.csv
index 52e1b466740..0398fbfb0ee 100644
--- a/addons/project_gtd/security/ir.model.access.csv
+++ b/addons/project_gtd/security/ir.model.access.csv
@@ -1,3 +1,7 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_project_gtd_context","project.gtd.context","model_project_gtd_context","group_project_getting",1,1,1,1
"access_project_gtd_timebox","project.gtd.timebox","model_project_gtd_timebox","group_project_getting",1,1,1,1
+"access_project_gtd_context_user","project.gtd.context project user","model_project_gtd_context","project.group_project_user",1,0,0,0
+"access_project_gtd_timebox_user","project.gtd.timebox project user","model_project_gtd_timebox","project.group_project_user",1,0,0,0
+"access_project_gtd_context_manager","project.gtd.context project manager","model_project_gtd_context","project.group_project_manager",1,1,1,1
+"access_project_gtd_timebox_manager","project.gtd.timebox project manager","model_project_gtd_timebox","project.group_project_manager",1,1,1,1
diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml
index a5009b7eb47..673f4239971 100644
--- a/addons/project_issue/project_issue_view.xml
+++ b/addons/project_issue/project_issue_view.xml
@@ -106,9 +106,9 @@
+ name="%(crm.action_crm_send_mail)d"
+ context="{'mail':'new', 'model': 'project.issue'}"
+ icon="gtk-go-forward" type="action" />
@@ -187,10 +187,10 @@
-
+
-
+
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
@@ -298,12 +298,12 @@
-
+
-
+
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 92b8a34ee9c..583822ccb8d 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}
@@ -280,32 +279,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 af5ceaea676..bd569abf90e 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 3e01c25e975..78ad2166698 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 56f9b46dbdf..f557997497b 100644
--- a/addons/purchase/__openerp__.py
+++ b/addons/purchase/__openerp__.py
@@ -35,7 +35,7 @@
""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
- 'depends': ['base', 'account', 'stock', 'process', 'mrp_procurement'],
+ 'depends': ['base', 'account', 'stock', 'process', 'procurement'],
'init_xml': [],
'update_xml': [
diff --git a/addons/purchase/board_purchase_view.xml b/addons/purchase/board_purchase_view.xml
index 5548b3f2838..8e08ee7134d 100644
--- a/addons/purchase/board_purchase_view.xml
+++ b/addons/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
- 36
-
-
+
+
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 2cfd4247bcf..af00075a6d3 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),
@@ -428,6 +427,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 +591,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 +633,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 +698,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'),
}
@@ -726,17 +726,16 @@ class mrp_procurement(osv.osv):
po_obj = self.pool.get('purchase.order')
for procurement in self.browse(cr, uid, ids):
res_id = procurement.move_id.id
- partner_list = sorted([(partner_id.sequence, partner_id) for partner_id in procurement.product_id.seller_ids if partner_id])
- partner_rec = partner_list and partner_list[0] and partner_list[0][1] or False
- partner = partner_rec.name or False
- partner_id = partner_rec.id or False
+ 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
uom_id = procurement.product_id.uom_po_id.id
qty = uom_obj._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, uom_id)
- if partner_rec.qty:
+ if 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]
@@ -779,7 +778,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 17fd47b7012..8086a169d9d 100644
--- a/addons/purchase/purchase_view.xml
+++ b/addons/purchase/purchase_view.xml
@@ -3,7 +3,7 @@
-
@@ -21,9 +21,7 @@
parent="base.menu_purchase_root" sequence="4"/>
-
-
+
-
+
-
+
@@ -161,7 +159,7 @@
-
+
@@ -235,7 +233,13 @@
+
+
+
+
+
@@ -245,17 +249,14 @@
-
-
-
-
-
-
-
+
+
+
+
-
-
+
+
@@ -288,7 +289,7 @@
-
+
@@ -315,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 71f2638d628..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 order', 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,32 +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),
- 'shipped_qty':fields.integer('Received Qty', readonly=True),
- 'invoiced_qty':fields.integer('Invoiced Qty', readonly=True),
'user_id':fields.many2one('res.users', 'Responsible', readonly=True),
- 'delay':fields.float('Days to Close', digits=(16,2), readonly=True),
- 'delay_pass':fields.float('Overpassed expected', digits=(16,2), 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),
@@ -94,33 +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,
- s.shipped::integer as shipped_qty,
- l.invoiced::integer as invoiced_qty,
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(s.minimum_planned_date,s.date_order))/(24*60*60)::decimal(16,2) as delay_pass,
+ 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.shipped,
- l.invoiced,
s.partner_id,
+ l.product_qty,
+ u.factor,
s.location_id,
+ l.price_unit,
s.date_approve,
- s.minimum_planned_date,
+ l.date_planned,
date_trunc('day',s.minimum_planned_date),
s.partner_address_id,
s.pricelist_id,
@@ -132,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 468f3892a13..b2bdf840c3d 100644
--- a/addons/purchase/report/purchase_report_view.xml
+++ b/addons/purchase/report/purchase_report_view.xml
@@ -8,7 +8,6 @@
-
@@ -20,14 +19,13 @@
tree
-
-
-
-
-
+
+
+
+
+
-
-
+
@@ -35,13 +33,14 @@
-
-
-
+
+
-
-
-
+
+
+
+
+
@@ -53,65 +52,56 @@
-
+
+ name="month"
+ domain="[('date','<=', time.strftime('%%Y-%%m-%%d')), ('date','>',(datetime.date.today()-datetime.timedelta(days=30)).strftime('%%Y-%%m-%%d'))]"
+ help="Tasks performed in this month"/>
+ string="Quotations"
+ name="quotes"
+ domain="[('state','=','draft')]"/>
-
-
-
+ string="Orders"
+ name="orders"
+ domain="[('state','<>','draft'),('state','<>','cancel')]"/>
-
+
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
-
+
-
+
-
@@ -127,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/report_account/i18n/hr.po b/addons/report_account/i18n/hr.po
index 62dde41d6fc..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-09 03:35+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 0f1647f8d06..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-09 03:35+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 245730b21cd..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-09 03:35+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 ac73360d8b3..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-09 03:36+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 c9ecd125a04..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-09 03:35+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 a40056a4f50..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-09 03:35+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 0dc383bac14..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-09 03:35+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 aa5adc5fe71..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-09 03:35+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 0b134a26c2f..5e5b4fc41ad 100644
--- a/addons/report_task/i18n/es.po
+++ b/addons/report_task/i18n/es.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-10 03:36+0000\n"
+"X-Launchpad-Export-Date: 2010-06-11 03:43+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: report_task
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 2a804db1707..d60b132a827 100644
--- a/addons/sale/__openerp__.py
+++ b/addons/sale/__openerp__.py
@@ -44,11 +44,11 @@
* Top 10 sales of the month
* Cases statistics
* Graph of sales by product
- * Graph of cases of the month
+ * Graph of cases of the month
""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
- 'depends': ['product', 'stock', 'mrp_procurement', 'process','board'],
+ 'depends': ['product', 'stock', 'procurement', 'process','board'],
'init_xml': [],
'update_xml': [
'wizard/sale_make_invoice_advance.xml',
@@ -72,6 +72,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 a39cac7c03f..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-09 03:35+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 b947fd04fd9..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-09 03:35+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 68f50068ec0..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),
diff --git a/addons/sale/report/sale_report_view.xml b/addons/sale/report/sale_report_view.xml
index f6090638891..9b8ed32ede4 100644
--- a/addons/sale/report/sale_report_view.xml
+++ b/addons/sale/report/sale_report_view.xml
@@ -128,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 ba92bad2ad4..94847945821 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -113,7 +113,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():
@@ -254,7 +254,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 = {
@@ -645,6 +645,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,
@@ -661,7 +662,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,
@@ -679,10 +680,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,
@@ -696,7 +697,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.
@@ -810,7 +811,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)]}),
@@ -825,7 +826,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. \
@@ -859,7 +860,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):
@@ -868,7 +869,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 ad39f7f1cf1..4a12e1dafaf 100644
--- a/addons/sale/sale_view.xml
+++ b/addons/sale/sale_view.xml
@@ -92,6 +92,15 @@
+
+
+
sale.order.formsale.order
@@ -112,7 +121,7 @@
-
+
@@ -131,6 +140,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)"
/>
+
-
+
+
-
+
@@ -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_view.xml b/addons/scrum/scrum_view.xml
index d4631a680ca..b076e98038a 100644
--- a/addons/scrum/scrum_view.xml
+++ b/addons/scrum/scrum_view.xml
@@ -141,8 +141,8 @@
-
-
+
+
-
+
@@ -188,7 +188,7 @@
scrum.sprinttree
-
+
@@ -268,8 +268,8 @@
-
-
+
+
@@ -357,10 +357,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/wizard/share_wizard.py b/addons/share/wizard/share_wizard.py
index c5e2aef2ff6..722fa9809b0 100644
--- a/addons/share/wizard/share_wizard.py
+++ b/addons/share/wizard/share_wizard.py
@@ -76,7 +76,7 @@ class share_create(osv.osv_memory):
'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( [ ('readonly','READ ONLY'),('readwrite','READ & WRITE')],'Access Mode'),
+ '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'),
}
@@ -84,6 +84,7 @@ class share_create(osv.osv_memory):
'user_type' : 'existing',
'domain': '[]',
'access_mode': 'readonly'
+
}
def default_get(self, cr, uid, fields, context=None):
@@ -124,7 +125,8 @@ class share_create(osv.osv_memory):
vals ={
'domain': this.domain,
'action_id': this.action_id and this.action_id.id or False,
- }
+ }
+ step1_id = this.id
context.update(vals)
value = {
@@ -132,7 +134,8 @@ class share_create(osv.osv_memory):
'view_type': 'form',
'view_mode': 'form',
'res_model': 'share.create',
- 'view_id': False,
+ '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,
@@ -162,9 +165,6 @@ class share_create(osv.osv_memory):
'user_type': this.user_type,
'existing_user_ids': map(lambda x:x.id, this.user_ids),
'new_user': this.new_user,
- 'domain': this.domain,
- 'access_mode': this.access_mode,
- 'action_id': this.action_id and this.action_id.id or False
}
context.update(vals)
@@ -189,6 +189,13 @@ class share_create(osv.osv_memory):
"""
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')
@@ -248,7 +255,7 @@ class share_create(osv.osv_memory):
#ACCESS RIGHTS / IR.RULES COMPUTATION
- #TODO: TO Resolve Recurrent Problems
+
active_model_ids = model_obj.search(cr, uid, [('model','=',active_model)])
active_model_id = active_model_ids and active_model_ids[0] or False
@@ -268,14 +275,36 @@ class share_create(osv.osv_memory):
return obj
- obj0 = model_obj.browse(cr, uid, active_model_id, context=context)
+ 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':
- for rel_field, model in obj1+obj2+obj3:
+ 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,
@@ -283,27 +312,68 @@ class share_create(osv.osv_memory):
'perm_read' : True
})
if access_mode == 'readwrite':
- for rel_field, model in obj1+obj2+obj3:
+ 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': 'Read Access of group %s on %s model'%(share_group_name, model.name),
+ '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_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, obj0.model),
- 'model_id': obj0.id,
- 'domain': domain,
- 'group_ids': [(6,0,[group_id])]
+ '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 = []
@@ -314,15 +384,10 @@ class share_create(osv.osv_memory):
rule_obj.create(cr, uid, {
'name': '%s-%s'%(share_group_name, model.model),
'model_id': model.id,
- 'domain': obj1_domain,
+ 'domain_force': obj1_domain,
'groups': [(6,0,[group_id])]
})
- # TODO:
- # 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)
- context['share_model'] = active_model
+ context['share_model'] = active_model.model
context['share_rec_id'] = active_id
diff --git a/addons/share/wizard/share_wizard_view.xml b/addons/share/wizard/share_wizard_view.xml
index 9e9b23f7f43..159583eecbb 100644
--- a/addons/share/wizard/share_wizard_view.xml
+++ b/addons/share/wizard/share_wizard_view.xml
@@ -39,8 +39,7 @@
-
-
+
@@ -54,13 +53,12 @@
-
-
+
+
-
diff --git a/addons/stock/__openerp__.py b/addons/stock/__openerp__.py
index 60ccea7d137..dd830143e6f 100644
--- a/addons/stock/__openerp__.py
+++ b/addons/stock/__openerp__.py
@@ -69,7 +69,6 @@ Thanks to the double entry management, the inventory controlling is powerful and
"partner_view.xml",
"report/report_stock_move_view.xml",
"report/report_stock_view.xml",
- "report/report_stock_picking_view.xml",
"security/stock_security.xml",
"security/ir.model.access.csv",
"board_warehouse_view.xml"
@@ -79,4 +78,3 @@ Thanks to the double entry management, the inventory controlling is powerful and
'active': False,
'certificate': '0055421559965',
}
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/stock/i18n/pl.po b/addons/stock/i18n/pl.po
index a4406384e8e..117d90e683a 100644
--- a/addons/stock/i18n/pl.po
+++ b/addons/stock/i18n/pl.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-05-21 08:22+0000\n"
+"PO-Revision-Date: 2010-06-13 15:17+0000\n"
"Last-Translator: Grzegorz Grzelak (Cirrus.pl) \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-05-22 04:00+0000\n"
+"X-Launchpad-Export-Date: 2010-06-14 03:42+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: stock
@@ -120,7 +120,7 @@ msgstr "Otrzymane produkty"
#: model:ir.actions.act_window,name:stock.action_picking_tree4
#: model:ir.ui.menu,name:stock.menu_action_picking_tree4
msgid "Incoming Products"
-msgstr "Przyjmowanie produktów"
+msgstr "Przyjęcia zewnętrzne"
#. module: stock
#: field:stock.picking,name:0
@@ -592,7 +592,7 @@ msgstr ""
#: model:ir.actions.act_window,name:stock.action_picking_form
#: model:ir.ui.menu,name:stock.menu_action_picking_form
msgid "New Reception Packing"
-msgstr "Nowy odbiór listy przesunięć"
+msgstr "Nowe przyjęcia zewnętrzne"
#. module: stock
#: wizard_field:stock.move.track,init,quantity:0
@@ -837,7 +837,7 @@ msgstr ""
#: model:ir.actions.act_window,name:stock.action_picking_tree9
#: model:ir.ui.menu,name:stock.menu_action_picking_tree9
msgid "New Internal Packing"
-msgstr "Nowa lista przesunięć wewnętrznych"
+msgstr "Nowe przesunięcie wewnętrzne"
#. module: stock
#: view:stock.inventory:0
@@ -1330,7 +1330,7 @@ msgstr "Cel przesunięcia"
#: model:ir.actions.act_window,name:stock.action_inventory_form_new
#: model:ir.ui.menu,name:stock.menu_action_inventory_form_new
msgid "New Periodical Inventory"
-msgstr "Nowa inentaryzacja okresowa"
+msgstr "Nowa inwentaryzacja okresowa"
#. module: stock
#: field:stock.production.lot,revisions:0
@@ -1346,7 +1346,7 @@ msgstr "FIFO"
#: model:ir.actions.act_window,name:stock.action_picking_tree2_delivery
#: model:ir.ui.menu,name:stock.menu_picking_waiting_delivery
msgid "Delivery Orders to Process"
-msgstr "Zamówienia dostawy do przetworzenia"
+msgstr "Wydania zewnętrzne do obsługi"
#. module: stock
#: field:stock.move,priority:0
@@ -1493,7 +1493,7 @@ msgstr ""
#: model:ir.actions.act_window,name:stock.action_picking_tree3_delivery
#: model:ir.ui.menu,name:stock.menu_action_picking_tree3_delivery
msgid "Future Delivery Orders"
-msgstr "Przyszłe zamówienia dostawy"
+msgstr "Przyszłe wydania zewnętrzne"
#. module: stock
#: selection:stock.location,icon:0
@@ -1990,7 +1990,7 @@ msgstr ""
#: model:ir.actions.act_window,name:stock.action_picking_tree_delivery
#: model:ir.ui.menu,name:stock.menu_action_picking_tree_delivery
msgid "Delivery Orders"
-msgstr "Zamówienia dostawy"
+msgstr "Wydania zewnętrzne"
#. module: stock
#: selection:stock.location,icon:0
@@ -2197,7 +2197,7 @@ msgstr "Czy chcesz ustawić zapasy na 0 ?"
#. module: stock
#: selection:stock.picking,move_type:0
msgid "Direct Delivery"
-msgstr "Dostawa bezpośrednia"
+msgstr "Dostawa częściowa"
#. module: stock
#: selection:stock.location,icon:0
@@ -2345,7 +2345,7 @@ msgstr ""
#. module: stock
#: selection:stock.picking,type:0
msgid "Delivery"
-msgstr "Dostawa"
+msgstr "Wydanie zewnętrzne"
#. module: stock
#: model:ir.actions.act_window,name:stock.action5
diff --git a/addons/stock/partner_view.xml b/addons/stock/partner_view.xml
index be2ed4bfc55..9ba4073e2e2 100644
--- a/addons/stock/partner_view.xml
+++ b/addons/stock/partner_view.xml
@@ -12,10 +12,10 @@
-
-
-
-
+
+
+
+
diff --git a/addons/stock/product.py b/addons/stock/product.py
index dc300994232..9a19d3e84c3 100644
--- a/addons/stock/product.py
+++ b/addons/stock/product.py
@@ -24,16 +24,38 @@ from tools.translate import _
class product_product(osv.osv):
- _inherit = "product.product"
+ _inherit = "product.product"
+
+ def get_product_accounts(self, cr, uid, product_id, context=None):
+ """ To get the stock input account, stock output account and stock journal related to product.
+ @param product_id: product id
+ @return: dictionary which contains information regarding stock input account, stock output account and stock journal
+ """
+ product_obj = self.pool.get('product.product').browse(cr, uid, product_id, context)
+
+ stock_input_acc = product_obj.property_stock_account_input and product_obj.property_stock_account_input.id or False
+ if not stock_input_acc:
+ stock_input_acc = product_obj.categ_id.property_stock_account_input_categ and product_obj.categ_id.property_stock_account_input_categ.id or False
+
+ stock_output_acc = product_obj.property_stock_account_output and product_obj.property_stock_account_output.id or False
+ if not stock_output_acc:
+ stock_output_acc = product_obj.categ_id.property_stock_account_output_categ and product_obj.categ_id.property_stock_account_output_categ.id or False
+
+ journal_id = product_obj.categ_id.property_stock_journal and product_obj.categ_id.property_stock_journal.id or False
+ account_variation = product_obj.categ_id.property_stock_variation and product_obj.categ_id.property_stock_variation.id or False
+
+ return {
+ 'stock_account_input': stock_input_acc,
+ 'stock_account_output': stock_output_acc,
+ 'stock_journal': journal_id,
+ 'property_stock_variation': account_variation
+ }
def do_change_standard_price(self, cr, uid, ids, datas, context={}):
- """
- Changes the Standard Price of Product and creates an account move accordingly.
-
- @param datas : dict. contain default datas like new_price, stock_output_account, stock_input_account, stock_journal
- @param context: A standard dictionary
-
- @return:
+ """ Changes the Standard Price of Product and creates an account move accordingly.
+ @param datas : dict. contain default datas like new_price, stock_output_account, stock_input_account, stock_journal
+ @param context: A standard dictionary
+ @return:
"""
location_obj = self.pool.get('stock.location')
@@ -44,10 +66,12 @@ class product_product(osv.osv):
stock_output_acc = datas.get('stock_output_account', False)
stock_input_acc = datas.get('stock_input_account', False)
journal_id = datas.get('stock_journal', False)
-
+ property_obj=self.pool.get('ir.property')
+ product_obj=self.browse(cr,uid,ids)[0]
+ account_variation = product_obj.categ_id.property_stock_variation
move_ids = []
+ loc_ids = location_obj.search(cr, uid,[('usage','=','internal')])
for rec_id in ids:
- loc_ids = location_obj.search(cr, uid, [('account_id','<>',False),('usage','=','internal')])
for location in location_obj.browse(cr, uid, loc_ids):
c = context.copy()
c.update({
@@ -60,7 +84,8 @@ class product_product(osv.osv):
diff = product.standard_price - new_price
assert diff, _("Could not find any difference between standard price and new price!")
if qty:
- location_account = location.account_id and location.account_id.id or False
+ location_account = account_variation and account_variation.id or False
+
company_id = location.company_id and location.company_id.id or False
assert location_account, _('Inventory Account is not specified for Location: %s' % (location.name))
assert company_id, _('Company is not specified in Location')
@@ -147,7 +172,10 @@ class product_product(osv.osv):
return _('Products: ')+self.pool.get('stock.location').browse(cr, user, context['location'], context).name
return res
- def get_product_available(self,cr,uid,ids,context=None):
+ def get_product_available(self, cr, uid, ids, context=None):
+ """ Finds whether product is available or not in particular warehouse.
+ @return: Dictionary of values
+ """
if context is None:
context = {}
states = context.get('states',[])
@@ -173,6 +201,8 @@ class product_product(osv.osv):
if context.get('location', False):
if type(context['location']) == type(1):
location_ids = [context['location']]
+ elif type(context['location']) in (type(''), type(u'')):
+ location_ids = self.pool.get('stock.location').search(cr, uid, [('name','ilike',context['location'])], context=context)
else:
location_ids = context['location']
else:
@@ -252,22 +282,25 @@ class product_product(osv.osv):
return res
def _product_available(self, cr, uid, ids, field_names=None, arg=False, context={}):
+ """ Finds the incoming and outgoing quantity of product.
+ @return: Dictionary of values
+ """
if not field_names:
- field_names=[]
+ field_names = []
res = {}
for id in ids:
res[id] = {}.fromkeys(field_names, 0.0)
for f in field_names:
c = context.copy()
- if f=='qty_available':
- c.update({ 'states':('done',), 'what':('in', 'out') })
- if f=='virtual_available':
- c.update({ 'states':('confirmed','waiting','assigned','done'), 'what':('in', 'out') })
- if f=='incoming_qty':
- c.update({ 'states':('confirmed','waiting','assigned'), 'what':('in',) })
- if f=='outgoing_qty':
- c.update({ 'states':('confirmed','waiting','assigned'), 'what':('out',) })
- stock=self.get_product_available(cr,uid,ids,context=c)
+ if f == 'qty_available':
+ c.update({ 'states': ('done',), 'what': ('in', 'out') })
+ if f == 'virtual_available':
+ c.update({ 'states': ('confirmed','waiting','assigned','done'), 'what': ('in', 'out') })
+ if f == 'incoming_qty':
+ c.update({ 'states': ('confirmed','waiting','assigned'), 'what': ('in',) })
+ if f == 'outgoing_qty':
+ c.update({ 'states': ('confirmed','waiting','assigned'), 'what': ('out',) })
+ stock = self.get_product_available(cr, uid, ids, context=c)
for id in ids:
res[id][f] = stock.get(id, 0.0)
return res
@@ -280,8 +313,15 @@ class product_product(osv.osv):
'track_production': fields.boolean('Track Production Lots' , help="Forces to use a Production Lot during production order"),
'track_incoming': fields.boolean('Track Incoming Lots', help="Forces to use a tracking lot during receptions"),
'track_outgoing': fields.boolean('Track Outgoing Lots', help="Forces to use a tracking lot during deliveries"),
- 'location_id': fields.dummy(string='Location', relation='stock.location', type='many2one', domain=[('usage','=','internal')]),
+ 'location_id': fields.dummy(string='Location', relation='stock.location', type='many2one'),
+ 'valuation':fields.selection([('manual_periodic', 'Periodic (manual)'),
+ ('real_time','Real Time (automatized)'),], 'Stock Valuation', help="Decide if the system must automatically creates account moves based on stock moves", required=True),
}
+
+ _defaults = {
+ 'valuation': lambda *a: 'manual_periodic',
+ }
+
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
res = super(product_product,self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
if context == None:
@@ -367,7 +407,6 @@ class product_template(osv.osv):
string='Stock Output Account', method=True, view_load=True,
help='This account will be used, instead of the default one, to value output stock'),
}
-
product_template()
@@ -386,8 +425,13 @@ class product_category(osv.osv):
type='many2one', relation='account.account',
string='Stock Output Account', method=True, view_load=True,
help='This account will be used to value the output stock'),
+ 'property_stock_variation': fields.property('account.account',
+ type='many2one',
+ relation='account.account',
+ string="Stock variation Account",
+ method=True, view_load=True,
+ help="This account will be used in product when valuation type is real-time valuation ",),
}
-
product_category()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/stock/product_view.xml b/addons/stock/product_view.xml
index 02c60968e04..36ba20b3b05 100644
--- a/addons/stock/product_view.xml
+++ b/addons/stock/product_view.xml
@@ -8,8 +8,8 @@
search
-
-
+
+
@@ -43,9 +43,9 @@
-
-
-
+
+
+
@@ -115,14 +115,26 @@
-
-
-
+
+
+
+
+ product.valuation.stock.form.inherit
+ product.product
+ form
+
+
+
+
+
+
+
+
diff --git a/addons/stock/report/__init__.py b/addons/stock/report/__init__.py
index a0a4bcb8ea5..381644fcd32 100644
--- a/addons/stock/report/__init__.py
+++ b/addons/stock/report/__init__.py
@@ -19,7 +19,6 @@
#
##############################################################################
-#import lot_overview
import product_stock
import lot_location
import ups
@@ -28,7 +27,4 @@ import lot_overview
import lot_overview_all
import report_stock
import report_stock_move
-import report_stock_picking
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/stock/report/report_stock_move.py b/addons/stock/report/report_stock_move.py
index 8d905a4c4d7..c26f0c13006 100755
--- a/addons/stock/report/report_stock_move.py
+++ b/addons/stock/report/report_stock_move.py
@@ -34,19 +34,20 @@ class report_stock_move(osv.osv):
'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),
- 'partner_id':fields.many2one('res.partner', 'Partner', readonly=True),
+ 'partner_id':fields.many2one('res.partner.address', 'Partner', readonly=True),
'product_id':fields.many2one('product.product', 'Product', readonly=True),
+ 'company_id':fields.many2one('res.company', 'Company', readonly=True),
+ 'picking_id':fields.many2one('stock.picking', 'Packing', readonly=True),
+ 'type': fields.selection([('out', 'Sending Goods'), ('in', 'Getting Goods'), ('internal', 'Internal'), ('delivery', 'Delivery')], 'Shipping Type', required=True, select=True, help="Shipping type specify, goods coming in or going out."),
'location_id': fields.many2one('stock.location', 'Source Location', readonly=True, select=True, help="Sets a location if you produce at a fixed location. This can be a partner location if you subcontract the manufacturing operations."),
'location_dest_id': fields.many2one('stock.location', 'Dest. Location', readonly=True, select=True, help="Location where the system will stock the finished products."),
+ 'state': fields.selection([('draft', 'Draft'), ('waiting', 'Waiting'), ('confirmed', 'Confirmed'), ('assigned', 'Available'), ('done', 'Done'), ('cancel', 'Cancelled')], 'State', readonly=True, select=True),
'product_qty':fields.integer('Qty',readonly=True),
'value' : fields.float('Total Value', required=True),
- 'product_uom': fields.many2one('product.uom', 'Product UOM', readonly=True),
- 'state': fields.selection([('draft', 'Draft'), ('waiting', 'Waiting'), ('confirmed', 'Confirmed'), ('assigned', 'Available'), ('done', 'Done'), ('cancel', 'Cancelled')], 'State', readonly=True, select=True,
- help='When the stock move is created it is in the \'Draft\' state.\n After that it is set to \'Confirmed\' state.\n If stock is available state is set to \'Avaiable\'.\n When the picking it done the state is \'Done\'.\
- \nThe state is \'Waiting\' if the move is waiting for another one.'),
- 'day_diff':fields.integer('Expected Performance',readonly=True),
+ 'day_diff2':fields.float('Delay (Days)',readonly=True, digits=(16,2), group_operator="avg"),
+ 'day_diff1':fields.float('Planned (Days)',readonly=True, digits=(16,2), group_operator="avg"),
+ 'day_diff':fields.float('Real (Days)',readonly=True, digits=(16,2), group_operator="avg"),
}
-
def init(self, cr):
tools.drop_view_if_exists(cr, 'report_stock_move')
cr.execute("""
@@ -56,8 +57,13 @@ class report_stock_move(osv.osv):
to_char(date_trunc('day',m.date_planned), 'YYYY') as year,
to_char(date_trunc('day',m.date_planned), 'MM') as month,
to_char(date_trunc('day',m.date_planned), 'YYYY-MM-DD') as day,
- (date(m.date_planned)-date(m.date_expected)) as day_diff,
+ avg(date(m.date_planned)-date(m.create_date)) as day_diff,
+ avg(date(m.date_expected)-date(m.create_date)) as day_diff1,
+ avg(date(m.date_planned)-date(m.date_expected)) as day_diff2,
m.address_id as partner_id,
+ m.picking_id as picking_id,
+ m.company_id as company_id,
+ p.type as type,
m.location_id as location_id,
m.location_dest_id as location_dest_id,
m.product_id as product_id,
@@ -65,11 +71,83 @@ class report_stock_move(osv.osv):
m.product_uom as product_uom,
sum(m.product_qty) as product_qty,
pt.standard_price * sum(m.product_qty) as value
- from stock_move m ,product_product pp,product_template pt
- where
- m.product_id=pp.id and pp.product_tmpl_id=pt.id
+ from
+ stock_move m
+ left join stock_picking p on (m.picking_id=p.id)
+ left join product_product pp on (m.product_id=pp.id)
+ left join product_template pt on (pp.product_tmpl_id=pt.id)
group by
m.id, m.product_id,m.address_id, m.location_id, m.location_dest_id,
- m.date_planned, m.state, m.product_uom,pt.standard_price,m.date_expected )
+ m.date_planned, m.state, m.product_uom,pt.standard_price,
+ m.picking_id, p.type, m.company_id
+ )
""")
report_stock_move()
+
+
+class report_stock_inventory(osv.osv):
+ _name = "report.stock.inventory"
+ _description = "Stock Statistics"
+ _auto = False
+ _columns = {
+ 'date_planned': fields.datetime('Date', readonly=True),
+ 'partner_id':fields.many2one('res.partner.address', 'Partner', readonly=True),
+ 'product_id':fields.many2one('product.product', 'Product', readonly=True),
+ 'location_id': fields.many2one('stock.location', 'Location', readonly=True),
+ 'prodlot_id': fields.many2one('stock.production.lot', 'Lot', readonly=True),
+ 'company_id': fields.many2one('res.company', 'Company', readonly=True),
+ 'product_qty':fields.float('Qty', digits=(16,2), readonly=True),
+ 'value' : fields.float('Total Value', digits=(16,2), required=True),
+ 'state': fields.selection([('draft', 'Draft'), ('waiting', 'Waiting'), ('confirmed', 'Confirmed'), ('assigned', 'Available'), ('done', 'Done'), ('cancel', 'Cancelled')], 'State', readonly=True, select=True,
+ help='When the stock move is created it is in the \'Draft\' state.\n After that it is set to \'Confirmed\' state.\n If stock is available state is set to \'Avaiable\'.\n When the picking it done the state is \'Done\'.\
+ \nThe state is \'Waiting\' if the move is waiting for another one.'),
+ 'location_type': fields.selection([('supplier', 'Supplier Location'), ('view', 'View'), ('internal', 'Internal Location'), ('customer', 'Customer Location'), ('inventory', 'Inventory'), ('procurement', 'Procurement'), ('production', 'Production'), ('transit', 'Transit Location for Inter-Companies Transfers')], 'Location Type', required=True),
+ }
+ def init(self, cr):
+ tools.drop_view_if_exists(cr, 'report_stock_inventory')
+ cr.execute("""
+create or replace view report_stock_inventory as (
+ (select
+ min(m.id) as id, m.date_planned as date_planned,
+ m.address_id as partner_id, m.location_id as location_id,
+ m.product_id as product_id, l.usage as location_type,
+ m.company_id,
+ m.state as state, m.prodlot_id as prodlot_id,
+ sum(-m.product_qty*u.factor)::decimal(16,2) as product_qty,
+ sum(-pt.standard_price * m.product_qty * u.factor)::decimal(16,2) as value
+ from
+ stock_move m
+ left join stock_picking p on (m.picking_id=p.id)
+ left join product_product pp on (m.product_id=pp.id)
+ left join product_template pt on (pp.product_tmpl_id=pt.id)
+ left join product_uom u on (m.product_uom=u.id)
+ left join stock_location l on (m.location_id=l.id)
+ group by
+ m.id, m.product_id, m.address_id, m.location_id, m.prodlot_id,
+ m.date_planned, m.state, l.usage, m.company_id
+) union all (
+ select
+ -m.id as id, m.date_planned as date_planned,
+ m.address_id as partner_id, m.location_dest_id as location_id,
+ m.product_id as product_id, l.usage as location_type,
+ m.company_id,
+ m.state as state, m.prodlot_id as prodlot_id,
+ sum(m.product_qty*u.factor)::decimal(16,2) as product_qty,
+ sum(pt.standard_price * m.product_qty * u.factor)::decimal(16,2) as value
+ from
+ stock_move m
+ left join stock_picking p on (m.picking_id=p.id)
+ left join product_product pp on (m.product_id=pp.id)
+ left join product_template pt on (pp.product_tmpl_id=pt.id)
+ left join product_uom u on (m.product_uom=u.id)
+ left join stock_location l on (m.location_dest_id=l.id)
+ group by
+ m.id, m.product_id, m.address_id, m.location_id, m.location_dest_id,
+ m.prodlot_id, m.date_planned, m.state, l.usage, m.company_id
+ )
+);
+ """)
+report_stock_inventory()
+
+
+
diff --git a/addons/stock/report/report_stock_move_view.xml b/addons/stock/report/report_stock_move_view.xml
index a3771b4a480..5adc3407b0f 100755
--- a/addons/stock/report/report_stock_move_view.xml
+++ b/addons/stock/report/report_stock_move_view.xml
@@ -1,26 +1,35 @@
+
+
+
report.stock.move.treereport.stock.movetree
-
-
-
+
+
+
+
+
+
-
-
+
+
-
-
-
+
+
+
@@ -30,9 +39,9 @@
report.stock.movegraph
-
+
-
+
@@ -42,54 +51,50 @@
report.stock.movesearch
-
+
-
-
-
-
-
-
+ name="done"
+ icon="terp-dialog-close"
+ domain="[('state','=','done')]"
+ help = "Completed Stock-Moves"/>
+
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
-
-
-
+
+
+
+
@@ -97,9 +102,9 @@
-
-
-
+
+
+
@@ -107,20 +112,110 @@
- Stock Moves
+ Moves Analysisreport.stock.moveformtree,graph
-
- {'search_default_product':1, 'search_default_src_location':1,'search_default_done':1,'group_by':[]}
+
+ {'contact_display': 'partner', 'search_default_month':1, 'search_default_group_product':1,'search_default_done':1,'group_by':[], 'group_by_no_leaf':1}
+
+
+
+
+
+
+ report.stock.inventory.tree
+ report.stock.inventory
+ tree
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+ report.stock.inventory.graph
+ report.stock.inventory
+ graph
+
+
+
+
+
+
+
+
+
+ report.stock.inventory.search
+ report.stock.inventory
+ search
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Inventory Analysis
+ report.stock.inventory
+ form
+ tree,graph
+
+ {'contact_display': 'partner', 'search_default_real':1, 'search_default_location_type_internal':1,'search_default_group_product':1,'search_default_group_location':1,'group_by':[], 'group_by_no_leaf':1}
+
+
-
diff --git a/addons/stock/report/report_stock_picking.py b/addons/stock/report/report_stock_picking.py
deleted file mode 100644
index b6e2a3d3373..00000000000
--- a/addons/stock/report/report_stock_picking.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-#
-##############################################################################
-from osv import fields,osv
-import tools
-
-class report_stock_picking(osv.osv):
- _name = "report.stock.picking"
- _description = "Stock Picking Report"
- _auto = False
- _columns = {
- 'year': fields.char('Year',size=64,required=False, 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),
- 'day': fields.char('Day', size=128, readonly=True),
- 'nbr': fields.integer('# of Lines', readonly=True),
- 'nbp': fields.integer('# of Picking', readonly=True),
- 'partner_id':fields.many2one('res.partner', 'Partner', readonly=True),
- 'product_qty': fields.float('# of Products', readonly=True),
- 'product_uos_qty': fields.float('# of Products', readonly=True),
- 'product_id': fields.many2one('product.product', 'Product', readonly=True),
- 'date': fields.date('Date', readonly=True),
- 'avg_days_to_deliver': fields.float('Avg Days to Deliver', digits=(16,2), readonly=True, group_operator="avg",
- help="Number of Avg Days to deliver"),
- 'state': fields.selection([('draft', 'Draft'),('auto', 'Waiting'),('confirmed', 'Confirmed'),('assigned', 'Available'),('done', 'Done'),('cancel', 'Cancelled')], 'State'),
- 'type': fields.selection([('out', 'Sending Goods'), ('in', 'Getting Goods'), ('internal', 'Internal'), ('delivery', 'Delivery')], 'Shipping Type', required=True),
- 'company_id': fields.many2one('res.company', 'Company', readonly=True),
- 'invoice_state': fields.selection([
- ("invoiced", "Invoiced"),
- ("2binvoiced", "To Be Invoiced"),
- ("none", "Not from Picking")], "Invoice Status",readonly=True),
- 'min_date': fields.date('Expected Date',help="Expected date for Picking. Default it takes current date"),
- 'order_date': fields.date('Order Date', help="Date of Order"),
- 'date_done': fields.date('Date Done', help="Date of completion"),
- 'location_id': fields.many2one('stock.location', 'Source Location', help="Sets a location if you produce at a fixed location. This can be a partner location if you subcontract the manufacturing operations."),
- 'location_dest_id': fields.many2one('stock.location', 'Dest. Location', help="Location where the system will stock the finished products."),
- 'max_date': fields.date('Max.Expected Date'),
- 'product_uos': fields.many2one('product.uom', 'Product UOS'),
- 'product_uom': fields.many2one('product.uom', 'Product UOM'),
- }
- def init(self, cr):
- tools.drop_view_if_exists(cr, 'report_stock_picking')
- cr.execute("""
- create or replace view report_stock_picking as (
- select
- min(sm.id) as id,
- date_trunc('day',sp.min_date) as min_date,
- date_trunc('day',sp.date) as order_date,
- date_trunc('day',sp.date_done) as date_done,
- date_trunc('day',sp.max_date) as max_date,
- to_char(sp.create_date, 'YYYY') as year,
- to_char(sp.create_date, 'MM') as month,
- to_char(sp.create_date, 'YYYY-MM-DD') as day,
- sp.address_id as partner_id,
- to_date(to_char(sp.create_date, 'MM-dd-YYYY'),'MM-dd-YYYY') as date,
- count(sm.id) as nbr,
- count(distinct sp.id) as nbp,
- sum(sm.product_qty) as product_qty,
- sum(sm.product_uos_qty) as product_uos_qty,
- sm.product_id as product_id,
- sm.location_dest_id as location_dest_id,
- sm.location_id as location_id,
- sp.type,
- sm.product_uos,
- sm.product_uom,
- sp.invoice_state,
- sp.company_id as company_id,
- avg(extract('epoch' from (sp.date_done-sp.create_date)))/(3600*24) as avg_days_to_deliver,
- sp.state
- from stock_move as sm
- left join stock_picking as sp ON (sm.picking_id=sp.id)
- group by sp.type,
- sp.create_date,
- sp.address_id,
- sm.product_id,
- to_char(sp.create_date, 'YYYY'),
- sm.location_dest_id,
- sm.location_id,
- to_char(sp.create_date, 'MM'),
- to_char(sp.create_date, 'YYYY-MM-DD'),
- sm.product_uos,
- sm.product_uom,
- date_trunc('day',sp.min_date),
- date_trunc('day',sp.date),
- date_trunc('day',sp.date_done),
- date_trunc('day',sp.max_date),
- sp.invoice_state,
- sp.company_id,
- sp.state
-
- )""")
-report_stock_picking()
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/stock/report/report_stock_picking_view.xml b/addons/stock/report/report_stock_picking_view.xml
deleted file mode 100644
index a14298ff771..00000000000
--- a/addons/stock/report/report_stock_picking_view.xml
+++ /dev/null
@@ -1,136 +0,0 @@
-
-
-
-
-
-
- report.stock.picking.tree
- report.stock.picking
- tree
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- report.stock.picking.graph
- report.stock.picking
- graph
-
-
-
-
-
-
-
-
-
-
-
- report.stock.picking.select
- report.stock.picking
- search
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Picking
- report.stock.picking
- form
- tree,graph
-
-
- {'search_default_Partner':1,'search_default_month':1,'group_by_no_leaf':1,'group_by':[]}
-
-
-
-
- tree
-
-
-
-
-
-
- graph
-
-
-
-
-
-
-
-
-
diff --git a/addons/stock/report/report_stock_view.xml b/addons/stock/report/report_stock_view.xml
index 34121d0c9ed..5732513e07a 100644
--- a/addons/stock/report/report_stock_view.xml
+++ b/addons/stock/report/report_stock_view.xml
@@ -2,104 +2,6 @@
-
- stock.report.prodlots.filter
- stock.report.prodlots
- search
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- stock.report.prodlots.view
- stock.report.prodlots
- form
-
-
-
-
-
-
-
-
-
-
-
- stock.report.prodlots.view
- stock.report.prodlots
- tree
-
-
-
-
-
-
-
-
-
-
-
- stock.report.prodlots.view
- stock.report.prodlots
- graph
-
-
-
-
-
-
-
-
-
-
- Inventory by Location
- ir.actions.act_window
- stock.report.prodlots
- form
- tree,form
- {'full':'1','search_default_internal_locations':1}
-
-
-
- stock.report.tracklots.view
- stock.report.tracklots
- tree
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/addons/stock/security/ir.model.access.csv b/addons/stock/security/ir.model.access.csv
index ca36c8460a7..4358e8ec9ab 100644
--- a/addons/stock/security/ir.model.access.csv
+++ b/addons/stock/security/ir.model.access.csv
@@ -1,5 +1,6 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_stock_incoterms_all","stock.incoterms all","model_stock_incoterms",,1,0,0,0
+"access_stock_incoterms_manager","stock.incoterms manager","model_stock_incoterms",stock.group_stock_manager,1,1,1,1
"access_stock_warehouse_manager","stock.warehouse.manager","model_stock_warehouse","stock.group_stock_manager",1,1,1,1
"access_stock_warehouse_user","stock.warehouse.user","model_stock_warehouse","base.group_user",1,0,0,0
"access_stock_location_manager","stock.location.manager","model_stock_location","stock.group_stock_manager",1,1,1,1
@@ -14,35 +15,27 @@
"access_stock_inventory_line","stock.inventory.line","model_stock_inventory_line","stock.group_stock_user",1,1,1,1
"access_stock_report_prodlots","stock.report.prodlots","model_stock_report_prodlots","stock.group_stock_manager",1,0,0,0
"access_stock_location_product_manager","stock.location product manager","model_stock_location","product.group_product_manager",1,0,0,0
-"access_stock_lines_date","report.stock.lines.date all","model_report_stock_lines_date",,1,0,0,0
+"access_stock_lines_date","report.stock.lines.date all","model_report_stock_lines_date",stock.group_stock_user,1,0,0,0
"access_stock_report_tracklots","stock.report.tracklots","model_stock_report_tracklots","stock.group_stock_user",1,1,1,1
-"access_report_products_to_received_planned","report.products.to.received.planned","model_report_products_to_received_planned","stock.group_stock_user",1,0,0,0
-"access_report_delivery_products_planned","report.delivery.products.planned","model_report_delivery_products_planned","stock.group_stock_user",1,0,0,0
-"access_stock_move_track","stock.move.track","model_stock_move_track","stock.group_stock_user",1,0,0,0
-"access_stock_move_consume","stock.move.consume","model_stock_move_consume","stock.group_stock_user",1,0,0,0
-"access_stock_move_scrap","stock.move.scrap","model_stock_move_scrap","stock.group_stock_user",1,0,0,0
-"access_stock_move_split","stock.move.split","model_stock_move_split","stock.group_stock_user",1,0,0,0
-"access_stock_move_split_lines","stock.move.split.lines","model_stock_move_split_lines","stock.group_stock_user",1,0,0,0
-"access_report_products_to_received_planned","report.products.to.received.planned","model_report_products_to_received_planned","stock.group_stock_user",1,0,0,0
-"access_report_delivery_products_planned","report.delivery.products.planned","model_report_delivery_products_planned","stock.group_stock_user",1,0,0,0
-"access_stock_move_track","stock.move.track","model_stock_move_track","stock.group_stock_user",1,0,0,0
-"access_stock_move_consume","stock.move.consume","model_stock_move_consume","stock.group_stock_user",1,0,0,0
-"access_stock_move_scrap","stock.move.scrap","model_stock_move_scrap","stock.group_stock_user",1,0,0,0
-"access_stock_move_split","stock.move.split","model_stock_move_split","stock.group_stock_user",1,0,0,0
-"access_stock_move_split_lines","stock.move.split.lines","model_stock_move_split_lines","stock.group_stock_user",1,0,0,0
-"access_stock_inventory_set_stock_zero","stock.inventory.set.stock.zero","model_stock_inventory_set_stock_zero","stock.group_stock_user",1,0,0,0
-"access_stock_fill_inventory","stock.fill.inventory","model_stock_fill_inventory","stock.group_stock_user",1,0,0,0
-"access_stock_inventory_line_split","stock.inventory.line.split","model_stock_inventory_line_split","stock.group_stock_user",1,0,0,0
-"access_stock_invoice_onshipping","stock.invoice.onshipping","model_stock_invoice_onshipping","stock.group_stock_user",1,0,0,0
+"access_report_products_to_received_planned","report.products.to.received.planned","model_report_products_to_received_planned","stock.group_stock_user",1,1,1,1
+"access_report_delivery_products_planned","report.delivery.products.planned","model_report_delivery_products_planned","stock.group_stock_user",1,1,1,1
+"access_stock_move_track","stock.move.track","model_stock_move_track","stock.group_stock_user",1,1,1,1
+"access_stock_move_consume","stock.move.consume","model_stock_move_consume","stock.group_stock_user",1,1,1,1
+"access_stock_move_scrap","stock.move.scrap","model_stock_move_scrap","stock.group_stock_user",1,1,1,1
+"access_stock_move_split","stock.move.split","model_stock_move_split","stock.group_stock_user",1,1,1,1
+"access_stock_move_split_lines","stock.move.split.lines","model_stock_move_split_lines","stock.group_stock_user",1,1,1,1
+"access_stock_inventory_set_stock_zero","stock.inventory.set.stock.zero","model_stock_inventory_set_stock_zero","stock.group_stock_user",1,1,1,1
+"access_stock_fill_inventory","stock.fill.inventory","model_stock_fill_inventory","stock.group_stock_user",1,1,1,1
+"access_stock_inventory_line_split","stock.inventory.line.split","model_stock_inventory_line_split","stock.group_stock_user",1,1,1,1
+"access_stock_invoice_onshipping","stock.invoice.onshipping","model_stock_invoice_onshipping","stock.group_stock_user",1,1,1,1
"access_stock_location_product","stock.location.product","model_stock_location_product","stock.group_stock_user",1,0,0,0
"access_report_stock_picking","report.stock.picking","model_report_stock_picking","stock.group_stock_user",1,0,0,0
-"access_stock_delivery","stock.delivery","model_stock_delivery","stock.group_stock_user",1,0,0,0
"access_stock_traceability_upstream","stock.traceability.upstream","model_stock_traceability_upstream","stock.group_stock_user",1,0,0,0
"access_stock_traceability_downstream","stock.traceability.downstream","model_stock_traceability_downstream","stock.group_stock_user",1,0,0,0
"access_stock_traceability_lot_upstream","stock.traceability.lot.upstream","model_stock_traceability_lot_upstream","stock.group_stock_user",1,0,0,0
"access_stock_traceability_lot_downstream","stock.traceability.lot.downstream","model_stock_traceability_lot_downstream","stock.group_stock_user",1,0,0,0
-"access_stock_partial_picking",stock.partial.picking","model_stock_partial_picking","stock.group_stock_user",1,0,0,0
-"access_stock_partial_move","stock.partial.move","model_stock_partial_move","stock.group_stock_user",1,0,0,0
+"access_stock_partial_picking",stock.partial.picking","model_stock_partial_picking",,1,1,1,1
+"access_stock_partial_move","stock.partial.move","model_stock_partial_move",,1,1,1,1
"access_stock_inventory_merge","stock.inventory.merge","model_stock_inventory_merge","stock.group_stock_user",1,0,0,0
"access_stock_change_standard_price","stock.change.standard.price","model_stock_change_standard_price","stock.group_stock_user",1,0,0,0
"access_action_traceability","action.traceability","model_action_traceability","stock.group_stock_user",1,0,0,0
diff --git a/addons/stock/security/stock_security.xml b/addons/stock/security/stock_security.xml
index 4dad60a3c97..099e32a889b 100644
--- a/addons/stock/security/stock_security.xml
+++ b/addons/stock/security/stock_security.xml
@@ -3,10 +3,10 @@
- Stock / Manager
+ Inventory / Manager
- Stock / Worker
+ Inventory / Worker
@@ -19,43 +19,43 @@
-
- stock_picking multi-company
+
+ stock_picking multi-company
- ['|',('company_id','=',False),('company_id','=',False)]
-
+ ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
+
- Warehouse multi-company
+ Warehouse multi-company['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
- Location multi-company
+ Location multi-company['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
- stock_move multi-company
+ stock_move multi-company['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
- Inventory Line multi-company
+ Inventory Line multi-company['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
- Inventory multi-company
+ Inventory multi-company['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index ecf09f4ae53..0e748ca418b 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
@@ -78,6 +77,9 @@ class stock_location(osv.osv):
return res
def _complete_name(self, cr, uid, ids, name, args, context):
+ """ Forms complete name of location from parent location to child location.
+ @return: Dictionary of values
+ """
def _get_one_full_name(location, level=4):
if location.location_id:
parent_path = _get_one_full_name(location.location_id, level-1) + "/"
@@ -90,6 +92,9 @@ class stock_location(osv.osv):
return res
def _product_qty_available(self, cr, uid, ids, field_names, arg, context={}):
+ """ Finds real and virtual quantity for product available at particular location.
+ @return: Dictionary of values
+ """
res = {}
for id in ids:
res[id] = {}.fromkeys(field_names, 0.0)
@@ -106,6 +111,10 @@ class stock_location(osv.osv):
return res
def product_detail(self, cr, uid, id, field, context={}):
+ """ Finds detail of product like price type, currency and then calculates its price.
+ @param field: Field name
+ @return: Calculated price
+ """
res = {}
res[id] = {}
final_value = 0.0
@@ -117,21 +126,25 @@ class stock_location(osv.osv):
if result:
# Choose the right filed standard_price to read
# Take the user company
- price_type_id=self.pool.get('res.users').browse(cr,uid,uid).company_id.property_valuation_price_type.id
- pricetype=self.pool.get('product.price.type').browse(cr,uid,price_type_id)
+ price_type_id = self.pool.get('res.users').browse(cr,uid,uid).company_id.property_valuation_price_type.id
+ pricetype = self.pool.get('product.price.type').browse(cr, uid, price_type_id)
for r in result:
c = (context or {}).copy()
c['location'] = id
product = self.pool.get('product.product').read(cr, uid, r['product_id'], [field_to_read], context=c)
# Compute the amount_unit in right currency
- context['currency_id']=self.pool.get('res.users').browse(cr,uid,uid).company_id.currency_id.id
- amount_unit=self.pool.get('product.product').browse(cr,uid,r['product_id']).price_get(pricetype.field, context)[r['product_id']]
+ context['currency_id'] = self.pool.get('res.users').browse(cr,uid,uid).company_id.currency_id.id
+ amount_unit = self.pool.get('product.product').browse(cr,uid,r['product_id']).price_get(pricetype.field, context)[r['product_id']]
final_value += (product[field_to_read] * amount_unit)
return final_value
def _product_value(self, cr, uid, ids, field_names, arg, context={}):
+ """ Calculates real and virtual stock value of a product.
+ @param field_names: Name of field
+ @return: Dictionary of values
+ """
result = {}
for id in ids:
result[id] = {}.fromkeys(field_names, 0.0)
@@ -144,7 +157,7 @@ class stock_location(osv.osv):
_columns = {
'name': fields.char('Location Name', size=64, required=True, translate=True),
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the stock location without removing it."),
- 'usage': fields.selection([('supplier', 'Supplier Location'), ('view', 'View'), ('internal', 'Internal Location'), ('customer', 'Customer Location'), ('inventory', 'Inventory'), ('procurement', 'Procurement'), ('production', 'Production')], 'Location Type', required=True),
+ 'usage': fields.selection([('supplier', 'Supplier Location'), ('view', 'View'), ('internal', 'Internal Location'), ('customer', 'Customer Location'), ('inventory', 'Inventory'), ('procurement', 'Procurement'), ('production', 'Production'), ('transit', 'Transit Location for Inter-Companies Transfers')], 'Location Type', required=True),
'allocation_method': fields.selection([('fifo', 'FIFO'), ('lifo', 'LIFO'), ('nearest', 'Nearest')], 'Allocation Method', required=True),
'complete_name': fields.function(_complete_name, method=True, type='char', size=100, string="Location Name"),
@@ -152,7 +165,7 @@ class stock_location(osv.osv):
'stock_real': fields.function(_product_qty_available, method=True, type='float', string='Real Stock', multi="stock"),
'stock_virtual': fields.function(_product_qty_available, method=True, type='float', string='Virtual Stock', multi="stock"),
- 'account_id': fields.many2one('account.account', string='Inventory Account', domain=[('type', '!=', 'view')]),
+ #'account_id': fields.many2one('account.account', string='Inventory Account', domain=[('type', '!=', 'view')]),
'location_id': fields.many2one('stock.location', 'Parent Location', select=True, ondelete='cascade'),
'child_ids': fields.one2many('stock.location', 'location_id', 'Contains'),
@@ -181,7 +194,7 @@ class stock_location(osv.osv):
'parent_right': fields.integer('Right Parent', select=1),
'stock_real_value': fields.function(_product_value, method=True, type='float', string='Real Stock Value', multi="stock"),
'stock_virtual_value': fields.function(_product_value, method=True, type='float', string='Virtual Stock Value', multi="stock"),
- 'company_id': fields.many2one('res.company', 'Company', required=True,select=1),
+ 'company_id': fields.many2one('res.company', 'Company', select=1, help='Let this field empty if this location is shared for every companies'),
'scrap_location': fields.boolean('Scrap Location', help='Check this box if the current location is a place for destroyed items'),
}
_defaults = {
@@ -199,6 +212,12 @@ class stock_location(osv.osv):
}
def chained_location_get(self, cr, uid, location, partner=None, product=None, context={}):
+ """ Finds chained location
+ @param location: Location id
+ @param partner: Partner id
+ @param product: Product id
+ @return: List of values
+ """
result = None
if location.chained_location_type == 'customer':
if partner:
@@ -210,6 +229,11 @@ class stock_location(osv.osv):
return result
def picking_type_get(self, cr, uid, from_location, to_location, context={}):
+ """ Gets type of picking.
+ @param from_location: Source location
+ @param to_location: Destination location
+ @return: Location type
+ """
result = 'internal'
if (from_location.usage=='internal') and (to_location and to_location.usage in ('customer', 'supplier')):
result = 'delivery'
@@ -224,13 +248,18 @@ class stock_location(osv.osv):
def _product_get_report(self, cr, uid, ids, product_ids=False,
context=None, recursive=False):
+ """ Finds the product quantity and price for particular location.
+ @param product_ids: Ids of product
+ @param recursive: True or False
+ @return: Dictionary of values
+ """
if context is None:
context = {}
product_obj = self.pool.get('product.product')
# Take the user company and pricetype
- price_type_id=self.pool.get('res.users').browse(cr,uid,uid).company_id.property_valuation_price_type.id
- pricetype=self.pool.get('product.price.type').browse(cr,uid,price_type_id)
- context['currency_id']=self.pool.get('res.users').browse(cr,uid,uid).company_id.currency_id.id
+ price_type_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.property_valuation_price_type.id
+ pricetype = self.pool.get('product.price.type').browse(cr, uid, price_type_id)
+ context['currency_id'] = self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id.id
if not product_ids:
product_ids = product_obj.search(cr, uid, [])
@@ -265,7 +294,7 @@ class stock_location(osv.osv):
# Compute based on pricetype
# Choose the right filed standard_price to read
- amount_unit=product.price_get(pricetype.field, context)[product.id]
+ amount_unit = product.price_get(pricetype.field, context)[product.id]
price = qty[product_id] * amount_unit
# price = qty[product_id] * product.standard_price
@@ -283,7 +312,14 @@ class stock_location(osv.osv):
result['total_price'] = total_price
return result
- def _product_get_multi_location(self, cr, uid, ids, product_ids=False, context={}, states=['done'], what=('in', 'out')):
+ def _product_get_multi_location(self, cr, uid, ids, product_ids=False, context={},
+ states=['done'], what=('in', 'out')):
+ """
+ @param product_ids: Ids of product
+ @param states: List of states
+ @param what: Tuple of
+ @return:
+ """
product_obj = self.pool.get('product.product')
context.update({
'states': states,
@@ -293,6 +329,11 @@ class stock_location(osv.osv):
return product_obj.get_product_available(cr, uid, product_ids, context=context)
def _product_get(self, cr, uid, id, product_ids=False, context={}, states=['done']):
+ """
+ @param product_ids:
+ @param states:
+ @return:
+ """
ids = id and [id] or []
return self._product_get_multi_location(cr, uid, ids, product_ids, context, states)
@@ -313,6 +354,11 @@ class stock_location(osv.osv):
# [ (tracking_id, product_qty, location_id) ]
#
def _product_reserve(self, cr, uid, ids, product_id, product_qty, context={}):
+ """
+ @param product_id: Id of product
+ @param product_qty: Quantity of product
+ @return: List of Values or False
+ """
result = []
amount = 0.0
for id in self.search(cr, uid, [('location_id', 'child_of', ids)]):
@@ -352,6 +398,10 @@ class stock_tracking(osv.osv):
_description = "Stock Tracking Lots"
def get_create_tracking_lot(self, cr, uid, ids, tracking_lot):
+ """
+ @param tracking_lot: Name of tracking lot
+ @return:
+ """
tracking_lot_list = self.search(cr, uid, [('name', '=', tracking_lot)],
limit=1)
if tracking_lot_list:
@@ -382,6 +432,7 @@ class stock_tracking(osv.osv):
'move_ids': fields.one2many('stock.move', 'tracking_id', 'Moves Tracked'),
'date': fields.datetime('Created Date', required=True),
}
+
_defaults = {
'active': lambda *a: 1,
'name': make_sscc,
@@ -417,6 +468,12 @@ class stock_picking(osv.osv):
_description = "Picking List"
def _set_maximum_date(self, cr, uid, ids, name, value, arg, context):
+ """ Calculates planned date if it is greater than 'value'.
+ @param name: Name of field
+ @param value: Value of field
+ @param arg: User defined argument
+ @return: True or False
+ """
if not value:
return False
if isinstance(ids, (int, long)):
@@ -433,6 +490,12 @@ class stock_picking(osv.osv):
return True
def _set_minimum_date(self, cr, uid, ids, name, value, arg, context):
+ """ Calculates planned date if it is less than 'value'.
+ @param name: Name of field
+ @param value: Value of field
+ @param arg: User defined argument
+ @return: True or False
+ """
if not value:
return False
if isinstance(ids, (int, long)):
@@ -448,6 +511,9 @@ class stock_picking(osv.osv):
return True
def get_min_max_date(self, cr, uid, ids, field_name, arg, context={}):
+ """ Finds minimum and maximum dates for picking.
+ @return: Dictionary of values
+ """
res = {}
for id in ids:
res[id] = {'min_date': False, 'max_date': False}
@@ -470,17 +536,19 @@ class stock_picking(osv.osv):
def create(self, cr, user, vals, context=None):
if ('name' not in vals) or (vals.get('name')=='/'):
- vals['name'] = self.pool.get('ir.sequence').get(cr, user, 'stock.picking')
+ seq_obj_name = 'stock.picking.' + vals['type']
+ vals['name'] = self.pool.get('ir.sequence').get(cr, user, seq_obj_name)
type_list = {
'out':_('Packing List'),
'in':_('Reception'),
'internal': _('Internal picking'),
'delivery': _('Delivery order')
}
+ new_id = super(stock_picking, self).create(cr, user, vals, context)
if not vals.get('auto_picking', False):
message = type_list.get(vals.get('type', False), _('Picking')) + " '" + (vals['name'] or "n/a") + "' "+ _("created.")
- self.log(cr, user, id, message)
- return super(stock_picking, self).create(cr, user, vals, context)
+ self.log(cr, user, new_id, message)
+ return new_id
_columns = {
'name': fields.char('Reference', size=64, select=True),
@@ -514,7 +582,6 @@ class stock_picking(osv.osv):
'max_date': fields.function(get_min_max_date, fnct_inv=_set_maximum_date, multi="min_max_date",
method=True, store=True, type='datetime', string='Max. Expected Date', select=2),
'move_lines': fields.one2many('stock.move', 'picking_id', 'Internal Moves', states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}),
- 'delivery_line':fields.one2many('stock.delivery', 'picking_id', 'Delivery lines', readonly=True),
'auto_picking': fields.boolean('Auto-Picking'),
'address_id': fields.many2one('res.partner.address', 'Partner', help="Address of partner"),
'invoice_state': fields.selection([
@@ -539,8 +606,11 @@ class stock_picking(osv.osv):
if default is None:
default = {}
default = default.copy()
- if not default.get('name',False):
- default['name'] = self.pool.get('ir.sequence').get(cr, uid, 'stock.picking')
+ picking_obj = self.browse(cr, uid, [id], context)[0]
+ if ('name' not in default) or (picking_obj.name=='/'):
+ seq_obj_name = 'stock.picking.' + picking_obj.type
+ default['name'] = self.pool.get('ir.sequence').get(cr, uid, seq_obj_name)
+
return super(stock_picking, self).copy(cr, uid, id, default, context)
def onchange_partner_in(self, cr, uid, context, partner_id=None):
@@ -550,6 +620,9 @@ class stock_picking(osv.osv):
return moves
def action_confirm(self, cr, uid, ids, context={}):
+ """ Confirms picking.
+ @return: True
+ """
self.write(cr, uid, ids, {'state': 'confirmed'})
todo = []
for picking in self.browse(cr, uid, ids, context=context):
@@ -573,6 +646,9 @@ class stock_picking(osv.osv):
# return True
def action_assign(self, cr, uid, ids, *args):
+ """ Changes state of picking to available if all moves are confirmed.
+ @return: True
+ """
for pick in self.browse(cr, uid, ids):
move_ids = [x.id for x in pick.move_lines if x.state == 'confirmed']
if not move_ids:
@@ -581,6 +657,9 @@ class stock_picking(osv.osv):
return True
def force_assign(self, cr, uid, ids, *args):
+ """ Changes state of picking to available if moves are confirmed or waiting.
+ @return: True
+ """
wf_service = netsvc.LocalService("workflow")
for pick in self.browse(cr, uid, ids):
move_ids = [x.id for x in pick.move_lines if x.state in ['confirmed','waiting']]
@@ -590,6 +669,9 @@ class stock_picking(osv.osv):
return True
def draft_force_assign(self, cr, uid, ids, *args):
+ """ Confirms picking directly from draft state.
+ @return: True
+ """
wf_service = netsvc.LocalService("workflow")
for pick in self.browse(cr, uid, ids):
wf_service.trg_validate(uid, 'stock.picking', pick.id,
@@ -600,6 +682,9 @@ class stock_picking(osv.osv):
return True
def draft_validate(self, cr, uid, ids, *args):
+ """ Validates picking directly from draft state.
+ @return: True
+ """
wf_service = netsvc.LocalService("workflow")
self.draft_force_assign(cr, uid, ids)
for pick in self.browse(cr, uid, ids):
@@ -612,6 +697,9 @@ class stock_picking(osv.osv):
return True
def cancel_assign(self, cr, uid, ids, *args):
+ """ Cancels picking and moves.
+ @return: True
+ """
wf_service = netsvc.LocalService("workflow")
for pick in self.browse(cr, uid, ids):
move_ids = [x.id for x in pick.move_lines]
@@ -620,6 +708,9 @@ class stock_picking(osv.osv):
return True
def action_assign_wkf(self, cr, uid, ids, context=None):
+ """ Changes picking state to assigned.
+ @return: True
+ """
for pick in self.browse(cr, uid, ids, context=context):
type_list = {
'out':'Packing List',
@@ -633,6 +724,9 @@ class stock_picking(osv.osv):
return True
def test_finnished(self, cr, uid, ids):
+ """ Tests whether the move is in done or cancel state or not.
+ @return: True or False
+ """
move_ids = self.pool.get('stock.move').search(cr, uid, [('picking_id', 'in', ids)])
for move in self.pool.get('stock.move').browse(cr, uid, move_ids):
if move.state not in ('done', 'cancel'):
@@ -643,18 +737,24 @@ class stock_picking(osv.osv):
return True
def test_assigned(self, cr, uid, ids):
+ """ Tests whether the move is in assigned state or not.
+ @return: True or False
+ """
ok = True
for pick in self.browse(cr, uid, ids):
mt = pick.move_type
for move in pick.move_lines:
- if (move.state in ('confirmed', 'draft')) and (mt=='one'):
+ if (move.state in ('confirmed', 'draft')) and (mt == 'one'):
return False
- if (mt=='direct') and (move.state=='assigned') and (move.product_qty):
+ if (mt == 'direct') and (move.state == 'assigned') and (move.product_qty):
return True
ok = ok and (move.state in ('cancel', 'done', 'assigned'))
return ok
def action_cancel(self, cr, uid, ids, context={}):
+ """ Changes picking state to cancel.
+ @return: True
+ """
for pick in self.browse(cr, uid, ids):
ids2 = [move.id for move in pick.move_lines]
self.pool.get('stock.move').action_cancel(cr, uid, ids2, context)
@@ -665,10 +765,16 @@ class stock_picking(osv.osv):
# TODO: change and create a move if not parents
#
def action_done(self, cr, uid, ids, context=None):
+ """ Changes picking state to done.
+ @return: True
+ """
self.write(cr, uid, ids, {'state': 'done', 'date_done': time.strftime('%Y-%m-%d %H:%M:%S')})
return True
def action_move(self, cr, uid, ids, context={}):
+ """ Changes move state to assigned.
+ @return: True
+ """
for pick in self.browse(cr, uid, ids):
todo = []
for move in pick.move_lines:
@@ -684,13 +790,17 @@ class stock_picking(osv.osv):
return False
def _get_payment_term(self, cr, uid, picking):
- '''Return {'contact': address, 'invoice': address} for invoice'''
+ """ Gets payment term from partner.
+ @return: Payment term
+ """
partner_obj = self.pool.get('res.partner')
partner = picking.address_id.partner_id
return partner.property_payment_term and partner.property_payment_term.id or False
def _get_address_invoice(self, cr, uid, picking):
- '''Return {'contact': address, 'invoice': address} for invoice'''
+ """ Gets invoice address of a partner
+ @return {'contact': address, 'invoice': address} for invoice
+ """
partner_obj = self.pool.get('res.partner')
partner = picking.address_id.partner_id
@@ -698,11 +808,17 @@ class stock_picking(osv.osv):
['contact', 'invoice'])
def _get_comment_invoice(self, cr, uid, picking):
- '''Return comment string for invoice'''
+ """
+ @return: comment string for invoice
+ """
return picking.note or ''
def _get_price_unit_invoice(self, cr, uid, move_line, type, context=None):
- '''Return the price unit for the move line'''
+ """ Gets price unit for invoice
+ @param move_line: Stock move lines
+ @param type: Type of invoice
+ @return: The price unit for the move line
+ """
if context is None:
context = {}
@@ -722,7 +838,11 @@ class stock_picking(osv.osv):
return 0.0
def _get_taxes_invoice(self, cr, uid, move_line, type):
- '''Return taxes ids for the move line'''
+ """ Gets taxes on invoice
+ @param move_line: Stock move lines
+ @param type: Type of invoice
+ @return: Taxes Ids for the move line
+ """
if type in ('in_invoice', 'in_refund'):
taxes = move_line.product_id.supplier_taxes_id
else:
@@ -751,7 +871,12 @@ class stock_picking(osv.osv):
def action_invoice_create(self, cr, uid, ids, journal_id=False,
group=False, type='out_invoice', context=None):
- '''Return ids of created invoices for the pickings'''
+ """ Creates invoice based on the invoice state selected for picking.
+ @param journal_id: Id of journal
+ @param group: Whether to create a group invoice or not
+ @param type: Type invoice to be created
+ @return: Ids of created invoices for the pickings
+ """
if context is None:
context = {}
@@ -850,9 +975,9 @@ class stock_picking(osv.osv):
account_id = self.pool.get('account.fiscal.position').map_account(cr, uid, partner.property_account_position, account_id)
notes = False
- if move_line.sale_line_id:
+ if ('sale_line_id' in move_line._columns.keys()) and move_line.sale_line_id:
notes = move_line.sale_line_id.notes
- elif move_line.purchase_line_id:
+ elif ('purchase_line_id' in move_line._columns.keys()) and move_line.purchase_line_id:
notes = move_line.purchase_line_id.notes
invoice_line_id = invoice_line_obj.create(cr, uid, {
@@ -883,6 +1008,9 @@ class stock_picking(osv.osv):
return res
def test_cancel(self, cr, uid, ids, context={}):
+ """ Test whether the move lines are canceled or not.
+ @return: True or False
+ """
for pick in self.browse(cr, uid, ids, context=context):
if not pick.move_lines:
return False
@@ -912,13 +1040,15 @@ class stock_picking(osv.osv):
return super(stock_picking, self).unlink(cr, uid, ids, context=context)
def do_partial(self, cr, uid, ids, partial_datas, context={}):
- """
- @ partial_datas : dict. contain details of partial picking
- like partner_id, address_id, delivery_date, delivery moves with product_id, product_qty, uom
+ """ Makes partial picking and moves done.
+ @param partial_datas : Dictionary containing details of partial picking
+ like partner_id, address_id, delivery_date,
+ delivery moves with product_id, product_qty, uom
+ @return: Dictionary of values
"""
res = {}
+
move_obj = self.pool.get('stock.move')
- delivery_obj = self.pool.get('stock.delivery')
product_obj = self.pool.get('product.product')
currency_obj = self.pool.get('res.currency')
users_obj = self.pool.get('res.users')
@@ -1044,14 +1174,6 @@ class stock_picking(osv.osv):
delivered_pack_id = pick.id
delivered_pack = self.browse(cr, uid, delivered_pack_id, context=context)
- delivery_id = delivery_obj.create(cr, uid, {
- 'name': delivered_pack.name or move.name,
- 'partner_id': partner_id,
- 'address_id': address_id,
- 'date': delivery_date,
- 'picking_id' : pick.id,
- 'move_delivered' : [(6,0, map(lambda x:x.id, delivered_pack.move_lines))]
- }, context=context)
res[pick.id] = {'delivered_picking': delivered_pack.id or False}
return res
@@ -1078,6 +1200,9 @@ class stock_production_lot(osv.osv):
_description = 'Production lot'
def _get_stock(self, cr, uid, ids, field_name, arg, context={}):
+ """ Gets stock of products for locations
+ @return: Dictionary of values
+ """
if 'location_id' not in context:
locations = self.pool.get('stock.location').search(cr, uid, [('usage', '=', 'internal')], context=context)
else:
@@ -1099,6 +1224,9 @@ class stock_production_lot(osv.osv):
return res
def _stock_search(self, cr, uid, obj, name, args, context):
+ """ Searches Ids of products
+ @return: Ids of locations
+ """
locations = self.pool.get('stock.location').search(cr, uid, [('usage', '=', 'internal')])
cr.execute('''select
prodlot_id,
@@ -1122,6 +1250,7 @@ class stock_production_lot(osv.osv):
'revisions': fields.one2many('stock.production.lot.revision', 'lot_id', 'Revisions'),
'company_id': fields.many2one('res.company','Company',select=1),
}
+
_defaults = {
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'name': lambda x, y, z, c: x.pool.get('ir.sequence').get(y, z, 'stock.lot.serial'),
@@ -1136,6 +1265,7 @@ stock_production_lot()
class stock_production_lot_revision(osv.osv):
_name = 'stock.production.lot.revision'
_description = 'Production lot revisions'
+
_columns = {
'name': fields.char('Revision Name', size=64, required=True),
'description': fields.text('Description'),
@@ -1153,22 +1283,6 @@ class stock_production_lot_revision(osv.osv):
stock_production_lot_revision()
-class stock_delivery(osv.osv):
-
- """ Tracability of partialdeliveries """
-
- _name = "stock.delivery"
- _description = "Delivery"
- _columns = {
- 'name': fields.char('Name', size=60, required=True),
- 'date': fields.datetime('Date', required=True),
- 'partner_id': fields.many2one('res.partner', 'Partner', required=True),
- 'address_id': fields.many2one('res.partner.address', 'Address', required=True),
- 'move_delivered':fields.one2many('stock.move', 'delivered_id', 'Move Delivered'),
- 'picking_id': fields.many2one('stock.picking', 'Picking list'),
-
- }
-stock_delivery()
# ----------------------------------------------------
# Move
# ----------------------------------------------------
@@ -1184,6 +1298,7 @@ class stock_move(osv.osv):
return (res and res[0]) or False
_name = "stock.move"
_description = "Stock Move"
+ _order = 'date_planned desc'
_log_create = False
def name_get(self, cr, uid, ids, context={}):
@@ -1193,6 +1308,9 @@ class stock_move(osv.osv):
return res
def _check_tracking(self, cr, uid, ids):
+ """ Checks if production lot is assigned to stock move or not.
+ @return: True or False
+ """
for move in self.browse(cr, uid, ids):
if not move.prodlot_id and \
(move.state == 'done' and \
@@ -1206,6 +1324,9 @@ class stock_move(osv.osv):
return True
def _check_product_lot(self, cr, uid, ids):
+ """ Checks whether move is done or not and production lot is assigned to that move.
+ @return: True or False
+ """
for move in self.browse(cr, uid, ids):
if move.prodlot_id and move.state == 'done' and (move.prodlot_id.product_id.id != move.product_id.id):
return False
@@ -1216,7 +1337,7 @@ class stock_move(osv.osv):
'priority': fields.selection([('0', 'Not urgent'), ('1', 'Urgent')], 'Priority'),
'date': fields.datetime('Created Date'),
- 'date_planned': fields.datetime('Date Planned', required=True, help="Scheduled date for the movement of the products or real date if the move is done."),
+ 'date_planned': fields.datetime('Date', required=True, help="Scheduled date for the movement of the products or real date if the move is done."),
'date_expected': fields.datetime('Date Expected', readonly=True,required=True, help="Scheduled date for the movement of the products"),
'product_id': fields.many2one('product.product', 'Product', required=True, select=True),
@@ -1250,10 +1371,8 @@ class stock_move(osv.osv):
digits_compute= dp.get_precision('Account')),
'company_id': fields.many2one('res.company', 'Company', required=True,select=1),
'partner_id': fields.related('picking_id','address_id','partner_id',type='many2one', relation="res.partner", string="Partner"),
- 'backorder_id': fields.related('picking_id','backorder_id',type='many2one', relation="stock.picking", string="Back Orders"),
+ 'backorder_id': fields.related('picking_id','backorder_id',type='many2one', relation="stock.picking", string="Back Order"),
'origin': fields.related('picking_id','origin',type='char', size=64, relation="stock.picking", string="Origin"),
- 'move_stock_return_history': fields.many2many('stock.move', 'stock_move_return_history', 'move_id', 'return_move_id', 'Move Return History',readonly=True),
- 'delivered_id': fields.many2one('stock.delivery', 'Product delivered'),
'scraped': fields.related('location_dest_id','scrap_location',type='boolean',relation='stock.location',string='Scraped'),
}
_constraints = [
@@ -1265,6 +1384,9 @@ class stock_move(osv.osv):
['prodlot_id'])]
def _default_location_destination(self, cr, uid, context={}):
+ """ Gets default address of partner for destination location
+ @return: Address id or False
+ """
if context.get('move_line', []):
if context['move_line'][0]:
if isinstance(context['move_line'][0], (tuple, list)):
@@ -1277,6 +1399,9 @@ class stock_move(osv.osv):
return False
def _default_location_source(self, cr, uid, context={}):
+ """ Gets default address of partner for source location
+ @return: Address id or False
+ """
if context.get('move_line', []):
try:
return context['move_line'][0][2]['location_id']
@@ -1303,12 +1428,9 @@ class stock_move(osv.osv):
if default is None:
default = {}
default = default.copy()
- default['move_stock_return_history'] = []
return super(stock_move, self).copy(cr, uid, id, default, context)
def create(self, cr, user, vals, context=None):
- if vals.get('move_stock_return_history',False):
- vals['move_stock_return_history'] = []
# Check that the stock.move is in draft state at creation to force
# passing through button_confirm
if vals.get('state','draft') not in ('draft','done','waiting'):
@@ -1327,7 +1449,15 @@ class stock_move(osv.osv):
cursor.commit()
return res
- def onchange_lot_id(self, cr, uid, ids, prodlot_id=False, product_qty=False, loc_id=False, product_id=False, context=None):
+ def onchange_lot_id(self, cr, uid, ids, prodlot_id=False, product_qty=False,
+ loc_id=False, product_id=False, context=None):
+ """ On change of production lot gives a warning message.
+ @param prodlot_id: Changed production lot id
+ @param product_qty: Quantity of product
+ @param loc_id: Location id
+ @param product_id: Product id
+ @return: Warning message
+ """
if not prodlot_id or not loc_id:
return {}
ctx = context and context.copy() or {}
@@ -1342,7 +1472,15 @@ class stock_move(osv.osv):
}
return {'warning': warning}
- def onchange_quantity(self, cr, uid, ids, product_id, product_qty, product_uom, product_uos):
+ def onchange_quantity(self, cr, uid, ids, product_id, product_qty,
+ product_uom, product_uos):
+ """ On change of product quantity finds UoM and UoS quantities
+ @param product_id: Product id
+ @param product_qty: Changed Quantity of product
+ @param product_uom: Unit of measure of product
+ @param product_uos: Unit of sale of product
+ @return: Dictionary of values
+ """
result = {
'product_uos_qty': 0.00
}
@@ -1360,7 +1498,15 @@ class stock_move(osv.osv):
return {'value': result}
- def onchange_product_id(self, cr, uid, ids, prod_id=False, loc_id=False, loc_dest_id=False, address_id=False):
+ def onchange_product_id(self, cr, uid, ids, prod_id=False, loc_id=False,
+ loc_dest_id=False, address_id=False):
+ """ On change of product id, if finds UoM, UoS, quantity and UoS quantity.
+ @param prod_id: Changed Product id
+ @param loc_id: Source location id
+ @param loc_id: Destination location id
+ @param address_id: Address id of partner
+ @return: Dictionary of values
+ """
if not prod_id:
return {}
lang = False
@@ -1387,6 +1533,10 @@ class stock_move(osv.osv):
return {'value': result}
def _chain_compute(self, cr, uid, moves, context={}):
+ """ Finds whether the location has chained location type or not.
+ @param moves: Stock moves
+ @return: Dictionary containing destination location with chained location type.
+ """
result = {}
for m in moves:
dest = self.pool.get('stock.location').chained_location_get(
@@ -1409,6 +1559,9 @@ class stock_move(osv.osv):
return result
def action_confirm(self, cr, uid, ids, context={}):
+ """ Confirms stock move.
+ @return: List of ids.
+ """
# ids = map(lambda m: m.id, moves)
moves = self.browse(cr, uid, ids)
self.write(cr, uid, ids, {'state': 'confirmed'})
@@ -1456,6 +1609,9 @@ class stock_move(osv.osv):
return []
def action_assign(self, cr, uid, ids, *args):
+ """ Changes state to confirmed or waiting.
+ @return: List of values
+ """
todo = []
for move in self.browse(cr, uid, ids):
if move.state in ('confirmed', 'waiting'):
@@ -1464,10 +1620,16 @@ class stock_move(osv.osv):
return res
def force_assign(self, cr, uid, ids, context={}):
+ """ Changes the state to assigned.
+ @return: True
+ """
self.write(cr, uid, ids, {'state': 'assigned'})
return True
def cancel_assign(self, cr, uid, ids, context={}):
+ """ Changes the state to confirmed.
+ @return: True
+ """
self.write(cr, uid, ids, {'state': 'confirmed'})
return True
@@ -1475,6 +1637,9 @@ class stock_move(osv.osv):
# Duplicate stock.move
#
def check_assign(self, cr, uid, ids, context={}):
+ """ Checks the product type and accordingly writes the state.
+ @return: No. of moves done
+ """
done = []
count = 0
pickings = {}
@@ -1516,6 +1681,9 @@ class stock_move(osv.osv):
# Cancel move => cancel others move and pickings
#
def action_cancel(self, cr, uid, ids, context={}):
+ """ Cancels the moves and if all moves are cancelled it cancels the picking.
+ @return: True
+ """
if not len(ids):
return True
pickings = {}
@@ -1540,11 +1708,57 @@ class stock_move(osv.osv):
#self.action_cancel(cr,uid, ids2, context)
return True
+ def _get_accounting_values(self, cr, uid, move, context=None):
+ product_obj=self.pool.get('product.product')
+ product_uom_obj = self.pool.get('product.uom')
+ price_type_obj = self.pool.get('product.price.type')
+ accounts = product_obj.get_product_accounts(cr,uid,move.product_id.id,context)
+ acc_src = accounts['stock_account_input']
+ acc_dest = accounts['stock_account_output']
+ acc_variation = accounts['property_stock_variation']
+ journal_id = accounts['stock_journal']
+
+ if not acc_src:
+ raise osv.except_osv(_('Error!'), _('There is no stock input account defined ' \
+ 'for this product: "%s" (id: %d)') % \
+ (move.product_id.name, move.product_id.id,))
+ if not acc_dest:
+ raise osv.except_osv(_('Error!'), _('There is no stock output account defined ' \
+ 'for this product: "%s" (id: %d)') % \
+ (move.product_id.name, move.product_id.id,))
+ if not journal_id:
+ raise osv.except_osv(_('Error!'), _('There is no journal defined '\
+ 'on the product category: "%s" (id: %d)') % \
+ (move.product_id.categ_id.name, move.product_id.categ_id.id,))
+ if not acc_variation:
+ raise osv.except_osv(_('Error!'), _('There is no variation account defined '\
+ 'on the product category: "%s" (id: %d)') % \
+ (move.product_id.categ_id.name, move.product_id.categ_id.id,))
+ if acc_src != acc_dest:
+ default_uom = move.product_id.uom_id.id
+ q = product_uom_obj._compute_qty(cr, uid, move.product_uom.id, move.product_qty, default_uom)
+ if move.product_id.cost_method == 'average' and move.price_unit:
+ amount = q * move.price_unit
+ # Base computation on valuation price type
+ else:
+ company_id = move.company_id.id
+ context['currency_id'] = move.company_id.currency_id.id
+ pricetype = price_type_obj.browse(cr,uid,move.company_id.property_valuation_price_type.id)
+ amount_unit = move.product_id.price_get(pricetype.field, context)[move.product_id.id]
+ amount = amount_unit * q or 1.0
+ # amount = q * move.product_id.standard_price
+ return journal_id, acc_src, acc_dest, acc_variation, amount
+
+
def action_done(self, cr, uid, ids, context={}):
+ """ Makes the move done and if all moves are done, it will finish the picking.
+ @return:
+ """
track_flag = False
picking_ids = []
product_uom_obj = self.pool.get('product.uom')
price_type_obj = self.pool.get('product.price.type')
+ product_obj=self.pool.get('product.product')
move_obj = self.pool.get('account.move')
for move in self.browse(cr, uid, ids):
if move.picking_id: picking_ids.append(move.picking_id.id)
@@ -1566,90 +1780,37 @@ class stock_move(osv.osv):
#
acc_src = None
acc_dest = None
- if move.location_id.account_id:
- acc_src = move.location_id.account_id.id
- if move.location_dest_id.account_id:
- acc_dest = move.location_dest_id.account_id.id
- if acc_src or acc_dest:
- test = [('product.product', move.product_id.id)]
- if move.product_id.categ_id:
- test.append( ('product.category', move.product_id.categ_id.id) )
- if not acc_src:
- acc_src = move.product_id.product_tmpl_id.\
- property_stock_account_input.id
- if not acc_src:
- acc_src = move.product_id.categ_id.\
- property_stock_account_input_categ.id
- if not acc_src:
- raise osv.except_osv(_('Error!'),
- _('There is no stock input account defined ' \
- 'for this product: "%s" (id: %d)') % \
- (move.product_id.name,
- move.product_id.id,))
- if not acc_dest:
- acc_dest = move.product_id.product_tmpl_id.\
- property_stock_account_output.id
- if not acc_dest:
- acc_dest = move.product_id.categ_id.\
- property_stock_account_output_categ.id
- if not acc_dest:
- raise osv.except_osv(_('Error!'),
- _('There is no stock output account defined ' \
- 'for this product: "%s" (id: %d)') % \
- (move.product_id.name,
- move.product_id.id,))
- if not move.product_id.categ_id.property_stock_journal.id:
- raise osv.except_osv(_('Error!'),
- _('There is no journal defined '\
- 'on the product category: "%s" (id: %d)') % \
- (move.product_id.categ_id.name,
- move.product_id.categ_id.id,))
- journal_id = move.product_id.categ_id.property_stock_journal.id
- if acc_src != acc_dest:
- ref = move.picking_id and move.picking_id.name or False
- default_uom = move.product_id.uom_id.id
- date = time.strftime('%Y-%m-%d')
- q = product_uom_obj._compute_qty(cr, uid, move.product_uom.id, move.product_qty, default_uom)
- if move.product_id.cost_method == 'average' and move.price_unit:
- amount = q * move.price_unit
- # Base computation on valuation price type
- else:
- company_id = move.company_id.id
- context['currency_id'] = move.company_id.currency_id.id
- pricetype = price_type_obj.browse(cr,uid,move.company_id.property_valuation_price_type.id)
- amount_unit = move.product_id.price_get(pricetype.field, context)[move.product_id.id]
- amount = amount_unit * q or 1.0
- # amount = q * move.product_id.standard_price
+ if move.product_id.valuation == 'real_time':
+ lines = []
+ if ((move.location_id.usage == 'internal' and move.location_dest_id.usage == 'customer') or (move.location_id.usage == 'internal' and move.location_dest_id.usage == 'transit')):
+ if move.location_id.company_id:
+ context.update({'force_company': move.location_id.company_id.id})
+ journal_id, acc_src, acc_dest, acc_variation, amount = self._get_accounting_values(cr, uid, move, context)
+ lines = [(journal_id, self.create_account_move(cr, uid, move, acc_dest, acc_variation, amount, context))]
- partner_id = False
- if move.picking_id:
- partner_id = move.picking_id.address_id and (move.picking_id.address_id.partner_id and move.picking_id.address_id.partner_id.id or False) or False
- lines = [
- (0, 0, {
- 'name': move.name,
- 'quantity': move.product_qty,
- 'product_id': move.product_id and move.product_id.id or False,
- 'credit': amount,
- 'account_id': acc_src,
- 'ref': ref,
- 'date': date,
- 'partner_id': partner_id}),
- (0, 0, {
- 'name': move.name,
- 'product_id': move.product_id and move.product_id.id or False,
- 'quantity': move.product_qty,
- 'debit': amount,
- 'account_id': acc_dest,
- 'ref': ref,
- 'date': date,
- 'partner_id': partner_id})
- ]
+ elif ((move.location_id.usage == 'supplier' and move.location_dest_id.usage == 'internal') or (move.location_id.usage == 'transit' and move.location_dest_id.usage == 'internal')):
+ if move.location_dest_id.company_id:
+ context.update({'force_company': move.location_dest_id.company_id.id})
+ journal_id, acc_src, acc_dest, acc_variation, amount = self._get_accounting_values(cr, uid, move, context)
+ lines = [(journal_id, self.create_account_move(cr, uid, move, acc_variation, acc_src, amount, context))]
+ elif (move.location_id.usage == 'internal' and move.location_dest_id.usage == 'internal' and move.location_id.company_id != move.location_dest_id.company_id):
+ if move.location_id.company_id:
+ context.update({'force_company': move.location_id.company_id.id})
+ journal_id, acc_src, acc_dest, acc_variation, amount = self._get_accounting_values(cr, uid, move, context)
+ line1 = [(journal_id, self.create_account_move(cr, uid, move, acc_dest, acc_variation, amount, context))]
+ if move.location_dest_id.company_id:
+ context.update({'force_company': move.location_dest_id.company_id.id})
+ journal_id, acc_src, acc_dest, acc_variation, amount = self._get_accounting_values(cr, uid, move, context)
+ line2 = [(journal_id, self.create_account_move(cr, uid, move, acc_variation, acc_src, amount, context))]
+ lines = line1 + line2
+ for j_id, line in lines:
move_obj.create(cr, uid, {
'name': move.name,
- 'journal_id': journal_id,
- 'line_id': lines,
- 'ref': ref,
- })
+ 'journal_id': j_id,
+ 'type':'cont_voucher',
+ 'line_id': line,
+ 'ref': move.picking_id and move.picking_id.name,
+ })
tracking_lot = False
if context:
tracking_lot = context.get('tracking_lot', False)
@@ -1668,7 +1829,31 @@ class stock_move(osv.osv):
for id in ids:
wf_service.trg_trigger(uid, 'stock.move', id, cr)
return True
-
+
+ def create_account_move(self, cr, uid, move,account_id,account_variation,amount, context=None):
+
+ partner_id = move.picking_id.address_id and (move.picking_id.address_id.partner_id and move.picking_id.address_id.partner_id.id or False) or False
+ lines=[(0, 0, {
+ 'name': move.name,
+ 'quantity': move.product_qty,
+ 'product_id': move.product_id and move.product_id.id or False,
+ 'credit': amount,
+ 'account_id': account_id,
+ 'ref': move.picking_id and move.picking_id.name or False,
+ 'date': time.strftime('%Y-%m-%d') ,
+ 'partner_id': partner_id,
+ }),
+ (0, 0, {
+ 'name': move.name,
+ 'product_id': move.product_id and move.product_id.id or False,
+ 'quantity': move.product_qty,
+ 'debit': amount,
+ 'account_id': account_variation,
+ 'ref': move.picking_id and move.picking_id.name or False,
+ 'date': time.strftime('%Y-%m-%d') ,
+ 'partner_id': partner_id,
+ })]
+ return lines
def unlink(self, cr, uid, ids, context=None):
if context is None:
context = {}
@@ -1680,6 +1865,9 @@ class stock_move(osv.osv):
cr, uid, ids, context=context)
def _create_lot(self, cr, uid, ids, product_id, prefix=False):
+ """ Creates production lot
+ @return: Production lot id
+ """
prodlot_obj = self.pool.get('stock.production.lot')
ir_sequence_obj = self.pool.get('ir.sequence')
sequence = ir_sequence_obj.get(cr, uid, 'stock.lot.serial')
@@ -1695,18 +1883,15 @@ class stock_move(osv.osv):
def action_scrap(self, cr, uid, ids, quantity, location_id, context=None):
- '''
- Move the scrap/damaged product into scrap location
-
- @ param cr: the database cursor
- @ param uid: the user id
- @ param ids: ids of stock move object to be scraped
- @ param quantity : specify scrap qty
- @ param location_id : specify scrap location
- @ param context: context arguments
-
- @ return: Scraped lines
- '''
+ """ Move the scrap/damaged product into scrap location
+ @param cr: the database cursor
+ @param uid: the user id
+ @param ids: ids of stock move object to be scraped
+ @param quantity : specify scrap qty
+ @param location_id : specify scrap location
+ @param context: context arguments
+ @return: Scraped lines
+ """
if quantity <= 0:
raise osv.except_osv(_('Warning!'), _('Please provide Proper Quantity !'))
res = []
@@ -1727,19 +1912,16 @@ class stock_move(osv.osv):
return res
def action_split(self, cr, uid, ids, quantity, split_by_qty=1, prefix=False, with_lot=True, context=None):
- '''
- Split Stock Move lines into production lot which specified split by quantity.
-
- @ param cr: the database cursor
- @ param uid: the user id
- @ param ids: ids of stock move object to be splited
- @ param split_by_qty : specify split by qty
- @ param prefix : specify prefix of production lot
- @ param with_lot : if true, prodcution lot will assign for split line otherwise not.
- @ param context: context arguments
-
- @ return: splited move lines
- '''
+ """ Split Stock Move lines into production lot which specified split by quantity.
+ @param cr: the database cursor
+ @param uid: the user id
+ @param ids: ids of stock move object to be splited
+ @param split_by_qty : specify split by qty
+ @param prefix : specify prefix of production lot
+ @param with_lot : if true, prodcution lot will assign for split line otherwise not.
+ @param context: context arguments
+ @return: Splited move lines
+ """
if quantity <= 0:
raise osv.except_osv(_('Warning!'), _('Please provide Proper Quantity !'))
@@ -1790,18 +1972,15 @@ class stock_move(osv.osv):
return res
def action_consume(self, cr, uid, ids, quantity, location_id=False, context=None):
- '''
- Consumed product with specific quatity from specific source location
-
- @ param cr: the database cursor
- @ param uid: the user id
- @ param ids: ids of stock move object to be consumed
- @ param quantity : specify consume quantity
- @ param location_id : specify source location
- @ param context: context arguments
-
- @ return: Consumed lines
- '''
+ """ Consumed product with specific quatity from specific source location
+ @param cr: the database cursor
+ @param uid: the user id
+ @param ids: ids of stock move object to be consumed
+ @param quantity : specify consume quantity
+ @param location_id : specify source location
+ @param context: context arguments
+ @return: Consumed lines
+ """
if context is None:
context = {}
@@ -1861,13 +2040,13 @@ class stock_move(osv.osv):
return res
def do_partial(self, cr, uid, ids, partial_datas, context={}):
- """
- @ partial_datas : dict. contain details of partial picking
- like partner_id, address_id, delivery_date, delivery moves with product_id, product_qty, uom
+ """ Makes partial pickings and moves done.
+ @param partial_datas: Dictionary containing details of partial picking
+ like partner_id, address_id, delivery_date, delivery
+ moves with product_id, product_qty, uom
"""
res = {}
picking_obj = self.pool.get('stock.picking')
- delivery_obj = self.pool.get('stock.delivery')
product_obj = self.pool.get('product.product')
currency_obj = self.pool.get('res.currency')
users_obj = self.pool.get('res.users')
@@ -1980,18 +2159,6 @@ class stock_move(osv.osv):
done_move_ids = []
for move in complete:
done_move_ids.append(move.id)
- if move.picking_id.id not in ref:
- delivery_id = delivery_obj.create(cr, uid, {
- 'partner_id': partner_id,
- 'address_id': address_id,
- 'date': delivery_date,
- 'name' : move.picking_id.name,
- 'picking_id': move.picking_id.id
- }, context=context)
- ref[move.picking_id.id] = delivery_id
- delivery_obj.write(cr, uid, ref[move.picking_id.id], {
- 'move_delivered' : [(4,move.id)]
- })
return done_move_ids
stock_move()
@@ -2017,10 +2184,17 @@ class stock_inventory(osv.osv):
def _inventory_line_hook(self, cr, uid, inventory_line, move_vals):
- '''Creates a stock move from an inventory line'''
+ """ Creates a stock move from an inventory line
+ @param inventory_line:
+ @param move_vals:
+ @return:
+ """
return self.pool.get('stock.move').create(cr, uid, move_vals)
def action_done(self, cr, uid, ids, context=None):
+ """ Finishes the inventory and writes its finished date
+ @return: True
+ """
for inv in self.browse(cr, uid, ids):
move_ids = []
move_line = []
@@ -2067,12 +2241,18 @@ class stock_inventory(osv.osv):
return True
def action_cancel(self, cr, uid, ids, context={}):
+ """ Cancels the stock move and change inventory state to draft.
+ @return: True
+ """
for inv in self.browse(cr, uid, ids):
self.pool.get('stock.move').action_cancel(cr, uid, [x.id for x in inv.move_ids], context)
self.write(cr, uid, [inv.id], {'state': 'draft'})
return True
def action_cancel_inventary(self, cr, uid, ids, context={}):
+ """ Cancels both stock move and inventory
+ @return: True
+ """
for inv in self.browse(cr,uid,ids):
self.pool.get('stock.move').action_cancel(cr, uid, [x.id for x in inv.move_ids], context)
self.write(cr, uid, [inv.id], {'state':'cancel'})
@@ -2096,6 +2276,12 @@ class stock_inventory_line(osv.osv):
}
def on_change_product_id(self, cr, uid, ids, location_id, product, uom=False):
+ """ Changes UoM and name if product_id changes.
+ @param location_id: Location id
+ @param product: Changed product_id
+ @param uom: UoM product
+ @return: Dictionary of changed values
+ """
if not product:
return {}
if not uom:
@@ -2161,6 +2347,7 @@ class stock_picking_move_wizard(osv.osv_memory):
def action_move(self, cr, uid, ids, context=None):
move_obj = self.pool.get('stock.move')
picking_obj = self.pool.get('stock.picking')
+ account_move_obj = self.pool.get('account.move')
for act in self.read(cr, uid, ids):
move_lines = move_obj.browse(cr, uid, act['move_ids'])
for line in move_lines:
diff --git a/addons/stock/stock_demo.xml b/addons/stock/stock_demo.xml
index 10a24cb7a15..bfa1845b43c 100644
--- a/addons/stock/stock_demo.xml
+++ b/addons/stock/stock_demo.xml
@@ -37,7 +37,7 @@
Shelf 2
-
+
Sub Products
@@ -288,7 +288,13 @@
-
+
+
+ property_stock_variation
+
+
+
+
diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml
index 553d398984b..120af5d78f5 100644
--- a/addons/stock/stock_view.xml
+++ b/addons/stock/stock_view.xml
@@ -3,6 +3,7 @@
+
@@ -407,7 +408,7 @@
-
+
@@ -673,9 +674,6 @@
-
-
-
@@ -715,7 +713,7 @@
-
+
@@ -758,11 +756,12 @@
@@ -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}
@@ -1735,7 +1738,7 @@
- Outcoming Shipments
+ Customers Packingsstock.pickingir.actions.act_windowform
@@ -1761,5 +1764,33 @@
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 aa7bb42cf8b..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,75 +164,71 @@ 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
@@ -262,53 +238,72 @@ class split_in_production_lot(osv.osv_memory):
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'
}
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 @@