[MERGE] merge with trunk addons
bzr revid: mra@mra-laptop-20100702040822-8ze0grzrpfzv1xoc
This commit is contained in:
+792
-627
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,7 @@
|
||||
'category': 'Profile',
|
||||
'description': """This module is to create Profile for Associates""",
|
||||
'author': 'Tiny',
|
||||
'depends': ['membership', 'board_association'],
|
||||
'depends': ['membership', 'event'],
|
||||
'update_xml': ['security/ir.model.access.csv', 'profile_association.xml'],
|
||||
'demo_xml': [],
|
||||
'installable': True,
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
from osv import fields, osv
|
||||
import pooler
|
||||
|
||||
|
||||
class profile_association_config_install_modules_wizard(osv.osv_memory):
|
||||
_name='profile.association.config.install_modules_wizard'
|
||||
_inherit = 'res.config.installer'
|
||||
@@ -30,9 +29,7 @@ class profile_association_config_install_modules_wizard(osv.osv_memory):
|
||||
_columns = {
|
||||
'hr_expense':fields.boolean('Expenses Tracking', help="Tracks the personal expenses process, from the employee expense encoding, to the reimbursement of the employee up to the reinvoicing to the final customer."),
|
||||
'project':fields.boolean('Project Management'),
|
||||
'board_document':fields.boolean('Document Management', help= "The Document Management System of Open ERP allows you to store, browse, automatically index, search and preview all kind of documents (internal documents, printed reports, calendar system). It opens an FTP access for the users to easily browse association's document."),
|
||||
'segmentation':fields.boolean('Segmentation'),
|
||||
'crm_configuration' : fields.boolean('Partner Relation & Calendars'),
|
||||
'event_project':fields.boolean('Organization and management of events', help="This module allows you to create retro planning for managing your events."),
|
||||
'project_gtd':fields.boolean('Getting Things Done',
|
||||
help="GTD is a methodology to efficiently organise yourself and your tasks. This module fully integrates GTD principle with OpenERP's project management."),
|
||||
'wiki': fields.boolean('Wiki',
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
<field name="project"/>
|
||||
<field name="project_gtd"/>
|
||||
<field name="wiki"/>
|
||||
<separator string="Event Management" colspan="4"/>
|
||||
<field name="event_project"/>
|
||||
<separator string="Resources Management" colspan="4"/>
|
||||
<field name="hr_expense"/>
|
||||
<separator string="Relationship Management" colspan="4"/>
|
||||
<field name="crm_configuration"/>
|
||||
</group>
|
||||
</data>
|
||||
</field>
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
|
||||
"access_profile_association_wizard_install","profile association wizard install","model_profile_association_config_install_modules_wizard","base.group_system",1,1,1,1
|
||||
|
||||
|
@@ -31,7 +31,7 @@
|
||||
<field name="marketing" on_change="onchange_moduleselection(crm,sale,project,knowledge,stock,mrp,account,purchase,hr,point_of_sale,marketing,misc_tools,report_designer,profile_association,profile_auction,profile_bookstore)" groups="base.group_extended"/> <field name="misc_tools" on_change="onchange_moduleselection(crm,sale,project,knowledge,stock,mrp,account,purchase,hr,point_of_sale,marketing,misc_tools,report_designer,profile_association,profile_auction,profile_bookstore)"/>
|
||||
<field name="report_designer" groups="base.group_extended" on_change="onchange_moduleselection(crm,sale,project,knowledge,stock,mrp,account,purchase,hr,point_of_sale,marketing,misc_tools,report_designer,profile_association,profile_auction,profile_bookstore)"/>
|
||||
<separator string="Install Specific Business Modules" colspan="4"/>
|
||||
<field name="profile_association" on_change="onchange_moduleselection(crm,sale,project,knowledge,stock,mrp,account,purchase,hr,point_of_sale,marketing,misc_tools,report_designer,profile_association,profile_auction,profile_bookstore)"/>
|
||||
<field name="association" on_change="onchange_moduleselection(crm,sale,project,knowledge,stock,mrp,account,purchase,hr,point_of_sale,marketing,misc_tools,report_designer,profile_association,profile_auction,profile_bookstore)"/>
|
||||
<field name="profile_auction" on_change="onchange_moduleselection(crm,sale,project,knowledge,stock,mrp,account,purchase,hr,point_of_sale,marketing,misc_tools,report_designer,profile_association,profile_auction,profile_bookstore)"/>
|
||||
<field name="profile_bookstore" on_change="onchange_moduleselection(crm,sale,project,knowledge,stock,mrp,account,purchase,hr,point_of_sale,marketing,misc_tools,report_designer,profile_association,profile_auction,profile_bookstore)"/>
|
||||
<field name="product_expiry" on_change="onchange_moduleselection(crm,sale,project,knowledge,stock,mrp,account,purchase,hr,point_of_sale,marketing,misc_tools,report_designer,profile_association,profile_auction,profile_bookstore)"/>
|
||||
|
||||
@@ -78,7 +78,7 @@ class base_setup_installer(osv.osv_memory):
|
||||
'product_expiry':fields.boolean('Food Industry',
|
||||
help="Installs a preselected set of OpenERP "
|
||||
"applications which will help you manage foods."),
|
||||
'profile_association':fields.boolean('Associations',
|
||||
'association':fields.boolean('Associations',
|
||||
help="Installs a preselected set of OpenERP "
|
||||
"applications which will help you manage your association "
|
||||
"more efficiently."),
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<!--Lead Stage Form view -->
|
||||
|
||||
<record id="crm_lead_stage_act" model="ir.actions.act_window">
|
||||
<field name="name">Lead Stages</field>
|
||||
<field name="name">Stages</field>
|
||||
<field name="res_model">crm.case.stage</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="crm.crm_case_stage_tree"/>
|
||||
@@ -19,9 +19,8 @@
|
||||
|
||||
|
||||
<!-- Resource Type Form View -->
|
||||
|
||||
<record id="crm_lead_resource_act" model="ir.actions.act_window">
|
||||
<field name="name">Lead Resource Type</field>
|
||||
<field name="name">Lead Sources</field>
|
||||
<field name="res_model">crm.case.resource.type</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="crm.crm_case_resource_type_tree"/>
|
||||
@@ -30,12 +29,11 @@
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_lead_resource_act"
|
||||
id="menu_crm_lead_resource_act" name="Resource Type"
|
||||
id="menu_crm_lead_resource_act" name="Lead Sources"
|
||||
groups="base.group_extended" sequence="2"
|
||||
parent="menu_crm_config_lead" />
|
||||
|
||||
<!-- CRM Lead Form View -->
|
||||
|
||||
<record model="ir.ui.view" id="crm_case_form_view_leads">
|
||||
<field name="name">CRM - Leads Form</field>
|
||||
<field name="model">crm.lead</field>
|
||||
@@ -226,9 +224,9 @@
|
||||
<field name="referred" invisible="1"/>
|
||||
|
||||
<field name="stage_id"/>
|
||||
<button name="stage_previous" string="Previous"
|
||||
<button name="stage_previous" string="Previous Stage"
|
||||
states="open,pending" type="object" icon="gtk-go-back" />
|
||||
<button name="stage_next" string="Next"
|
||||
<button name="stage_next" string="Next Stage"
|
||||
states="open,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<field name="section_id" invisible="context.get('invisible_section', True)" />
|
||||
@@ -292,13 +290,11 @@
|
||||
|
||||
<separator orientation="vertical"/>
|
||||
<filter icon="terp-go-today" string="Today"
|
||||
domain="[('create_date','<', time.strftime('%%Y-%%m-%%d 23:59:59')), \
|
||||
('create_date','>=', time.strftime('%%Y-%%m-%%d 23:59:59'))]"
|
||||
help="Todays' Opportunities" />
|
||||
domain="[('create_date','<', time.strftime('%%Y-%%m-%%d 23:59:59')), ('create_date','>=', time.strftime('%%Y-%%m-%%d 00:00:00'))]"
|
||||
help="Todays' Leads" />
|
||||
<filter icon="terp-go-week" string="7 Days"
|
||||
help="Opportunities during last 7 days"
|
||||
domain="[('create_date','<', time.strftime('%%Y-%%m-%%d')),\
|
||||
('create_date','>=',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]"
|
||||
help="Leads creating during last 7 days"
|
||||
domain="[('create_date','<', time.strftime('%%Y-%%m-%%d 23:59:59')),('create_date','>=',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d 00:00:00'))]"
|
||||
/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name"/>
|
||||
@@ -314,7 +310,7 @@
|
||||
<filter icon="terp-personal+"
|
||||
context="{'invisible_section': False}"
|
||||
domain="[('section_id.user_id','=',uid)]"
|
||||
help="My Sale Team"/>
|
||||
help="My Sales Team"/>
|
||||
<filter icon="terp-personal+"
|
||||
context="{'invisible_section': False}"
|
||||
domain="[]"
|
||||
|
||||
@@ -1,54 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Opportunity Categories Form View -->
|
||||
|
||||
<record id="crm_opportunity_categ_action" model="ir.actions.act_window">
|
||||
<field name="name">Opportunity Categories</field>
|
||||
<field name="res_model">crm.case.categ</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="crm.crm_case_categ_tree-view"/>
|
||||
<field name="domain">[('object_id.model', '=', 'crm.lead')]</field>
|
||||
<field name="context">{'object_id':'crm.lead'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_opportunity_categ_action"
|
||||
id="menu_crm_case_opportunity-act" name="Categories"
|
||||
parent="menu_crm_config_opportunity" sequence="1"/>
|
||||
|
||||
<!-- Opportunity Stages Form View-->
|
||||
|
||||
<record id="crm_opportunity_stage_act" model="ir.actions.act_window">
|
||||
<field name="name">Opportunity Stages</field>
|
||||
<field name="res_model">crm.case.stage</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="crm.crm_case_stage_tree"/>
|
||||
<field name="domain">[('object_id.model', '=', 'crm.lead')]</field>
|
||||
<field name="context">{'object_id':'crm.lead'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_opportunity_stage_act"
|
||||
id="menu_crm_opportunity_stage_act" name="Stages"
|
||||
parent="menu_crm_config_opportunity" sequence="2"/>
|
||||
|
||||
<!-- Opportunity Resource Type Form View -->
|
||||
|
||||
<record id="crm_opportunity_resource_act" model="ir.actions.act_window">
|
||||
<field name="name">Opportunity Resource Type</field>
|
||||
<field name="res_model">crm.case.resource.type</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="crm.crm_case_resource_type_tree"/>
|
||||
<field name="domain">[('object_id.model', '=', 'crm.lead')]</field>
|
||||
<field name="context">{'object_id':'crm.lead'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_opportunity_resource_act"
|
||||
id="menu_crm_opportunity_resource_act" name="Resource"
|
||||
parent="menu_crm_config_opportunity" sequence="3"/>
|
||||
|
||||
<!-- Opportunities Form View -->
|
||||
|
||||
<record model="ir.ui.view" id="crm_case_form_view_oppor">
|
||||
<field name="name">Opportunities</field>
|
||||
<field name="model">crm.lead</field>
|
||||
@@ -149,11 +102,13 @@
|
||||
<field name="country_id"/>
|
||||
<field name="state_id"/>
|
||||
</group>
|
||||
<group colspan="2" col="3">
|
||||
<separator string="Communication" colspan="4" col="3"/>
|
||||
<group colspan="2" col="2">
|
||||
<separator string="Communication" colspan="2"/>
|
||||
<field name="fax"/>
|
||||
<newline/>
|
||||
<field name="mobile"/>
|
||||
</group>
|
||||
<group colspan="2" col="2">
|
||||
<separator string="Mailings" colspan="2"/>
|
||||
<field name="optin"/>
|
||||
<field name="optout"/>
|
||||
</group>
|
||||
@@ -251,9 +206,9 @@
|
||||
<field name="country_id" invisible="context.get('invisible_country', True)" />
|
||||
<field name="date_action"/>
|
||||
<field name="stage_id"/>
|
||||
<button name="stage_previous" string="Previous"
|
||||
<button name="stage_previous" string="Previous Stage"
|
||||
states="open,pending" type="object" icon="gtk-go-back" />
|
||||
<button name="stage_next" string="Next"
|
||||
<button name="stage_next" string="Next Stage"
|
||||
states="open,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<field name="planned_revenue" sum="Total of Planned Revenue"/>
|
||||
@@ -315,12 +270,11 @@
|
||||
domain="[('state','=','pending')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter icon="terp-go-today" string="Today"
|
||||
domain="[('create_date','<', time.strftime('%%Y-%%m-%%d 23:59:59')), ('create_date','>=', time.strftime('%%Y-%%m-%%d 23:59:59'))]"
|
||||
domain="[('create_date','<', time.strftime('%%Y-%%m-%%d 23:59:59')), ('create_date','>=', time.strftime('%%Y-%%m-%%d 00:00:00'))]"
|
||||
help="Todays' Opportunities" />
|
||||
<filter icon="terp-go-week" string="7 Days"
|
||||
help="Opportunities during last 7 days"
|
||||
domain="[('create_date','<', time.strftime('%%Y-%%m-%%d')),\
|
||||
('create_date','>=',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]"
|
||||
help="Opportunities created during last 7 days"
|
||||
domain="[('create_date','<', time.strftime('%%Y-%%m-%%d 23:59:59')),('create_date','>=',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d 00:00:00'))]"
|
||||
/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name" string="Opportunity"/>
|
||||
@@ -337,7 +291,7 @@
|
||||
<filter icon="terp-personal+"
|
||||
domain="[('section_id.user_id','=',uid)]"
|
||||
context="{'invisible_section': False}"
|
||||
help="My Sale Team" />
|
||||
help="My Sales Team" />
|
||||
<filter icon="terp-personal+"
|
||||
context="{'invisible_section': False}"
|
||||
domain="[]"
|
||||
|
||||
+15
-15
@@ -5,12 +5,9 @@
|
||||
<menuitem id="base.menu_crm_config_sales" name="Sales"
|
||||
parent="base.menu_base_config" sequence="1"/>
|
||||
|
||||
<menuitem id="menu_crm_config_lead" name="Lead"
|
||||
<menuitem id="menu_crm_config_lead" name="Leads & Opportunities"
|
||||
parent="base.menu_crm_config_sales" sequence="0" groups="base.group_extended"/>
|
||||
|
||||
<menuitem id="menu_crm_config_opportunity" name="Opportunity"
|
||||
parent="base.menu_crm_config_sales" sequence="1"/>
|
||||
|
||||
<menuitem id="menu_crm_config_meeting" name="Meeting"
|
||||
parent="base.menu_base_config" sequence="4"/>
|
||||
|
||||
@@ -77,11 +74,16 @@
|
||||
<!-- Case Sections Action -->
|
||||
|
||||
<record id="crm_case_section_act" model="ir.actions.act_window">
|
||||
<field name="name">Sales Team</field>
|
||||
<field name="name">Sales Teams</field>
|
||||
<field name="res_model">crm.case.section</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="crm_case_section_view_tree"/>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_case_section_act"
|
||||
id="menu_crm_case_section_act" sequence="4"
|
||||
parent="menu_crm_config_lead" />
|
||||
|
||||
|
||||
<!-- CRM Stage Tree View -->
|
||||
|
||||
@@ -167,12 +169,10 @@
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="crm_case_categ_tree-view"/>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_case_section_act"
|
||||
id="menu_crm_case_section_act" sequence="4"
|
||||
parent="menu_crm_config_opportunity" />
|
||||
|
||||
|
||||
|
||||
<menuitem action="crm_case_categ-act"
|
||||
id="menu_crm_case_categ-act" name="Categories"
|
||||
parent="menu_crm_config_lead" sequence="1"/>
|
||||
|
||||
<!-- Resource Type of case Tree View -->
|
||||
|
||||
@@ -339,14 +339,14 @@
|
||||
</record>
|
||||
|
||||
<record id="crm_segmentation-act" model="ir.actions.act_window">
|
||||
<field name="name">Segmentations</field>
|
||||
<field name="name">Segmentation</field>
|
||||
<field name="res_model">crm.segmentation</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="crm_segmentation-view"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_segmentation_tree-act" model="ir.actions.act_window">
|
||||
<field name="name">Segmentations</field>
|
||||
<field name="name">Segmentation</field>
|
||||
<field name="res_model">crm.segmentation</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
@@ -354,8 +354,8 @@
|
||||
|
||||
<menuitem action="crm_segmentation_tree-act"
|
||||
id="menu_crm_segmentation-act"
|
||||
groups="base.group_extended" sequence="5"
|
||||
parent="menu_crm_config_opportunity" />
|
||||
groups="base.group_extended" sequence="3"
|
||||
parent="base.menu_config_address_book" />
|
||||
|
||||
<record model="ir.ui.view" id="view_users_form_simple_modif_inherited1">
|
||||
<field name="name">view.users.form.crm.modif.inherited1</field>
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
mobile: (333) 715-1450
|
||||
section_id: crm.section_sales_department
|
||||
referred: False
|
||||
title: M.
|
||||
- |
|
||||
I check that the lead is in 'draft' state,
|
||||
-
|
||||
|
||||
@@ -178,7 +178,7 @@ class crm_send_new_email(osv.osv_memory):
|
||||
if 'email_cc' in fields:
|
||||
res.update({'email_cc': tools.ustr(case.email_cc or '')})
|
||||
if 'text' in fields:
|
||||
res.update({'text': u'\n\n'+(tools.ustr(case.user_id.signature or ''))})
|
||||
res.update({'text': u'\n'+(tools.ustr(case.user_id.signature or ''))})
|
||||
if 'state' in fields:
|
||||
res.update({'state': u'pending'})
|
||||
|
||||
@@ -211,7 +211,7 @@ class crm_send_new_email(osv.osv_memory):
|
||||
if 'email_from' in fields:
|
||||
res.update({'email_from': user_mail_from and tools.ustr(user_mail_from) or False})
|
||||
|
||||
signature = u'\n' + (tools.ustr(case.user_id.signature or ''))
|
||||
signature = u'\n' + (tools.ustr(case.user_id.signature or '')) + u'\n'
|
||||
original = [signature]
|
||||
|
||||
if include_original == True and 'text' in fields:
|
||||
@@ -221,9 +221,9 @@ class crm_send_new_email(osv.osv_memory):
|
||||
sentdate = u'Date: %s' % (tools.ustr(hist.date))
|
||||
desc = u'\n%s'%(tools.ustr(hist.description))
|
||||
|
||||
original = [header, sender, to, sentdate, desc, signature]
|
||||
original = [signature, header, sender, to, sentdate, desc]
|
||||
|
||||
res['text']= u'\n\n\n' + u'\n'.join(original)
|
||||
res['text']= u'\n' + u'\n'.join(original)
|
||||
|
||||
if 'subject' in fields:
|
||||
res.update({u'subject': u'Re: %s' %(tools.ustr(hist.name or ''))})
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
</group>
|
||||
<notebook colspan="6">
|
||||
<page string="Message">
|
||||
<field name="text" nolabel="1" colspan="4"/>
|
||||
<field name="text" nolabel="1" colspan="4" default_focus="1"/>
|
||||
</page>
|
||||
<page string="Attachments">
|
||||
<field name="attachment_ids" colspan="4" nolabel="1">
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
'security/event_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'wizard/event_make_invoice_view.xml',
|
||||
'wizard/partner_event_registration_view.xml',
|
||||
'board_association_view.xml',
|
||||
],
|
||||
'demo_xml': ['event_demo.xml', 'board_association_demo.xml'],
|
||||
|
||||
+42
-14
@@ -35,7 +35,6 @@ class event_type(osv.osv):
|
||||
_columns = {
|
||||
'name': fields.char('Event type', size=64, required=True),
|
||||
}
|
||||
|
||||
event_type()
|
||||
|
||||
class event_event(osv.osv):
|
||||
@@ -44,7 +43,14 @@ class event_event(osv.osv):
|
||||
_description = __doc__
|
||||
_inherit = 'crm.case.section'
|
||||
_order = 'date_begin'
|
||||
|
||||
|
||||
def _get_currency(self, cr, uid, context):
|
||||
user = self.pool.get('res.users').browse(cr, uid, [uid])[0]
|
||||
if user.company_id:
|
||||
return user.company_id.currency_id.id
|
||||
else:
|
||||
return self.pool.get('res.currency').search(cr, uid, [('rate','=',1.0)])[0]
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
""" Copy record of Given id
|
||||
@param id: Id of Event Registration type record.
|
||||
@@ -57,6 +63,14 @@ class event_event(osv.osv):
|
||||
'state': 'draft'
|
||||
})
|
||||
return super(event_event, self).copy(cr, uid, id, default=default, context=context)
|
||||
|
||||
def onchange_product(self, cr, uid, ids, product_id):
|
||||
|
||||
if not product_id:
|
||||
return {'value': {'unit_price': False}}
|
||||
else:
|
||||
unit_price=self.pool.get('product.product').price_get(cr, uid, [product_id])[product_id]
|
||||
return {'value': {'unit_price': unit_price}}
|
||||
|
||||
def button_draft(self, cr, uid, ids, context=None):
|
||||
return self.write(cr, uid, ids, {'state': 'draft'}, context=context)
|
||||
@@ -88,6 +102,7 @@ class event_event(osv.osv):
|
||||
@param context: A standard dictionary for contextual values
|
||||
@return: Dictionary of function fields value.
|
||||
"""
|
||||
|
||||
register_pool = self.pool.get('event.registration')
|
||||
res = {}
|
||||
for event in self.browse(cr, uid, ids, context):
|
||||
@@ -103,11 +118,11 @@ class event_event(osv.osv):
|
||||
reg_ids = register_pool.search(cr, uid, [
|
||||
('event_id', '=', event.id),
|
||||
('state', 'in', state)])
|
||||
|
||||
if 'register_current' in fields:
|
||||
res[event.id]['register_current'] = len(reg_ids)
|
||||
if 'register_prospect' in fields:
|
||||
res[event.id]['register_prospect'] = len(reg_ids)
|
||||
|
||||
|
||||
return res
|
||||
|
||||
@@ -142,6 +157,7 @@ class event_event(osv.osv):
|
||||
register_pool.write(cr, uid, reg_ids, register_values)
|
||||
return res
|
||||
|
||||
|
||||
_columns = {
|
||||
'type': fields.many2one('event.type', 'Type', help="Type of Event like Seminar, Exhibition, Conference, Training."),
|
||||
'register_max': fields.integer('Maximum Registrations', help="Provide Maximun Number of Registrations"),
|
||||
@@ -157,15 +173,20 @@ class event_event(osv.osv):
|
||||
'mail_registr': fields.text('Registration Email', help='This email will be sent when someone subscribes to the event.'),
|
||||
'mail_confirm': fields.text('Confirmation Email', help="This email will be sent when the event gets confimed or when someone subscribes to a confirmed event. This is also the email sent to remind someone about the event."),
|
||||
'product_id': fields.many2one('product.product', 'Product', required=True, help="Product which is provided cost of event. Invoice of event will be created with this Product."),
|
||||
'note': fields.text('Notes', help="Description or Summary of Event")
|
||||
'note': fields.text('Notes', help="Description or Summary of Event"),
|
||||
'currency_id': fields.many2one('res.currency', 'Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}),
|
||||
"unit_price": fields.float('Cost'),
|
||||
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'state': 'draft',
|
||||
'code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'event.event'),
|
||||
# 'code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'event.event'),
|
||||
'user_id': lambda obj, cr, uid, context: uid,
|
||||
'currency_id': _get_currency,
|
||||
}
|
||||
|
||||
|
||||
event_event()
|
||||
|
||||
class event_registration(osv.osv):
|
||||
@@ -192,13 +213,16 @@ and users by email"),
|
||||
"invoice_id": fields.many2one("account.invoice", "Invoice"),
|
||||
'date_closed': fields.datetime('Closed', readonly=True),
|
||||
'ref': fields.reference('Reference', selection=crm._links_get, size=128),
|
||||
'ref2': fields.reference('Reference 2', selection=crm._links_get, size=128),
|
||||
'ref2': fields.reference('Reference 2', selection=crm._links_get, size=128),
|
||||
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('model','=',_name)]),
|
||||
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('model','=',_name)]),
|
||||
'currency_id': fields.many2one('res.currency', 'Currency', readonly=True),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'nb_register': 1,
|
||||
'tobe_invoiced': True,
|
||||
'name': 'Registration',
|
||||
# 'currency_id': _get_currency,
|
||||
}
|
||||
|
||||
def _make_invoice(self, cr, uid, reg, lines, context=None):
|
||||
@@ -235,7 +259,7 @@ and users by email"),
|
||||
res = False
|
||||
invoices = {}
|
||||
tax_ids=[]
|
||||
|
||||
new_invoice_ids = []
|
||||
inv_lines_pool = self.pool.get('account.invoice.line')
|
||||
inv_pool = self.pool.get('account.invoice')
|
||||
product_pool = self.pool.get('product.product')
|
||||
@@ -276,6 +300,7 @@ and users by email"),
|
||||
invoices.setdefault(reg.partner_id.id, []).append((reg, inv_line_ids))
|
||||
|
||||
for val in invoices.values():
|
||||
res = False
|
||||
if grouped:
|
||||
res = self._make_invoice(cr, uid, val[0][0], [v for k , v in val], context=context)
|
||||
|
||||
@@ -286,7 +311,9 @@ and users by email"),
|
||||
for k , v in val:
|
||||
res = self._make_invoice(cr, uid, k, [v], context=context)
|
||||
self.write(cr, uid, [k.id], {'state': 'done', 'invoice_id': res}, context=context)
|
||||
return res
|
||||
if res: new_invoice_ids.append(res)
|
||||
|
||||
return new_invoice_ids
|
||||
|
||||
def check_confirm(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
@@ -302,7 +329,7 @@ and users by email"),
|
||||
if total_confirmed <= registration.event_id.register_max or registration.event_id.register_max == 0:
|
||||
self.write(cr, uid, [registration.id], {'state': 'open'}, context=context)
|
||||
self.mail_user(cr, uid, [registration.id])
|
||||
self._history(cr, uid, [registration.id], _('Open'))
|
||||
self._history(cr, uid, [registration], _('Open'))
|
||||
else:
|
||||
unconfirmed_ids.append(registration.id)
|
||||
if unconfirmed_ids:
|
||||
@@ -343,6 +370,7 @@ and users by email"),
|
||||
|
||||
values['date_deadline']= event.date_begin
|
||||
values['description']= event.mail_confirm
|
||||
values['currency_id'] = event.currency_id.id
|
||||
res = super(event_registration, self).create(cr, uid, values, context=context)
|
||||
registrations = self.browse(cr, uid, [res], context=context)
|
||||
self._history(cr, uid, registrations, _('Created'))
|
||||
@@ -354,7 +382,6 @@ and users by email"),
|
||||
values['date_deadline']= event.date_begin
|
||||
values['description']= event.mail_confirm
|
||||
return super(event_registration, self).write(cr, uid, ids, values, context=context)
|
||||
|
||||
|
||||
def mail_user(self, cr, uid, ids, confirm=False, context=None):
|
||||
"""
|
||||
@@ -434,14 +461,16 @@ and users by email"),
|
||||
return {'value': {'unit_price': False, 'event_product': False}}
|
||||
data_event = self.pool.get('event.event').browse(cr, uid, event_id)
|
||||
|
||||
context['currency_id'] = data_event.currency_id.id
|
||||
|
||||
if data_event.product_id:
|
||||
if not partner_invoice_id:
|
||||
unit_price=self.pool.get('product.product').price_get(cr, uid, [data_event.product_id.id], context=context)[data_event.product_id.id]
|
||||
return {'value': {'unit_price': unit_price, 'event_product': data_event.product_id.name}}
|
||||
return {'value': {'unit_price': unit_price, 'event_product': data_event.product_id.name, 'currency_id': data_event.currency_id.id}}
|
||||
data_partner = self.pool.get('res.partner').browse(cr, uid, partner_invoice_id)
|
||||
context.update({'partner_id': data_partner})
|
||||
unit_price = self.pool.get('product.product')._product_price(cr, uid, [data_event.product_id.id], False, False, {'pricelist': data_partner.property_product_pricelist.id})[data_event.product_id.id]
|
||||
return {'value': {'unit_price': unit_price, 'event_product': data_event.product_id.name}}
|
||||
return {'value': {'unit_price': unit_price, 'event_product': data_event.product_id.name, 'currency_id': data_event.currency_id.id}}
|
||||
|
||||
return {'value': {'unit_price': False, 'event_product': False}}
|
||||
|
||||
@@ -489,6 +518,5 @@ and users by email"),
|
||||
|
||||
event_registration()
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
<field name="date_begin">2008-01-01 19:00:00</field>
|
||||
<field name="date_end">2008-01-01 23:00:00</field>
|
||||
<field name="product_id" ref="event_product_0"/>
|
||||
<field name="unit_price">68.00</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="register_max">500</field>
|
||||
<field name="type" ref="event_type_1"/>
|
||||
@@ -91,6 +92,7 @@
|
||||
<field name="date_begin">2008-03-05 18:00:00</field>
|
||||
<field name="date_end">2008-03-05 21:00:00</field>
|
||||
<field name="product_id" ref="event_product_1"/>
|
||||
<field name="unit_price">24.00</field>
|
||||
<field name="type" ref="event_type_1"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="register_max">350</field>
|
||||
@@ -102,6 +104,7 @@
|
||||
<field name="date_begin">2008-09-09 14:00:00</field>
|
||||
<field name="date_end">2008-09-09 16:30:00</field>
|
||||
<field name="product_id" ref="event_product_2"/>
|
||||
<field name="unit_price">15.50</field>
|
||||
<field name="type" ref="event_type_2"/>
|
||||
<field name="register_max">200</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
|
||||
+136
-75
@@ -51,10 +51,12 @@
|
||||
<field name="user_id" select="1"/>
|
||||
<field name="date_begin" select="1"/>
|
||||
<field name="date_end"/>
|
||||
<field name="product_id"/>
|
||||
<field name="product_id" on_change="onchange_product(product_id)"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="General">
|
||||
<field name="unit_price"/>
|
||||
<field name="currency_id"/>
|
||||
<separator string="Event description" colspan="4"/>
|
||||
<field name="parent_id" domain="[('parent_id','child_of','Event')]"/>
|
||||
<field name="active"/>
|
||||
@@ -118,6 +120,33 @@
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_event_calendar" model="ir.ui.view">
|
||||
<field name="name">event.event.calendar</field>
|
||||
<field name="model">event.event</field>
|
||||
<field name="type">calendar</field>
|
||||
<field eval="2" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<calendar color="user_id" date_start="date_begin" string="Event Organization">
|
||||
<field name="name"/>
|
||||
<field name="type"/>
|
||||
</calendar>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record model="ir.ui.view" id="view_event_graph">
|
||||
<field name="name">Event Graph</field>
|
||||
<field name="model">event.event</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Event by Registration" type="bar" orientation="horizontal">
|
||||
<field name="name"/>
|
||||
<field name="register_current" operator="+"/>
|
||||
<field name="register_prospect" operator="+"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_search">
|
||||
<field name="name">Events</field>
|
||||
@@ -160,7 +189,7 @@
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">event.event</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_mode">tree,form,calendar,graph</field>
|
||||
<field name="context">{"search_default_draft": "1"}</field>
|
||||
<field name="search_view_id" ref="view_event_search"/>
|
||||
</record>
|
||||
@@ -170,9 +199,18 @@
|
||||
name="Registration"
|
||||
res_model="event.registration"
|
||||
src_model="event.event"
|
||||
view_mode="tree,form"
|
||||
view_mode="tree,form,calendar,graph"
|
||||
domain="[('event_id', '=', active_id)]"
|
||||
view_type="form"/>
|
||||
|
||||
<act_window
|
||||
id="act_register_event_partner"
|
||||
name="Subscribe"
|
||||
res_model="event.registration"
|
||||
src_model="res.partner"
|
||||
view_mode="tree,form,calendar,graph"
|
||||
domain="[('partner_id', '=', active_id)]"
|
||||
view_type="form"/>
|
||||
|
||||
<menuitem name="Events" id="menu_event_event" action="action_event_view" parent="menu_event_main" />
|
||||
|
||||
@@ -203,29 +241,32 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Registration">
|
||||
<group col="6" colspan="4">
|
||||
<field name="name" select="1" colspan="2"/>
|
||||
<field name="event_id" select="1" on_change="onchange_event(event_id, partner_invoice_id)" domain="[('state','in',('draft','confirm'))]"/>
|
||||
<field name="nb_register"/>
|
||||
<group colspan="2">
|
||||
<field name="user_id" select="1"/>
|
||||
<button name="remind_user" string="Send Reminder" states="open,pending" type="object" colspan="2" icon="gtk-go-forward"/>
|
||||
</group>
|
||||
<field name="user_id" select="1"/>
|
||||
<newline/>
|
||||
<field name="partner_id" required="1" select="1" on_change="onchange_partner_id(partner_id,event_id)" />
|
||||
<field name="partner_invoice_id" on_change="onchange_partner_invoice_id(event_id, partner_invoice_id)"/>
|
||||
<field name="unit_price"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="General">
|
||||
<field name="contact_id" on_change="onchange_contact_id(contact_id, partner_id)" /><newline/>
|
||||
<group colspan="4" col="6">
|
||||
<field name="nb_register"/>
|
||||
<field name="unit_price"/>
|
||||
<field name="currency_id"/>
|
||||
</group>
|
||||
<separator string="Communication Information" colspan="4"/>
|
||||
<field name="contact_id" on_change="onchange_contact_id(contact_id, partner_id)" />
|
||||
<field name="email_from"/>
|
||||
<button name="remind_partner" string="Send Reminder" states="open,pending" type="object" colspan="2" icon="gtk-go-forward"/>
|
||||
<newline/>
|
||||
<separator string="Badge" colspan="4"/>
|
||||
<field name="badge_title"/>
|
||||
<field name="badge_name" on_change="onchange_badge_name(badge_name)"/>
|
||||
<field name="badge_partner"/>
|
||||
<newline/>
|
||||
<separator string="Status" colspan="4"/>
|
||||
<group col="8" colspan="4">
|
||||
<separator string="Status" colspan="4"/>
|
||||
<newline/>
|
||||
<field name="state" select="1" colspan="2"/>
|
||||
<button name="button_reg_close" string="Close Registration" states="open" type="object" icon="gtk-close"/>
|
||||
<button name="check_confirm" string="Confirm Registration" states="draft" type="object" icon="gtk-apply"/>
|
||||
@@ -241,77 +282,97 @@
|
||||
<group colspan="4">
|
||||
<field colspan="4" name="email_cc" string="CC"/>
|
||||
</group>
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="form,tree">
|
||||
<form string="Communication history">
|
||||
<group col="6" colspan="4">
|
||||
<field name="date"/>
|
||||
<field name="email_to"/>
|
||||
<field name="email_from"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Details">
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
<page string="Attachments">
|
||||
<field name="attachment_ids" colspan="4" readonly="1" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<button colspan="4"
|
||||
string="Reply to Last Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'crm.lead', 'include_original' : True}"
|
||||
icon="gtk-undo" type="action" />
|
||||
</form>
|
||||
<tree string="Communication history">
|
||||
<field name="date"/>
|
||||
<field name="email_from" />
|
||||
<field name="email_to"/>
|
||||
<field name="description"/>
|
||||
</tree>
|
||||
</field>
|
||||
<button colspan="4" string="Send New Email"
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="form,tree">
|
||||
<form string="Communication history">
|
||||
<group col="6" colspan="4">
|
||||
<field name="date"/>
|
||||
<field name="email_to"/>
|
||||
<field name="email_from"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Details">
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
<page string="Attachments">
|
||||
<field name="attachment_ids" colspan="4" readonly="1" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<button colspan="4"
|
||||
string="Reply to Last Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'event.registration', 'include_original' : True}"
|
||||
icon="gtk-undo" type="action" />
|
||||
</form>
|
||||
<tree string="Communication history">
|
||||
<field name="date"/>
|
||||
<field name="email_from" />
|
||||
<field name="email_to"/>
|
||||
<field name="description"/>
|
||||
</tree>
|
||||
</field>
|
||||
<button colspan="4" string="Send New Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'new', 'model': 'event.registration'}"
|
||||
icon="gtk-go-forward" type="action" />
|
||||
</page>
|
||||
<page string="History">
|
||||
<group colspan="4">
|
||||
<field name="name" select="1" colspan="4"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Dates" colspan="2"/>
|
||||
<field name="create_date"/>
|
||||
<field name="date_closed"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
</page>
|
||||
<page string="History">
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Dates" colspan="2"/>
|
||||
<field name="create_date"/>
|
||||
<field name="date_closed"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Misc" colspan="2"/>
|
||||
<field name="id"/>
|
||||
<field name="active"/>
|
||||
</group>
|
||||
<group col="3" colspan="4">
|
||||
<separator colspan="4" string="References"/>
|
||||
<field name="ref" />
|
||||
<field name="ref2" />
|
||||
</group>
|
||||
<!-- TODO-->
|
||||
<field name="log_ids" nolabel="1" colspan="4">
|
||||
<tree string="Logs">
|
||||
<field name="name" colspan="4"/>
|
||||
<field name="date"/>
|
||||
<field name="user_id"/>
|
||||
</tree>
|
||||
<form string="Logs">
|
||||
<separator string="Action Information" colspan="4"/>
|
||||
<field name="name" colspan="4"/>
|
||||
<field name="date"/>
|
||||
<field name="user_id"/>
|
||||
</form>
|
||||
</field>
|
||||
</page>
|
||||
<!-- TODO-->
|
||||
<field name="log_ids" nolabel="1" colspan="4">
|
||||
<tree string="Logs">
|
||||
<field name="name" colspan="4"/>
|
||||
<field name="date"/>
|
||||
<field name="user_id"/>
|
||||
</tree>
|
||||
<form string="Logs">
|
||||
<separator string="Action Information" colspan="4"/>
|
||||
<field name="name" colspan="4"/>
|
||||
<field name="date"/>
|
||||
<field name="user_id"/>
|
||||
</form>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Calendar view of event registration -->
|
||||
|
||||
<record id="view_event_registration_calendar" model="ir.ui.view">
|
||||
<field name="name">event.registration.calendar</field>
|
||||
<field name="model">event.registration</field>
|
||||
<field name="type">calendar</field>
|
||||
<field eval="2" name="priority"/>
|
||||
<field name="arch" type="xml">
|
||||
<calendar color="event_id" date_start="create_date" string="Event Registration">
|
||||
<field name="event_id"/>
|
||||
<field name="partner_invoice_id"/>
|
||||
</calendar>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="view_event_registration_graph">
|
||||
<field name="name">Registration Graph</field>
|
||||
<field name="model">event.registration</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Registration" type="bar" orientation="horizontal">
|
||||
<field name="event_id"/>
|
||||
<field name = "nb_register" operator="+"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Search view of event registration form-->
|
||||
|
||||
@@ -322,8 +383,8 @@
|
||||
<field name="arch" type="xml">
|
||||
<search string="Event Registration">
|
||||
<group col="12" colspan="4">
|
||||
<filter icon="terp-document-new" string="Draft" name="draft" domain="[('state','=','draft')]" help="Draft Registrations"/>
|
||||
<filter icon="terp-camera_test" string="Confirmed" domain="[('state','in',('open','done'))]" help="Confirmed Registrations"/>
|
||||
<filter icon="terp-check" string="Current" name="draft" domain="[('state','in',('draft', 'open'))]" help="Current Registrations"/>
|
||||
<filter icon="terp-camera_test" string="Open" domain="[('state','=','open')]" help="Open Registrations"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="partner_id" />
|
||||
<field name="event_id" widget="selection"/>
|
||||
@@ -353,7 +414,7 @@
|
||||
<field name="res_model">event.registration</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="domain"></field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_mode">tree,form,calendar,graph</field>
|
||||
<field name="context">{"search_default_draft": "1"}</field>
|
||||
<field name="search_view_id" ref="view_registration_search"/>
|
||||
</record>
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
register_min: 0.0
|
||||
state: draft
|
||||
type: 'event_type_conference0'
|
||||
reply_to: 'info@customer.com'
|
||||
|
||||
- |
|
||||
we set the limit of registrations to this event using "Minimum Registrations" 2 and "Maximum Registrations" 10
|
||||
@@ -172,18 +173,6 @@
|
||||
obj_event = self.browse(cr, uid, [ref('event_event_conference0')])[0]
|
||||
assert obj_event.register_current == '2'
|
||||
assert obj_event.register_prospect == '1'
|
||||
|
||||
- |
|
||||
We check all registered partners to this event using the wizard "List Register Partners".
|
||||
-
|
||||
!record {model: event.partners.list, id: event_partners_list_0}:
|
||||
{}
|
||||
-
|
||||
I click on "Open Partners" button of "List Register Partners" wizard.
|
||||
-
|
||||
!python {model: event.partners.list}: |
|
||||
self.list_partners(cr, uid, [ref("event_partners_list_0")], {"active_ids":
|
||||
[ref("event.event_event_conference0")]})
|
||||
|
||||
- |
|
||||
This event is finished by click on "Event Done" button of this event form.
|
||||
|
||||
@@ -21,4 +21,5 @@
|
||||
|
||||
import event_make_invoice
|
||||
import event_confirm_registration
|
||||
import partner_event_registration
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -83,7 +83,7 @@ class event_make_invoice(osv.osv_memory):
|
||||
id = mod_obj.read(cr, uid, result, ['res_id'])
|
||||
|
||||
return {
|
||||
'domain': "[('id','=',%s)]" % res,
|
||||
'domain': "[('id','in',%s)]" % res,
|
||||
'name': 'Invoices',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
@@ -95,4 +95,4 @@ class event_make_invoice(osv.osv_memory):
|
||||
}
|
||||
|
||||
event_make_invoice()
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import wizard
|
||||
import netsvc
|
||||
import tools
|
||||
from osv import fields, osv
|
||||
from tools.translate import _
|
||||
|
||||
|
||||
class partner_event_registration(osv.osv_memory):
|
||||
""" event Registration """
|
||||
|
||||
_name = "partner.event.registration"
|
||||
_description = __doc__
|
||||
_order = 'event_id'
|
||||
|
||||
_columns = {
|
||||
'event_id': fields.many2one('event.event', 'Event'),
|
||||
'event_type': fields.many2one('event.type', 'Type', readonly=True),
|
||||
'unit_price': fields.float('Cost', readonly=True),
|
||||
'currency_id': fields.many2one('res.currency', 'Currency', readonly=True),
|
||||
'start_date': fields.datetime('Start date', required=True, help="Beginning Date of Event", readonly=True),
|
||||
'end_date': fields.datetime('Closing date', required=True, help="Closing Date of Event", readonly=True),
|
||||
'nb_register': fields.integer('Number of Registration'),
|
||||
}
|
||||
_defaults = {
|
||||
'nb_register': 1,
|
||||
}
|
||||
|
||||
def open_registration(self, cr, uid, ids, context=None):
|
||||
value = {}
|
||||
res_obj = self.pool.get('res.partner')
|
||||
record_ids = context and context.get('active_ids', []) or []
|
||||
addr = res_obj.address_get(cr, uid, record_ids)
|
||||
contact_id = False
|
||||
if addr.has_key('default'):
|
||||
job_ids = self.pool.get('res.partner.job').search(cr, uid, [('address_id', '=', addr['default'])])
|
||||
if job_ids:
|
||||
contact_id = self.pool.get('res.partner.job').browse(cr, uid, job_ids[0]).contact_id.id
|
||||
|
||||
event_obj = self.pool.get('event.event')
|
||||
reg_obj = self.pool.get('event.registration')
|
||||
mod_obj = self.pool.get('ir.model.data')
|
||||
result = mod_obj._get_id(cr, uid, 'event', 'view_registration_search')
|
||||
res = mod_obj.read(cr, uid, result, ['res_id'])
|
||||
|
||||
data_obj = self.pool.get('ir.model.data')
|
||||
# Select the view
|
||||
id2 = data_obj._get_id(cr, uid, 'event', 'view_event_registration_form')
|
||||
id3 = data_obj._get_id(cr, uid, 'event', 'view_event_registration_tree')
|
||||
if id2:
|
||||
id2 = data_obj.browse(cr, uid, id2, context=context).res_id
|
||||
if id3:
|
||||
id3 = data_obj.browse(cr, uid, id3, context=context).res_id
|
||||
|
||||
for current in self.browse(cr, uid, ids, context=context):
|
||||
for reg in reg_obj.browse(cr, uid, record_ids, context=context):
|
||||
new_case = reg_obj.create(cr, uid, {
|
||||
'name' : 'Registration',
|
||||
'event_id' : current.event_id and current.event_id.id or False,
|
||||
'unit_price' : current.event_id.unit_price,
|
||||
'currency_id' : current.event_id.currency_id and current.event_id.currency_id.id or False,
|
||||
'partner_id' : record_ids[0],
|
||||
'partner_invoice_id' : record_ids[0] or False,
|
||||
'event_product': current.event_id.product_id.name,
|
||||
'contact_id': contact_id,
|
||||
'nb_register': current.nb_register,
|
||||
|
||||
}, context=context)
|
||||
|
||||
value = {
|
||||
'name': _('Event Registration'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'event.registration',
|
||||
'res_id' : new_case,
|
||||
'views': [(id2, 'form'), (id3, 'tree'), (False, 'calendar'), (False, 'graph')],
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': res['res_id']
|
||||
}
|
||||
return value
|
||||
|
||||
def name_get(self, cr, uid, ids, context=None):
|
||||
"""Overrides orm name_get method
|
||||
@param ids: List of partner_event_register ids
|
||||
"""
|
||||
if not context:
|
||||
context = {}
|
||||
|
||||
res = []
|
||||
if not ids:
|
||||
return res
|
||||
reads = self.read(cr, uid, ids, ['event_type', 'event_id'], context)
|
||||
for record in reads:
|
||||
event_id = record['event_id'][1]
|
||||
if record['event_type']:
|
||||
event_id = record['event_type'][1] + ' on ' + event_id
|
||||
res.append((record['id'], event_id))
|
||||
return res
|
||||
|
||||
def onchange_event_id(self, cr, uid, ids, event_id, context={}):
|
||||
res = {}
|
||||
if event_id:
|
||||
obj_event = self.pool.get('event.event')
|
||||
event = obj_event.browse(cr, uid, event_id)
|
||||
res['value'] = {
|
||||
'event_type': event.type and event.type.id or False,
|
||||
'start_date': event.date_begin,
|
||||
'end_date': event.date_end,
|
||||
'unit_price': event.unit_price,
|
||||
'currency_id': event.currency_id and event.currency_id.id or False
|
||||
}
|
||||
return res
|
||||
|
||||
partner_event_registration()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Partner event registration -->
|
||||
|
||||
<record id="view_partner_event_registration" model="ir.ui.view">
|
||||
<field name="name">Partner event registration</field>
|
||||
<field name="model">partner.event.registration</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Event Registration">
|
||||
<separator string="Event For Registration" colspan="4"/>
|
||||
<group colspan="4" col="4">
|
||||
<field name="event_id" on_change="onchange_event_id(event_id, context)"/>
|
||||
<field name="nb_register"/>
|
||||
</group>
|
||||
<separator string="Event Details" colspan="4"/>
|
||||
<group colspan="4" col="4">
|
||||
<field name="start_date"/>
|
||||
<field name="end_date"/>
|
||||
<field name="event_type"/>
|
||||
<group colspan="2" col="3">
|
||||
<field name="unit_price"/>
|
||||
<field name="currency_id" nolabel="1"/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
|
||||
<separator string="" colspan="4" />
|
||||
<group colspan="4" col="6">
|
||||
<label string="" colspan="2"/>
|
||||
<button special="cancel" string="_Close" icon="gtk-close"/>
|
||||
<button name="open_registration" string="_Subcribe" type="object" icon="gtk-go-back"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<act_window name="Event Registration"
|
||||
res_model="partner.event.registration"
|
||||
src_model="res.partner"
|
||||
view_mode="form"
|
||||
target="new"
|
||||
key2="client_action_multi"
|
||||
id="action_partner_event_registration"
|
||||
/>
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -31,7 +31,7 @@
|
||||
'author': 'Tiny',
|
||||
'depends': ['project_retro_planning', 'event'],
|
||||
'init_xml': [],
|
||||
'update_xml': ['event_wizard.xml', 'event_view.xml'],
|
||||
'update_xml': ['wizard/event_project_view.xml', 'event_view.xml'],
|
||||
'demo_xml': [],
|
||||
'installable': True,
|
||||
'active': False,
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<field name="register_max" position="after">
|
||||
<separator string="Tasks management" colspan="4"/>
|
||||
<field name="project_id"/>
|
||||
<button string="Create Retro-Planning" name="%(event_wiz)d" type="action" icon="gtk-execute"/>
|
||||
<button string="Create Retro-Planning" name="%(action_event_project)d" type="action" icon="gtk-execute"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
@@ -39,6 +39,15 @@
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<act_window
|
||||
id="act_event_task"
|
||||
name="Tasks"
|
||||
res_model="project.task"
|
||||
src_model="event.event"
|
||||
view_mode="tree,form,calendar,graph"
|
||||
domain="[('project_id', '=', project_id)]"
|
||||
view_type="form"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -1,18 +1,6 @@
|
||||
<?xml version="1.0" ?>
|
||||
<openerp>
|
||||
<data>
|
||||
<wizard string="Project"
|
||||
model="event.event"
|
||||
name="event.project"
|
||||
id="event_wiz"
|
||||
menu="False"/>
|
||||
|
||||
<wizard
|
||||
string="Tasks"
|
||||
model="event.event"
|
||||
name="wizard_event_tasks"
|
||||
id="wizard_event_task"/>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import project_wizard
|
||||
import event_task
|
||||
import event_project
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
#
|
||||
# Order Point Method:
|
||||
# - Order if the virtual stock of today is bellow the min of the defined order point
|
||||
#
|
||||
|
||||
from osv import fields, osv
|
||||
from tools.translate import _
|
||||
import time
|
||||
|
||||
class event_project(osv.osv_memory):
|
||||
"""
|
||||
Event Project
|
||||
"""
|
||||
_name = "event.project"
|
||||
_description = "Event Project"
|
||||
|
||||
_columns = {
|
||||
'project_id': fields.many2one('project.project', 'Template of Project', domain = [('active', '<>', False), ('state', '=', 'template')], required =True, help="This is Template Project. Project of event is a duplicate of this Template. After click on 'Create Retro-planning', New Project will be duplicated from this template project.")
|
||||
}
|
||||
|
||||
def create_duplicate(self, cr, uid, ids, context):
|
||||
event_obj=self.pool.get('event.event')
|
||||
project_obj = self.pool.get('project.project')
|
||||
event = event_obj.browse(cr, uid, context.get('active_id', False))
|
||||
for current in self.browse(cr, uid, ids):
|
||||
duplicate_project_id = project_obj.copy(cr, uid, current.project_id.id, {'active': True})
|
||||
duplicate_project = project_obj.browse(cr, uid, duplicate_project_id, context)
|
||||
project_obj.write(cr, uid, [duplicate_project_id], {
|
||||
'name': duplicate_project.name ,
|
||||
'date_start':time.strftime('%Y-%m-%d'),
|
||||
'date': event.date_begin[0:10] })
|
||||
event_obj.write(cr, uid, [event.id], {'project_id': duplicate_project_id })
|
||||
|
||||
return {}
|
||||
|
||||
event_project()
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_event_project" model="ir.ui.view">
|
||||
<field name="name">Retro-Planning</field>
|
||||
<field name="model">event.project</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Retro-Planning">
|
||||
<field name="project_id" />
|
||||
<separator string="" colspan="4"/>
|
||||
<group colspan="4" col="6">
|
||||
<button icon="gtk-close" special="cancel" string="Close"/>
|
||||
<button icon="gtk-ok" name="create_duplicate" string="Ok" type="object"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_event_project" model="ir.actions.act_window">
|
||||
<field name="name">Retro-Planning</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">event.project</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="view_event_project"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,62 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import wizard
|
||||
import pooler
|
||||
from tools.translate import _
|
||||
|
||||
def _event_tasks(self, cr, uid, data, context):
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
mod_obj = pool.get('ir.model.data')
|
||||
result = mod_obj._get_id(cr, uid, 'project', 'view_task_search_form')
|
||||
id = mod_obj.read(cr, uid, result, ['res_id'])
|
||||
event_id = data['id']
|
||||
cr.execute('SELECT project_id FROM event_event WHERE id = %s', (event_id, ))
|
||||
res = cr.fetchone()
|
||||
if not res[0]:
|
||||
raise wizard.except_wizard(_('Error !'), _('No project defined for this event.\nYou can create one with the retro-planning button !'))
|
||||
value = {
|
||||
'domain': [('project_id', '=', res[0])],
|
||||
'name': 'Tasks',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form,calendar',
|
||||
'res_model': 'project.task',
|
||||
'context': { },
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': id['res_id']
|
||||
}
|
||||
return value
|
||||
|
||||
class wizard_event_tasks(wizard.interface):
|
||||
states = {
|
||||
'init': {
|
||||
'actions': [],
|
||||
'result': {
|
||||
'type': 'action',
|
||||
'action': _event_tasks,
|
||||
'state': 'end'
|
||||
}
|
||||
},
|
||||
}
|
||||
wizard_event_tasks("wizard_event_tasks")
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
#
|
||||
# Order Point Method:
|
||||
# - Order if the virtual stock of today is bellow the min of the defined order point
|
||||
#
|
||||
|
||||
import wizard
|
||||
import pooler
|
||||
|
||||
import time
|
||||
|
||||
parameter_form = '''<?xml version="1.0"?>
|
||||
<form string="Event" colspan="4">
|
||||
<field name="project_id"
|
||||
/>
|
||||
</form>'''
|
||||
|
||||
parameter_fields = {
|
||||
'project_id': {'string':'Project', 'type':'many2one', 'required':True, 'relation':'project.project', 'domain': [('active','<>',False),('state','=','template')]},
|
||||
}
|
||||
|
||||
def _create_duplicate(self, cr, uid, data, context):
|
||||
event_obj=pooler.get_pool(cr.dbname).get('event.event')
|
||||
project_obj = pooler.get_pool(cr.dbname).get('project.project')
|
||||
duplicate_project_id= project_obj.copy(cr, uid, data['form']['project_id'], {'active': True})
|
||||
project_obj.write(cr, uid, [duplicate_project_id], {'name': "copy of " + project_obj.browse(cr, uid, duplicate_project_id, context).name , 'date_start':time.strftime('%Y-%m-%d'),'date': event_obj.browse(cr, uid, [data['id']])[0].date_begin[0:10] })
|
||||
event_obj.write(cr, uid, [data['id']], {'project_id': duplicate_project_id })
|
||||
return {}
|
||||
|
||||
class wizard_event_project(wizard.interface):
|
||||
states = {
|
||||
'init': {
|
||||
'actions': [],
|
||||
'result': {'type': 'form', 'arch':parameter_form, 'fields': parameter_fields, 'state':[('end','Cancel'),('done', 'Ok')]}
|
||||
|
||||
},
|
||||
'done':{
|
||||
'actions':[_create_duplicate],
|
||||
'result' : {'type':'state', 'state':'end'}
|
||||
}
|
||||
}
|
||||
wizard_event_project('event.project')
|
||||
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -109,7 +109,7 @@ class hr_timesheet_invoice_create(osv.osv_memory):
|
||||
last_invoice = self.pool.get('account.invoice').create(cr, uid, curr_invoice)
|
||||
invoices.append(last_invoice)
|
||||
|
||||
context2=context.copy()
|
||||
context2 = context.copy()
|
||||
context2['lang'] = partner.lang
|
||||
cr.execute("SELECT product_id, to_invoice, sum(unit_amount) " \
|
||||
"FROM account_analytic_line as line " \
|
||||
@@ -158,7 +158,7 @@ class hr_timesheet_invoice_create(osv.osv_memory):
|
||||
#
|
||||
# Compute for lines
|
||||
#
|
||||
cr.execute("SELECT * FROM account_analytic_line WHERE account_id = %s and id IN %s AND product_id=%s and to_invoice=%s", (account.id, tuple(data['ids']), product_id, factor_id))
|
||||
cr.execute("SELECT * FROM account_analytic_line WHERE account_id = %s and id IN %s AND product_id=%s and to_invoice=%s ORDER BY account_analytic_line.date", (account.id, tuple(data['ids']), product_id, factor_id))
|
||||
|
||||
line_ids = cr.dictfetchall()
|
||||
note = []
|
||||
@@ -169,7 +169,7 @@ class hr_timesheet_invoice_create(osv.osv_memory):
|
||||
details.append(line['date'])
|
||||
if data['time']:
|
||||
if line['product_uom_id']:
|
||||
details.append("%s %s" % (line['unit_amount'], self.pool.get('product.uom').browse(cr, uid, [line['product_uom_id']])[0].name))
|
||||
details.append("%s %s" % (line['unit_amount'], self.pool.get('product.uom').browse(cr, uid, [line['product_uom_id']],context2)[0].name))
|
||||
else:
|
||||
details.append("%s" % (line['unit_amount'], ))
|
||||
if data['name']:
|
||||
|
||||
@@ -7,13 +7,13 @@ msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 5.0.4\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
|
||||
"PO-Revision-Date: 2009-11-17 07:57+0000\n"
|
||||
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
|
||||
"PO-Revision-Date: 2010-07-01 09:07+0000\n"
|
||||
"Last-Translator: Borja López Soilán (Pexego) <borjals@pexego.es>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-06-22 04:14+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-07-02 03:33+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: l10n_chart_uk_minimal
|
||||
@@ -43,7 +43,7 @@ msgstr "Ingreso"
|
||||
#. module: l10n_chart_uk_minimal
|
||||
#: model:account.account.type,name:l10n_chart_uk_minimal.account_type_tax
|
||||
msgid "Tax"
|
||||
msgstr "Contribución"
|
||||
msgstr "Impuesto"
|
||||
|
||||
#. module: l10n_chart_uk_minimal
|
||||
#: model:account.account.type,name:l10n_chart_uk_minimal.account_type_cash
|
||||
|
||||
@@ -21,12 +21,11 @@
|
||||
|
||||
|
||||
{
|
||||
"name" : "",
|
||||
"name" : "marketing_campaign",
|
||||
"version" : "1.1",
|
||||
"depends" : ["marketing",
|
||||
"crm",
|
||||
"document",
|
||||
"email_template"
|
||||
"document",
|
||||
"email_template"
|
||||
],
|
||||
"author" : "OpenERP SA",
|
||||
"category": 'Generic Modules/Marketing',
|
||||
@@ -37,6 +36,8 @@ are dynamic and multi-channels. The process:
|
||||
miscelleanous actions, etc.
|
||||
* Define segments that are selections of target people
|
||||
* Launch your campaign to automate communications.
|
||||
|
||||
If you need demo data, you can install the module marketing_campaign_crm_demo.
|
||||
""",
|
||||
'website': 'http://www.openerp.com',
|
||||
'init_xml': [],
|
||||
@@ -50,8 +51,7 @@ are dynamic and multi-channels. The process:
|
||||
"security/ir.model.access.csv"
|
||||
],
|
||||
'demo_xml': [
|
||||
'marketing_campaign_demo.xml',
|
||||
],
|
||||
],
|
||||
'installable': True,
|
||||
'active': False,
|
||||
}
|
||||
|
||||
@@ -23,10 +23,12 @@ import time
|
||||
import base64
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from operator import itemgetter
|
||||
from traceback import format_exception
|
||||
from sys import exc_info
|
||||
|
||||
from osv import fields, osv
|
||||
import netsvc
|
||||
import tools
|
||||
from tools.translate import _
|
||||
|
||||
_intervalTypes = {
|
||||
@@ -36,6 +38,46 @@ _intervalTypes = {
|
||||
'years': lambda interval: relativedelta(years=interval),
|
||||
}
|
||||
|
||||
DT_FMT = '%Y-%m-%d %H:%M:%S'
|
||||
|
||||
def dict_map(f, d):
|
||||
return dict((k, f(v)) for k,v in d.items())
|
||||
|
||||
def _find_fieldname(model, field):
|
||||
inherit_columns = dict_map(itemgetter(2), model._inherit_fields)
|
||||
all_columns = dict(inherit_columns, **model._columns)
|
||||
for fn in all_columns:
|
||||
if all_columns[fn] is field:
|
||||
return fn
|
||||
raise ValueError('field not found: %r' % (field,))
|
||||
|
||||
class selection_converter(object):
|
||||
"""Format the selection in the browse record objects"""
|
||||
def __init__(self, value):
|
||||
self._value = value
|
||||
self._str = value
|
||||
|
||||
def set_value(self, cr, uid, _self_again, record, field, lang):
|
||||
# this design is terrible
|
||||
# search fieldname from the field
|
||||
fieldname = _find_fieldname(record._table, field)
|
||||
context = dict(lang=lang.code)
|
||||
fg = record._table.fields_get(cr, uid, [fieldname], context=context)
|
||||
selection = dict(fg[fieldname]['selection'])
|
||||
self._str = selection[self.value]
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
return self._value
|
||||
|
||||
def __str__(self):
|
||||
return self._str
|
||||
|
||||
translate_selections = {
|
||||
'selection': selection_converter,
|
||||
}
|
||||
|
||||
|
||||
class marketing_campaign(osv.osv):
|
||||
_name = "marketing.campaign"
|
||||
_description = "Marketing Campaign"
|
||||
@@ -45,6 +87,9 @@ class marketing_campaign(osv.osv):
|
||||
'object_id': fields.many2one('ir.model', 'Object', required=True,
|
||||
help="Choose the Object on which you want \
|
||||
this campaign to be run"),
|
||||
'partner_field_id': fields.many2one('ir.model.fields', 'Partner Field',
|
||||
domain="[('model_id', '=', object_id), ('ttype', '=', 'many2one'), ('relation', '=', 'res.partner')]",
|
||||
help="The generated workitems will be linked to the partner related to the record"),
|
||||
'mode':fields.selection([('test', 'Test Directly'),
|
||||
('test_realtime', 'Test in Realtime'),
|
||||
('manual', 'With Manual Confirmation'),
|
||||
@@ -75,11 +120,11 @@ you required for the campaign"),
|
||||
raise osv.except_osv("Error", "There is no activitity in the campaign")
|
||||
actvity_ids = [ act_id.id for act_id in campaign.activity_ids]
|
||||
act_obj = self.pool.get('marketing.campaign.activity')
|
||||
act_ids = act_obj.search(cr, uid, [('id', 'in', actvity_ids),
|
||||
act_ids = act_obj.search(cr, uid, [('id', 'in', actvity_ids),
|
||||
('start', '=', True)])
|
||||
if not act_ids :
|
||||
raise osv.except_osv("Error", "There is no starting activitity in the campaign")
|
||||
act_ids = act_obj.search(cr, uid, [('id', 'in', actvity_ids),
|
||||
act_ids = act_obj.search(cr, uid, [('id', 'in', actvity_ids),
|
||||
('type', '=', 'email')])
|
||||
for activity in act_obj.browse(cr, uid, act_ids):
|
||||
if not activity.email_template_id.enforce_from_account :
|
||||
@@ -101,6 +146,33 @@ you required for the campaign"),
|
||||
def state_cancel_set(self, cr, uid, ids, *args):
|
||||
self.write(cr, uid, ids, {'state': 'cancelled'})
|
||||
return True
|
||||
|
||||
|
||||
def signal(self, cr, uid, model, res_id, signal, context=None):
|
||||
if not signal:
|
||||
raise ValueError('signal cannot be False')
|
||||
|
||||
Workitems = self.pool.get('marketing.campaign.workitem')
|
||||
domain = [('object_id.model', '=', model),
|
||||
('state', '=', 'running')]
|
||||
campaign_ids = self.search(cr, uid, domain, context=context)
|
||||
for campaign in self.browse(cr, uid, campaign_ids, context):
|
||||
for activity in campaign.activity_ids:
|
||||
if activity.signal != signal:
|
||||
continue
|
||||
wi_domain = [('activity_id', '=', activity.id),
|
||||
('res_id', '=', res_id),
|
||||
('state', '=', 'todo'),
|
||||
('date', '=', False),
|
||||
]
|
||||
wi_ids = Workitems.search(cr, uid, wi_domain, context=context)
|
||||
Workitems.process(cr, uid, wi_ids, context=context)
|
||||
return True
|
||||
|
||||
def _signal(self, cr, uid, record, signal, context=None):
|
||||
return self.signal(cr, uid, record._table._name,
|
||||
record.id, signal, context)
|
||||
|
||||
marketing_campaign()
|
||||
|
||||
class marketing_campaign_segment(osv.osv):
|
||||
@@ -135,7 +207,6 @@ class marketing_campaign_segment(osv.osv):
|
||||
|
||||
def state_running_set(self, cr, uid, ids, *args):
|
||||
segment = self.browse(cr, uid, ids[0])
|
||||
curr_date = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
vals = {'state': 'running'}
|
||||
if not segment.date_run:
|
||||
vals['date_run'] = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
@@ -159,19 +230,21 @@ class marketing_campaign_segment(osv.osv):
|
||||
def synchroniz(self, cr, uid, ids, *args):
|
||||
self.process_segment(cr, uid, ids)
|
||||
return True
|
||||
|
||||
def process_segment(self, cr, uid, segment_ids=None, context={}):
|
||||
|
||||
def process_segment(self, cr, uid, segment_ids=None, context=None):
|
||||
Workitems = self.pool.get('marketing.campaign.workitem')
|
||||
if not segment_ids:
|
||||
segment_ids = self.search(cr, uid, [('state', '=', 'running')], context=context)
|
||||
|
||||
action_date = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
campaigns = {}
|
||||
campaigns = set()
|
||||
for segment in self.browse(cr, uid, segment_ids, context=context):
|
||||
campaigns[segment.campaign_id.id] = True
|
||||
campaigns.add(segment.campaign_id.id)
|
||||
act_ids = self.pool.get('marketing.campaign.activity').search(cr,
|
||||
uid, [('start', '=', True), ('campaign_id', '=', segment.campaign_id.id)])
|
||||
uid, [('start', '=', True), ('campaign_id', '=', segment.campaign_id.id)], context=context)
|
||||
|
||||
model_obj = self.pool.get(segment.object_id.model)
|
||||
partner_field = segment.campaign_id.partner_field_id.name
|
||||
criteria = []
|
||||
if segment.sync_last_date:
|
||||
criteria += [(segment.sync_mode, '>', segment.sync_last_date)]
|
||||
@@ -179,24 +252,30 @@ class marketing_campaign_segment(osv.osv):
|
||||
criteria += eval(segment.ir_filter_id.domain)
|
||||
object_ids = model_obj.search(cr, uid, criteria, context=context)
|
||||
|
||||
for o_ids in model_obj.browse(cr, uid, object_ids, context=context) :
|
||||
for o_ids in model_obj.browse(cr, uid, object_ids, context=context):
|
||||
# avoid duplicated workitem for the same resource
|
||||
if segment.sync_mode == 'write_date':
|
||||
segids = self.pool.get('marketing.campaign.workitem').search(cr, uid, [('res_id','=',o_ids.id),('segment_id','=',segment.id)])
|
||||
if segids:
|
||||
wi_ids = Workitems.search(cr, uid, [('res_id','=',o_ids.id),('segment_id','=',segment.id)], context=context)
|
||||
if wi_ids:
|
||||
continue
|
||||
|
||||
wi_vals = {
|
||||
'segment_id': segment.id,
|
||||
'date': action_date,
|
||||
'state': 'todo',
|
||||
'res_id': o_ids.id
|
||||
}
|
||||
if partner_field:
|
||||
partner = getattr(o_ids, partner_field)
|
||||
if partner:
|
||||
wi_vals['partner_id'] = partner.id
|
||||
|
||||
for act_id in act_ids:
|
||||
wi_vals = {
|
||||
'segment_id': segment.id,
|
||||
'activity_id': act_id,
|
||||
'date': action_date,
|
||||
'partner_id': o_ids.partner_id and o_ids.partner_id.id or False,
|
||||
'state': 'todo',
|
||||
'res_id': o_ids.id
|
||||
}
|
||||
self.pool.get('marketing.campaign.workitem').create(cr, uid, wi_vals)
|
||||
self.write(cr, uid, segment.id, {'sync_last_date':action_date})
|
||||
self.pool.get('marketing.campaign.workitem').process_all(cr, uid, campaigns.keys(), context=context)
|
||||
wi_vals['activity_id'] = act_id
|
||||
Workitems.create(cr, uid, wi_vals, context=context)
|
||||
|
||||
self.write(cr, uid, segment.id, {'sync_last_date':action_date}, context=context)
|
||||
Workitems.process_all(cr, uid, list(campaigns), context=context)
|
||||
return True
|
||||
|
||||
marketing_campaign_segment()
|
||||
@@ -204,6 +283,7 @@ marketing_campaign_segment()
|
||||
class marketing_campaign_activity(osv.osv):
|
||||
_name = "marketing.campaign.activity"
|
||||
_description = "Campaign Activity"
|
||||
|
||||
_actions_type = [('email', 'E-mail'), ('paper', 'Paper'), ('action', 'Action'),
|
||||
('subcampaign', 'Sub-Campaign')]
|
||||
_columns = {
|
||||
@@ -212,7 +292,7 @@ class marketing_campaign_activity(osv.osv):
|
||||
required = True, ondelete='cascade', select=1),
|
||||
'object_id': fields.related('campaign_id','object_id',
|
||||
type='many2one', relation='ir.model',
|
||||
string='Object'),
|
||||
string='Object', readonly=True),
|
||||
'start': fields.boolean('Start',help= "This activity is launched when the campaign starts."),
|
||||
'condition': fields.char('Condition', size=256, required=True,
|
||||
help="Python condition to know if the activity can be launched"),
|
||||
@@ -236,15 +316,33 @@ class marketing_campaign_activity(osv.osv):
|
||||
'subcampaign_segment_id': fields.many2one('marketing.campaign.segment',
|
||||
'Sub Campaign Segment'),
|
||||
'variable_cost': fields.float('Variable Cost'),
|
||||
'revenue': fields.float('Revenue')
|
||||
'revenue': fields.float('Revenue'),
|
||||
'signal': fields.char('Signal', size=128,
|
||||
help='An activity with a signal can be called \
|
||||
programmatically'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'type': lambda *a: 'email',
|
||||
'condition': lambda *a: 'True',
|
||||
'object_id' : lambda obj, cr, uid, context : context.get('object_id',False),
|
||||
}
|
||||
|
||||
def _check_signal(self, cr, uid, ids, context=None):
|
||||
return all(activity.signal
|
||||
for activity in self.browse(cr, uid, ids, context)
|
||||
for transition in activity.from_ids
|
||||
if transition.trigger == 'signal')
|
||||
|
||||
_constraints = [
|
||||
(_check_signal,
|
||||
"An incoming transition is triggered by a signal but this transition \
|
||||
doesn't have one",
|
||||
['signal', 'from_ids']
|
||||
),
|
||||
]
|
||||
|
||||
def __init__(self, *args):
|
||||
# FIXME use self._process_wi_<type>
|
||||
self._actions = {'paper' : self.process_wi_report,
|
||||
'email' : self.process_wi_email,
|
||||
'action' : self.process_wi_action,
|
||||
@@ -281,8 +379,8 @@ class marketing_campaign_activity(osv.osv):
|
||||
return True
|
||||
|
||||
def process_wi_email(self, cr, uid, activity, workitem, context=None):
|
||||
return self.pool.get('email.template').generate_mail(cr, uid,
|
||||
activity.email_template_id.id,
|
||||
return self.pool.get('email.template').generate_mail(cr, uid,
|
||||
activity.email_template_id.id,
|
||||
[workitem.res_id], context=context)
|
||||
|
||||
def process_wi_action(self, cr, uid, activity, workitem, context={}):
|
||||
@@ -291,7 +389,7 @@ class marketing_campaign_activity(osv.osv):
|
||||
context['active_id'] = workitem.res_id
|
||||
res = server_obj.run(cr, uid, [activity.server_action_id.id], context)
|
||||
#server action return False if the action is perfomed except client_action,other and python code
|
||||
return res==False and True or res
|
||||
return res==False and True or res
|
||||
|
||||
def process(self, cr, uid, act_id, wi_id, context={}):
|
||||
activity = self.browse(cr, uid, act_id)
|
||||
@@ -304,25 +402,75 @@ marketing_campaign_activity()
|
||||
class marketing_campaign_transition(osv.osv):
|
||||
_name = "marketing.campaign.transition"
|
||||
_description = "Campaign Transition"
|
||||
_rec_name = "interval_type"
|
||||
|
||||
_interval_units = [('hours', 'Hour(s)'), ('days', 'Day(s)'),
|
||||
('months', 'Month(s)'), ('years','Year(s)')]
|
||||
|
||||
|
||||
def _get_name(self, cr, uid, ids, fn, args, context=None):
|
||||
result = dict.fromkeys(ids, False)
|
||||
formatters = {
|
||||
'auto': _('Automatic transition'),
|
||||
'time': _('After %(interval_nbr)d %(interval_type)s'),
|
||||
'signal': _('On signal'),
|
||||
}
|
||||
for tr in self.browse(cr, uid, ids, context=context,
|
||||
fields_process=translate_selections):
|
||||
result[tr.id] = formatters[tr.trigger.value] % tr
|
||||
return result
|
||||
|
||||
|
||||
def _delta(self, cr, uid, ids, context=None):
|
||||
assert len(ids) == 1
|
||||
transition = self.browse(cr, uid, ids[0], context)
|
||||
if transition.trigger != 'time':
|
||||
raise ValueError('Delta is only relevant for timed transiton')
|
||||
return relativedelta(**{transition.interval_type: transition.interval_nbr})
|
||||
|
||||
|
||||
_columns = {
|
||||
'name': fields.function(_get_name, method=True, string='Name',
|
||||
type='char', size=128),
|
||||
'activity_from_id': fields.many2one('marketing.campaign.activity',
|
||||
'Source Activity', select=1),
|
||||
'Source Activity', select=1,
|
||||
required=True),
|
||||
'activity_to_id': fields.many2one('marketing.campaign.activity',
|
||||
'Destination Activity'),
|
||||
'interval_nbr': fields.integer('Interval No.'),
|
||||
'interval_type': fields.selection([('hours', 'Hours'), ('days', 'Days'),
|
||||
('months', 'Months'),
|
||||
('years','Years')],'Interval Type')
|
||||
'Destination Activity',
|
||||
required=True),
|
||||
'interval_nbr': fields.integer('Interval Value', required=True),
|
||||
'interval_type': fields.selection(_interval_units, 'Interval Unit',
|
||||
required=True),
|
||||
|
||||
'trigger': fields.selection([('auto', 'Automatic'),
|
||||
('time', 'Time'),
|
||||
('signal','Signal')],
|
||||
'Trigger', required=True,
|
||||
help="How is trigger the destination workitem"),
|
||||
}
|
||||
|
||||
def default_get(self, cr, uid, fields, context={}):
|
||||
value = super(marketing_campaign_transition, self).default_get(cr, uid,
|
||||
fields, context)
|
||||
if context.has_key('type_id'):
|
||||
value[context['type_id']] = context['activity_id']
|
||||
return value
|
||||
_defaults = {
|
||||
'interval_nbr': 1,
|
||||
'interval_type': 'days',
|
||||
'trigger': 'time',
|
||||
}
|
||||
|
||||
_sql_constraints = [
|
||||
('interval_positive', 'CHECK(interval_nbr >= 0)', 'The interval must be positive or zero')
|
||||
]
|
||||
|
||||
def _check_signal(self, cr, uid, ids, context=None):
|
||||
return all(tr.activity_to_id.signal
|
||||
for tr in self.browse(cr, uid, ids, context)
|
||||
if tr.trigger == 'signal')
|
||||
|
||||
_constraints = [
|
||||
(_check_signal,
|
||||
"The transition is triggered by a signal but destination activity \
|
||||
doesn't have one",
|
||||
['trigger', 'activity_to_ids']
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
marketing_campaign_transition()
|
||||
|
||||
@@ -331,15 +479,15 @@ class marketing_campaign_workitem(osv.osv):
|
||||
_description = "Campaign Workitem"
|
||||
|
||||
def _res_name_get(self, cr, uid, ids, field_name, arg, context=None):
|
||||
res = {}
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.res_id:
|
||||
try:
|
||||
res[obj.id] = self.pool.get(obj.object_id.model).name_get(cr, uid, [obj.res_id], context=context)[0][1]
|
||||
except:
|
||||
res[obj.id] = '/'
|
||||
else:
|
||||
res[obj.id] = '/'
|
||||
res = dict.fromkeys(ids, '/')
|
||||
for wi in self.browse(cr, uid, ids, context=context):
|
||||
if not wi.res_id:
|
||||
continue
|
||||
|
||||
proxy = self.pool.get(wi.object_id.model)
|
||||
ng = proxy.name_get(cr, uid, [wi.res_id], context=context)
|
||||
if ng:
|
||||
res[wi.id] = ng[0][1]
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
@@ -353,9 +501,9 @@ class marketing_campaign_workitem(osv.osv):
|
||||
type='many2one', relation='ir.model', string='Object', select=1),
|
||||
'res_id': fields.integer('Resource ID', select=1, readonly=1),
|
||||
'res_name': fields.function(_res_name_get, method=True, string='Resource Name', type="char", size=64),
|
||||
'date': fields.datetime('Execution Date'),
|
||||
'date': fields.datetime('Execution Date', help='If date is not set, this workitem have to be run manually'),
|
||||
'partner_id': fields.many2one('res.partner', 'Partner', select=1),
|
||||
'state': fields.selection([('todo', 'To Do'), ('inprogress', 'In Progress'),
|
||||
'state': fields.selection([('todo', 'To Do'),
|
||||
('exception', 'Exception'), ('done', 'Done'),
|
||||
('cancelled', 'Cancelled')], 'State'),
|
||||
|
||||
@@ -363,27 +511,9 @@ class marketing_campaign_workitem(osv.osv):
|
||||
}
|
||||
_defaults = {
|
||||
'state': lambda *a: 'todo',
|
||||
'date': False,
|
||||
}
|
||||
|
||||
def process_chain(self, cr, uid, workitem_id, context={}):
|
||||
workitem = self.browse(cr, uid, workitem_id)
|
||||
for mct_id in workitem.activity_id.to_ids:
|
||||
launch_date = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
if mct_id.interval_type and mct_id.interval_nbr :
|
||||
launch_date = (datetime.now() + _intervalTypes[ \
|
||||
mct_id.interval_type](mct_id.interval_nbr) \
|
||||
).strftime('%Y-%m-%d %H:%M:%S')
|
||||
workitem_vals = {
|
||||
'segment_id': workitem.segment_id.id,
|
||||
'activity_id': mct_id.activity_to_id.id,
|
||||
'date': launch_date,
|
||||
'partner_id': workitem.partner_id.id,
|
||||
'res_id': workitem.res_id,
|
||||
'state': 'todo',
|
||||
}
|
||||
self.create(cr, uid, workitem_vals)
|
||||
return True
|
||||
|
||||
def button_draft(self, cr, uid, workitem_ids, context={}):
|
||||
for wi in self.browse(cr, uid, workitem_ids, context=context):
|
||||
if wi.state=='exception':
|
||||
@@ -396,63 +526,115 @@ class marketing_campaign_workitem(osv.osv):
|
||||
self.write(cr, uid, [wi.id], {'state':'cancelled'}, context=context)
|
||||
return True
|
||||
|
||||
def process(self, cr, uid, workitem_ids, context={}):
|
||||
for wi in self.browse(cr, uid, workitem_ids):
|
||||
if wi.state == 'todo':
|
||||
eval_context = {
|
||||
'pool': self.pool,
|
||||
'cr': cr,
|
||||
'uid': uid,
|
||||
'wi': wi,
|
||||
'object': wi.activity_id,
|
||||
'transition': wi.activity_id.to_ids
|
||||
}
|
||||
try:
|
||||
expr = eval(str(wi.activity_id.condition), eval_context)
|
||||
if expr:
|
||||
result = True
|
||||
if wi.campaign_id.mode in ('manual','active'):
|
||||
result = self.pool.get('marketing.campaign.activity').process(
|
||||
cr, uid, wi.activity_id.id, wi.id, context)
|
||||
if result:
|
||||
self.write(cr, uid, wi.id, {'state': 'done'})
|
||||
self.process_chain(cr, uid, wi.id, context)
|
||||
else:
|
||||
vals = {'state': 'exception'}
|
||||
if type(result) == type({}) and 'error_msg' in result:
|
||||
vals['error_msg'] = result['error_msg']
|
||||
self.write(cr, uid, wi.id, vals)
|
||||
else:
|
||||
self.write(cr, uid, wi.id, {'state': 'cancelled'})
|
||||
except Exception,e:
|
||||
self.write(cr, uid, wi.id, {'state': 'exception', 'error_msg': str(e)})
|
||||
def _process_one(self, cr, uid, workitem, context=None):
|
||||
if workitem.state != 'todo':
|
||||
return
|
||||
|
||||
activity = workitem.activity_id
|
||||
|
||||
eval_context = {
|
||||
'pool': self.pool,
|
||||
'cr': cr,
|
||||
'uid': uid,
|
||||
'wi': workitem,
|
||||
'object': activity,
|
||||
'transition': activity.to_ids
|
||||
}
|
||||
try:
|
||||
condition = activity.condition
|
||||
campaign_mode = workitem.campaign_id.mode
|
||||
if condition:
|
||||
if not eval(condition, eval_context):
|
||||
workitem.write({'state': 'cancelled'}, context=context)
|
||||
return
|
||||
result = True
|
||||
if campaign_mode in ('manual', 'active'):
|
||||
Activities = self.pool.get('marketing.campaign.activity')
|
||||
result = Activities.process(cr, uid, activity.id, workitem.id,
|
||||
context=context)
|
||||
|
||||
values = dict(state='done')
|
||||
if not workitem.date:
|
||||
values['date'] = datetime.now().strftime(DT_FMT)
|
||||
workitem.write(values, context=context)
|
||||
|
||||
if result:
|
||||
# process _chain
|
||||
for transition in activity.to_ids:
|
||||
launch_date = False
|
||||
if transition.trigger == 'auto':
|
||||
launch_date = datetime.now()
|
||||
elif transition.trigger == 'time':
|
||||
launch_date = datetime.now() + transition._delta()
|
||||
|
||||
if launch_date:
|
||||
launch_date = launch_date.strftime(DT_FMT)
|
||||
values = {
|
||||
'date': launch_date,
|
||||
'segment_id': workitem.segment_id.id,
|
||||
'activity_id': transition.activity_to_id.id,
|
||||
'partner_id': workitem.partner_id.id,
|
||||
'res_id': workitem.res_id,
|
||||
'state': 'todo',
|
||||
}
|
||||
wi_id = self.create(cr, uid, values, context=context)
|
||||
|
||||
# Now, depending of the trigger and the campaign mode
|
||||
# we now if must run the newly created workitem.
|
||||
#
|
||||
# rows = transition trigger \ colums = campaign mode
|
||||
#
|
||||
# test test_realtime manual normal (active)
|
||||
# time Y N N N
|
||||
# signal N N N N
|
||||
# auto Y Y N Y
|
||||
#
|
||||
|
||||
run = False
|
||||
if transition.trigger != 'signal' and campaign_mode != 'manual':
|
||||
if transition.trigger == 'auto' or campaign_mode == 'test':
|
||||
run = True
|
||||
if run:
|
||||
new_wi = self.browse(cr, uid, wi_id, context)
|
||||
self._process_one(cr, uid, new_wi, context)
|
||||
|
||||
except Exception:
|
||||
tb = "".join(format_exception(*exc_info()))
|
||||
workitem.write({'state': 'exception', 'error_msg': tb},
|
||||
context=context)
|
||||
|
||||
def process(self, cr, uid, workitem_ids, context=None):
|
||||
for wi in self.browse(cr, uid, workitem_ids, context):
|
||||
self._process_one(cr, uid, wi, context)
|
||||
return True
|
||||
|
||||
def process_all(self, cr, uid, camp_ids=None, context={}):
|
||||
def process_all(self, cr, uid, camp_ids=None, context=None):
|
||||
camp_obj = self.pool.get('marketing.campaign')
|
||||
if not camp_ids:
|
||||
if camp_ids is None:
|
||||
camp_ids = camp_obj.search(cr, uid, [('state','=','running')], context=context)
|
||||
for camp in camp_obj.browse(cr, uid, camp_ids, context=context):
|
||||
if camp.mode == 'manual':
|
||||
# manual states are not processed automatically
|
||||
continue
|
||||
while True:
|
||||
if camp.mode in ('test_realtime','active'):
|
||||
workitem_ids = self.search(cr, uid, [('state', '=', 'todo'),
|
||||
('date','<=', time.strftime('%Y-%m-%d %H:%M:%S'))])
|
||||
elif camp.mode == 'test':
|
||||
workitem_ids = self.search(cr, uid, [('state', '=', 'todo')])
|
||||
else:
|
||||
# manual states are not processed automatically
|
||||
workitem_ids = []
|
||||
if workitem_ids:
|
||||
self.process(cr, uid, workitem_ids, context)
|
||||
else:
|
||||
domain = [('state', '=', 'todo'), ('date', '!=', False)]
|
||||
if camp.mode in ('test_realtime', 'active'):
|
||||
domain += [('date','<=', time.strftime('%Y-%m-%d %H:%M:%S'))]
|
||||
|
||||
workitem_ids = self.search(cr, uid, domain, context=context)
|
||||
if not workitem_ids:
|
||||
break
|
||||
|
||||
self.process(cr, uid, workitem_ids, context)
|
||||
return True
|
||||
|
||||
def preview(self, cr, uid, ids, context):
|
||||
res = {}
|
||||
wi_obj = self.browse(cr, uid, ids)[0]
|
||||
wi_obj = self.browse(cr, uid, ids[0], context)
|
||||
if wi_obj.activity_id.type == 'email':
|
||||
data_obj = self.pool.get('ir.model.data')
|
||||
data_id = data_obj._get_id(cr, uid, 'email_template', 'email_template_preview_form')
|
||||
view_id = 0
|
||||
if data_id:
|
||||
view_id = data_obj.browse(cr, uid, data_id, context=context).res_id
|
||||
res = {
|
||||
@@ -469,18 +651,17 @@ class marketing_campaign_workitem(osv.osv):
|
||||
'context': "{'template_id':%d,'rel_model_ref':%d}"%
|
||||
(wi_obj.activity_id.email_template_id.id,
|
||||
wi_obj.res_id)
|
||||
|
||||
}
|
||||
|
||||
elif wi_obj.activity_id.type == 'paper':
|
||||
datas = {'ids': [wi_obj.res_id],
|
||||
'model': wi_obj.object_id.model}
|
||||
res = {
|
||||
res = {
|
||||
'type' : 'ir.actions.report.xml',
|
||||
'report_name': wi_obj.activity_id.report_id.report_name,
|
||||
'datas' : datas,
|
||||
'nodestroy': True,
|
||||
}
|
||||
'nodestroy': True,
|
||||
}
|
||||
return res
|
||||
|
||||
marketing_campaign_workitem()
|
||||
@@ -491,16 +672,16 @@ class email_template(osv.osv):
|
||||
'object_name': lambda obj, cr, uid, context: context.get('object_id',False),
|
||||
}
|
||||
email_template()
|
||||
|
||||
|
||||
class email_template_preview(osv.osv_memory):
|
||||
_inherit = "email_template.preview"
|
||||
|
||||
|
||||
def _default_rel_model(self, cr, uid, context=None):
|
||||
if 'rel_model_ref' in context :
|
||||
return context['rel_model_ref']
|
||||
else :
|
||||
return False
|
||||
|
||||
|
||||
_defaults = {
|
||||
'rel_model_ref' : _default_rel_model
|
||||
}
|
||||
@@ -510,11 +691,11 @@ email_template_preview()
|
||||
class report_xml(osv.osv):
|
||||
_inherit = 'ir.actions.report.xml'
|
||||
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
|
||||
if not context:
|
||||
if context is None:
|
||||
context = {}
|
||||
if context and 'object_id' in context and context['object_id']:
|
||||
model = self.pool.get('ir.model').browse(cr, uid,
|
||||
context['object_id']).model
|
||||
object_id = context.get('object_id')
|
||||
if object_id:
|
||||
model = self.pool.get('ir.model').browse(cr, uid, object_id).model
|
||||
args.append(('model', '=', model))
|
||||
return super(report_xml, self).search(cr, uid, args, offset, limit, order, context, count)
|
||||
|
||||
|
||||
@@ -21,65 +21,9 @@
|
||||
<field name="object_id" select="1"/>
|
||||
<field name="mode"/>
|
||||
<field name="fixed_cost"/>
|
||||
<field name="partner_field_id"/>
|
||||
</group>
|
||||
<field name="activity_ids" nolabel = "1" colspan="4" default_get="{'object_id':object_id}">
|
||||
<form string="Activities">
|
||||
<group colspan="4" col="6">
|
||||
<separator string="Activity Definition" colspan="4"/>
|
||||
<separator string="Cost Control" colspan="2"/>
|
||||
<field name="name" select="1" />
|
||||
<field name="start"/>
|
||||
<field name="variable_cost" select="1"/>
|
||||
<field name="object_id" invisible="1"/>
|
||||
</group>
|
||||
<group colspan="2" col="2">
|
||||
<separator string="Condition" colspan="2"/>
|
||||
<field name="condition"/>
|
||||
</group>
|
||||
<group colspan="2" col="2">
|
||||
<separator string="Action" colspan="2"/>
|
||||
<field name="type" colspan="4"/>
|
||||
<group colspan="4" attrs="{'invisible':[('type','!=','email')]}" >
|
||||
<field name="email_template_id" attrs="{'required':[('type','=','email')]}" />
|
||||
</group>
|
||||
<group colspan="4" attrs="{'invisible':[('type','!=','paper')]}" >
|
||||
<field name="report_id" attrs="{'required':[('type','=','paper')]}"/>
|
||||
<field name="report_directory_id" attrs="{'required':[('type','=','paper')]}" />
|
||||
</group>
|
||||
<group colspan="4" attrs="{'invisible':[('type','!=','action')]}" >
|
||||
<field name="server_action_id" attrs="{'required':[('type','=','action')]}" domain="[('model_id','=',object_id)]" />
|
||||
</group>
|
||||
<group colspan="4" attrs="{'invisible':[('type','!=','subcampaign')]}" >
|
||||
<field name="subcampaign_id" attrs="{'required':[('type','=','subcampaign')]}" />
|
||||
<field name="subcampaign_segment_id" attrs="{'required':[('type','=','subcampaign')]}" />
|
||||
</group>
|
||||
</group>
|
||||
<newline/>
|
||||
<group colspan="4" col="4">
|
||||
<separator string="Transitions" colspan="4"/>
|
||||
<field name="to_ids" nolabel="1" colspan="2" mode="tree" default_get="{'type_id':'activity_from_id','activity_id':active_id or False}">
|
||||
<tree string="Outgoing Transitions" editable="bottom">
|
||||
<field name="activity_to_id"/>
|
||||
<field name="interval_nbr"/>
|
||||
<field name="interval_type"/>
|
||||
</tree>
|
||||
</field>
|
||||
<field name="from_ids" nolabel="1" colspan="2" mode="tree" default_get="{'type_id':'activity_to_id','activity_id':active_id or False}">
|
||||
<tree string="Incoming Transitions" editable="bottom">
|
||||
<field name="activity_from_id"/>
|
||||
<field name="interval_nbr"/>
|
||||
<field name="interval_type"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
</form>
|
||||
<tree string="Activities">
|
||||
<field name="name"/>
|
||||
<field name="start"/>
|
||||
<field name="condition"/>
|
||||
<field name="type"/>
|
||||
</tree>
|
||||
</field>
|
||||
<field name="activity_ids" nolabel = "1" colspan="4" default_get="{'default_object_id': object_id}" />
|
||||
<separator string="Status" colspan="4" />
|
||||
<group col="10" colspan="4">
|
||||
<field name="state" readonly="1" select="2" nolabel="1"/>
|
||||
@@ -117,7 +61,7 @@
|
||||
<field name="start" invisible="1"/>
|
||||
<field name="condition"/>
|
||||
</node>
|
||||
<arrow object="marketing.campaign.transition" source="activity_from_id" destination="activity_to_id" label="['interval_type']">
|
||||
<arrow object="marketing.campaign.transition" source="activity_from_id" destination="activity_to_id" label="['name']">
|
||||
<field name="activity_from_id"/>
|
||||
<field name="activity_to_id"/>
|
||||
<field name="interval_nbr"/>
|
||||
@@ -264,6 +208,8 @@
|
||||
======================
|
||||
Marketing Activities
|
||||
======================
|
||||
|
||||
these views are not intended to be used outside the campaign context.
|
||||
-->
|
||||
|
||||
<record model="ir.ui.view" id="view_marketing_campaign_activity_form">
|
||||
@@ -272,59 +218,60 @@
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Activities">
|
||||
|
||||
<group colspan="4" col="6">
|
||||
<separator string="Activity Definition" colspan="4"/>
|
||||
<separator string="Cost Control" colspan="2"/>
|
||||
<field name="name" select="1" />
|
||||
<field name="start"/>
|
||||
<field name="variable_cost" select="1"/>
|
||||
<field name="object_id" invisible="1"/>
|
||||
</group>
|
||||
<group colspan="2" col="2">
|
||||
<separator string="Condition" colspan="2"/>
|
||||
<field name="condition"/>
|
||||
</group>
|
||||
<group colspan="2" col="2">
|
||||
<separator string="Action"/>
|
||||
<field name="type" colspan="4"/>
|
||||
<group colspan="4" attrs="{'invisible':[('type','!=','email')]}" >
|
||||
<field name="email_template_id" attrs="{'required':[('type','=','email')]}" />
|
||||
</group>
|
||||
<group colspan="4" attrs="{'invisible':[('type','!=','paper')]}" >
|
||||
<field name="report_id" attrs="{'required':[('type','=','paper')]}" context="{'object_id':object_id}"/>
|
||||
<field name="report_directory_id" attrs="{'required':[('type','=','paper')]}" />
|
||||
</group>
|
||||
<group colspan="4" attrs="{'invisible':[('type','!=','action')]}" >
|
||||
<field name="server_action_id" attrs="{'required':[('type','=','action')]}" />
|
||||
</group>
|
||||
<group colspan="4" attrs="{'invisible':[('type','!=','subcampaign')]}" >
|
||||
<field name="subcampaign_id" attrs="{'required':[('type','=','subcampaign')]}" />
|
||||
<field name="subcampaign_segment_id" attrs="{'required':[('type','=','subcampaign')]}" />
|
||||
<field name="object_id" invisible="1"/>
|
||||
<separator string="Activity Definition" colspan="4"/>
|
||||
<field name="name" select="1" colspan='4' />
|
||||
<field name="signal"/>
|
||||
<field name="start"/>
|
||||
<field name="variable_cost" select="1"/>
|
||||
<newline/>
|
||||
|
||||
<separator string="Action" colspan="4"/>
|
||||
<group colspan='4' col='4'>
|
||||
<field name="condition" colspan='4'/>
|
||||
<field name="type" width='100'/>
|
||||
<group colspan='2' col='1'>
|
||||
<group attrs="{'invisible':[('type','!=','email')]}" >
|
||||
<field name="email_template_id" attrs="{'required':[('type','=','email')]}" />
|
||||
</group>
|
||||
<group attrs="{'invisible':[('type','!=','paper')]}" >
|
||||
<field name="report_id" attrs="{'required':[('type','=','paper')]}" context="{'object_id':object_id}"/>
|
||||
<field name="report_directory_id" attrs="{'required':[('type','=','paper')]}" />
|
||||
</group>
|
||||
<group attrs="{'invisible':[('type','!=','action')]}" >
|
||||
<field name="server_action_id" attrs="{'required':[('type','=','action')]}" domain="[('model_id','=',object_id)]" />
|
||||
</group>
|
||||
<group attrs="{'invisible':[('type','!=','subcampaign')]}" >
|
||||
<field name="subcampaign_id" attrs="{'required':[('type','=','subcampaign')]}" />
|
||||
<field name="subcampaign_segment_id" attrs="{'required':[('type','=','subcampaign')]}" />
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
<newline/>
|
||||
<group colspan="4" col="4">
|
||||
<separator string="Transitions" colspan="4"/>
|
||||
<field name="to_ids" nolabel="1" colspan="2" mode="tree" default_get="{'type_id':'activity_from_id','activity_id':active_id or False}">
|
||||
<tree string="Outgoing Transitions" editable="bottom">
|
||||
<field name="activity_to_id"/>
|
||||
<field name="interval_nbr"/>
|
||||
<field name="interval_type"/>
|
||||
</tree>
|
||||
</field>
|
||||
<field name="from_ids" nolabel="1" colspan="2" mode="tree" default_get="{'type_id':'activity_to_id','activity_id':active_id or False}">
|
||||
<tree string="Incoming Transitions" editable="bottom">
|
||||
<field name="activity_from_id"/>
|
||||
<field name="interval_nbr"/>
|
||||
<field name="interval_type"/>
|
||||
</tree>
|
||||
|
||||
<group colspan="4" col="2" expand="1">
|
||||
<separator string="Transitions" colspan="2"/>
|
||||
<field name="from_ids" nolabel="1" mode="tree" default_get="{'default_activity_to_id': active_id}">
|
||||
<tree string="Incoming Transitions" editable="bottom">
|
||||
<field name="activity_from_id"/>
|
||||
<field name='trigger'/>
|
||||
<field name="interval_nbr"/>
|
||||
<field name="interval_type"/>
|
||||
</tree>
|
||||
</field>
|
||||
<field name="to_ids" nolabel="1" mode="tree" default_get="{'default_activity_from_id': active_id}">
|
||||
<tree string="Outgoing Transitions" editable="bottom">
|
||||
<field name="activity_to_id"/>
|
||||
<field name='trigger'/>
|
||||
<field name="interval_nbr"/>
|
||||
<field name="interval_type"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record model="ir.ui.view" id="view_marketing_campaign_activity_tree">
|
||||
<field name="name">marketing.campaign.activity.tree</field>
|
||||
<field name="model">marketing.campaign.activity</field>
|
||||
@@ -332,7 +279,6 @@
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Activities">
|
||||
<field name="name" select="1"/>
|
||||
<field name="campaign_id" select="1"/>
|
||||
<field name="start"/>
|
||||
<field name="condition"/>
|
||||
<field name="type"/>
|
||||
@@ -340,16 +286,6 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_marketing_campaign_activity_form">
|
||||
<field name="name">Activities</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">marketing.campaign.activity</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="view_marketing_campaign_activity_tree"/>
|
||||
</record>
|
||||
|
||||
<!--menuitem id="menu_marketing_campaign_activity_form" parent="menu_marketing" action="action_marketing_campaign_activity_form" sequence="3" /-->
|
||||
|
||||
<!--
|
||||
======================
|
||||
@@ -423,7 +359,6 @@
|
||||
<field name="arch" type="xml">
|
||||
<search string="Marketing Campaign Activities">
|
||||
<filter icon="terp-gtk-go-back-rtl" string="To Do" name = "todo" domain="[('state','=','todo')]"/>
|
||||
<filter icon="terp-camera_test" string="In Progress" domain="[('state','=','inprogress')]"/>
|
||||
<filter icon="terp-emblem-important" string="Exception" domain="[('state','=','exception')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="segment_id" select="1"/>
|
||||
@@ -443,7 +378,7 @@
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_marketing_campaign_workitem">
|
||||
<field name="name">Campaign Activities</field>
|
||||
<field name="name">Campaign Activities (Workitems)</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">marketing.campaign.workitem</field>
|
||||
<field name="view_type">form</field>
|
||||
|
||||
@@ -22,16 +22,15 @@
|
||||
from osv import fields,osv
|
||||
|
||||
class res_partner(osv.osv):
|
||||
""" Inherits partner and adds CRM information in the partner form """
|
||||
_inherit = 'res.partner'
|
||||
|
||||
_columns = {
|
||||
'workitem_ids': fields.one2many('marketing.campaign.workitem', 'partner_id',\
|
||||
'Workitems', readonly=True),
|
||||
|
||||
}
|
||||
'workitem_ids': fields.one2many('marketing.campaign.workitem',
|
||||
'partner_id', 'Workitems',
|
||||
readonly=True),
|
||||
}
|
||||
|
||||
res_partner()
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
"name" : "marketing_campaign_crm_demo",
|
||||
"version" : "1.0",
|
||||
"depends" : ["marketing_campaign",
|
||||
"crm",
|
||||
],
|
||||
"author" : "OpenERP SA",
|
||||
"category": 'Generic Modules/Marketing',
|
||||
"description": """Demo data for the module marketing_campaign.""",
|
||||
'website': 'http://www.openerp.com',
|
||||
'init_xml': [],
|
||||
'update_xml': [],
|
||||
'demo_xml': [
|
||||
'marketing_campaign_demo.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'active': False,
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
+4
-3
@@ -19,7 +19,7 @@
|
||||
<field eval=""""[]"""" name="domain"/>
|
||||
<field name="parent_id" ref="document_directory_marketingcampaign"/>
|
||||
<field eval=""""ressource"""" name="type"/>
|
||||
<field name="ressource_type_id" ref="model_marketing_campaign"/>
|
||||
<field name="ressource_type_id" ref="marketing_campaign.model_marketing_campaign"/>
|
||||
</record>
|
||||
|
||||
<!-- Email tempalte -->
|
||||
@@ -163,7 +163,7 @@
|
||||
<field name="type">ir.actions.report.xml</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="report_name">crm.lead.demo</field>
|
||||
<field name="report_rml">marketing_campaign/report/crm_lead_mc_demo_report.rml</field>
|
||||
<field name="report_rml">marketing_campaign_crm_demo/crm_lead_mc_demo_report.rml</field>
|
||||
<field name="report_type">pdf</field>
|
||||
</record>
|
||||
|
||||
@@ -171,6 +171,7 @@
|
||||
<record id="marketing_campaign_openerpondemandfreetrial0" model="marketing.campaign">
|
||||
<field name="name">OpenERP OnDemand Free Trial 2010</field>
|
||||
<field name="object_id" ref="crm.model_crm_lead"/>
|
||||
<field name="partner_field_id" ref="crm.field_crm_lead_partner_id"/>
|
||||
</record>
|
||||
|
||||
<!-- Activity -->
|
||||
@@ -303,4 +304,4 @@
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
</openerp>
|
||||
@@ -14,29 +14,12 @@
|
||||
<field name="type">form</field>
|
||||
<field name="inherit_id" ref="marketing_campaign.view_marketing_campaign_activity_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="type" position="after">
|
||||
<group colspan="2" ><!--attrs="{'invisible':[('type','!=','mailchimp')]}"-->
|
||||
<field name="mailchimp_account_id" attrs="{'required':[('type','=','mailchimp')]}" domain="[('state','=','approved')]" on_change="onchange_mailchimp(mailchimp_account_id)"/>
|
||||
<field name="mailchimp_list" attrs="{'required':[('type','=','mailchimp')]}" on_change="onchange_mailchimp_list(mailchimp_account_id,mailchimp_list)"/>
|
||||
</group>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
|
||||
<record model="ir.ui.view" id="view_marketing_campaign_form_inherit">
|
||||
<field name="name">marketing.campaign.form.inherit</field>
|
||||
<field name="model">marketing.campaign</field>
|
||||
<field name="type">form</field>
|
||||
<field name="inherit_id" ref="marketing_campaign.view_marketing_campaign_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="type" position="after">
|
||||
<xpath expr='//field[@name="type"]/following-sibling::group' position='inside'>
|
||||
<group colspan="2" attrs="{'invisible':[('type','!=','mailchimp')]}">
|
||||
<field name="mailchimp_account_id" attrs="{'required':[('type','=','mailchimp')]}" domain="[('state','=','approved')]" on_change="onchange_mailchimp(mailchimp_account_id)"/>
|
||||
<field name="mailchimp_list" attrs="{'required':[('type','=','mailchimp')]}" on_change="onchange_mailchimp_list(mailchimp_account_id,mailchimp_list)"/>
|
||||
</group>
|
||||
</field>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
+37
-19
@@ -20,6 +20,7 @@
|
||||
##############################################################################
|
||||
|
||||
from mx import DateTime
|
||||
from datetime import datetime, timedelta
|
||||
from osv import osv, fields
|
||||
from tools.translate import _
|
||||
import ir
|
||||
@@ -99,8 +100,8 @@ class mrp_routing_workcenter(osv.osv):
|
||||
'name': fields.char('Name', size=64, required=True),
|
||||
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of routing workcenters."),
|
||||
'cycle_nbr': fields.float('Number of Cycles', required=True,
|
||||
help="Time in hours for doing one cycle."),
|
||||
'hour_nbr': fields.float('Number of Hours', required=True, help="Cost per hour"),
|
||||
help="Number of operations this workcenter can do."),
|
||||
'hour_nbr': fields.float('Number of Hours', required=True, help="Time in hours for doing one cycle."),
|
||||
'routing_id': fields.many2one('mrp.routing', 'Parent Routing', select=True, ondelete='cascade',
|
||||
help="Routing indicates all the workcenters used, for how long and/or cycles." \
|
||||
"If Routing is indicated then,the third tab of a production order (workcenters) will be automatically pre-completed."),
|
||||
@@ -372,8 +373,6 @@ def rounding(f, r):
|
||||
|
||||
class many2many_domain(fields.many2many):
|
||||
def set(self, cr, obj, id, name, values, user=None, context=None):
|
||||
if not values:
|
||||
return
|
||||
return super(many2many_domain, self).set(cr, obj, id, name, values, user=user,
|
||||
context=context)
|
||||
|
||||
@@ -392,8 +391,6 @@ class many2many_domain(fields.many2many):
|
||||
|
||||
class one2many_domain(fields.one2many):
|
||||
def set(self, cr, obj, id, field, values, user=None, context=None):
|
||||
if not values:
|
||||
return
|
||||
return super(one2many_domain, self).set(cr, obj, id, field, values,
|
||||
user=user, context=context)
|
||||
|
||||
@@ -416,7 +413,6 @@ class mrp_production(osv.osv):
|
||||
_name = 'mrp.production'
|
||||
_description = 'Manufacturing Order'
|
||||
_date_name = 'date_planned'
|
||||
_log_create = True
|
||||
|
||||
def _production_calc(self, cr, uid, ids, prop, unknow_none, context={}):
|
||||
""" Calculates total hours and total no. of cycles for a production order.
|
||||
@@ -485,10 +481,10 @@ class mrp_production(osv.osv):
|
||||
'picking_id': fields.many2one('stock.picking', 'Picking list', readonly=True,
|
||||
help="This is the internal picking list that brings the finished product to the production plan"),
|
||||
'move_prod_id': fields.many2one('stock.move', 'Move product', readonly=True),
|
||||
'move_lines': many2many_domain('stock.move', 'mrp_production_move_ids', 'production_id', 'move_id', 'Products to Consumme', domain=[('state','not in', ('done', 'cancel'))]),
|
||||
'move_lines2': many2many_domain('stock.move', 'mrp_production_move_ids', 'production_id', 'move_id', 'Consummed Products', domain=[('state','in', ('done', 'cancel'))]),
|
||||
'move_created_ids': one2many_domain('stock.move', 'production_id', 'Moves Created', domain=[('state','not in', ('done', 'cancel'))]),
|
||||
'move_created_ids2': one2many_domain('stock.move', 'production_id', 'Moves Created', domain=[('state','in', ('done', 'cancel'))]),
|
||||
'move_lines': many2many_domain('stock.move', 'mrp_production_move_ids', 'production_id', 'move_id', 'Products to Consumme', domain=[('state','not in', ('done', 'cancel'))], states={'done':[('readonly',True)]}),
|
||||
'move_lines2': many2many_domain('stock.move', 'mrp_production_move_ids', 'production_id', 'move_id', 'Consummed Products', domain=[('state','in', ('done', 'cancel'))], readonly=True),
|
||||
'move_created_ids': one2many_domain('stock.move', 'production_id', 'Moves Created', domain=[('state','not in', ('done', 'cancel'))], states={'done':[('readonly',True)]}),
|
||||
'move_created_ids2': one2many_domain('stock.move', 'production_id', 'Moves Created', domain=[('state','in', ('done', 'cancel'))], readonly=True),
|
||||
'product_lines': fields.one2many('mrp.production.product.line', 'production_id', 'Scheduled goods'),
|
||||
'workcenter_lines': fields.one2many('mrp.production.workcenter.line', 'production_id', 'Work Centers Utilisation'),
|
||||
'state': fields.selection([('draft','Draft'),('picking_except', 'Picking Exception'),('confirmed','Waiting Goods'),('ready','Ready to Produce'),('in_production','In Production'),('cancel','Cancelled'),('done','Done')],'State', readonly=True,
|
||||
@@ -508,7 +504,18 @@ class mrp_production(osv.osv):
|
||||
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.production', context=c),
|
||||
}
|
||||
_order = 'date_planned asc, priority desc';
|
||||
|
||||
|
||||
def _check_qty(self, cr, uid, ids):
|
||||
orders = self.browse(cr, uid, ids)
|
||||
for order in orders:
|
||||
if order.product_qty <= 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
_constraints = [
|
||||
(_check_qty, 'Order quantity cannot be negative or zero !', ['product_qty']),
|
||||
]
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
productions = self.read(cr, uid, ids, ['state'])
|
||||
unlink_ids = []
|
||||
@@ -638,15 +645,23 @@ class mrp_production(osv.osv):
|
||||
""" Changes the production state to Ready and location id of stock move.
|
||||
@return: True
|
||||
"""
|
||||
for (id,name) in self.name_get(cr, uid, ids):
|
||||
message = _('Manufacturing Order ') + " '" + name + "' "+ _("is ready to produce.")
|
||||
self.log(cr, uid, id, message)
|
||||
move_obj = self.pool.get('stock.move')
|
||||
self.write(cr, uid, ids, {'state': 'ready'})
|
||||
for production in self.browse(cr, uid, ids):
|
||||
|
||||
for (production_id,name) in self.name_get(cr, uid, ids):
|
||||
production = self.browse(cr, uid, production_id)
|
||||
if production.move_prod_id:
|
||||
move_obj.write(cr, uid, [production.move_prod_id.id],
|
||||
{'location_id': production.location_dest_id.id})
|
||||
|
||||
message = ("%s %s %s %s %s %s") % (
|
||||
_('Manufacturing Order '),
|
||||
name,
|
||||
_("scheduled the"),
|
||||
datetime.strptime(production.date_planned,'%Y-%m-%d %H:%M:%S').strftime('%Y-%m-%d'),
|
||||
_("for"),
|
||||
production.product_id.name)
|
||||
self.log(cr, uid, production_id, message)
|
||||
return True
|
||||
|
||||
def action_production_end(self, cr, uid, ids):
|
||||
@@ -680,9 +695,10 @@ class mrp_production(osv.osv):
|
||||
@param production_mode: specify production mode (consume/consume&produce).
|
||||
@return: True
|
||||
"""
|
||||
|
||||
stock_mov_obj = self.pool.get('stock.move')
|
||||
production = self.browse(cr, uid, production_id)
|
||||
|
||||
|
||||
raw_product_todo = []
|
||||
final_product_todo = []
|
||||
|
||||
@@ -692,6 +708,7 @@ class mrp_production(osv.osv):
|
||||
continue
|
||||
produced_qty += produced_product.product_qty
|
||||
|
||||
|
||||
if production_mode in ['consume','consume_produce']:
|
||||
consumed_products = {}
|
||||
for consumed_product in production.move_lines2:
|
||||
@@ -700,12 +717,13 @@ class mrp_production(osv.osv):
|
||||
if not consumed_products.get(consumed_product.product_id.id, False):
|
||||
consumed_products[consumed_product.product_id.id] = 0
|
||||
consumed_products[consumed_product.product_id.id] -= consumed_product.product_qty
|
||||
|
||||
|
||||
for raw_product in production.move_lines:
|
||||
for f in production.product_lines:
|
||||
if f.product_id.id==raw_product.product_id.id:
|
||||
consumed_qty = consumed_products.get(raw_product.product_id.id, 0)
|
||||
rest_qty = production_qty * f.product_qty / production.product_qty - consumed_qty
|
||||
|
||||
if rest_qty > 0:
|
||||
stock_mov_obj.action_consume(cr, uid, [raw_product.id], rest_qty, production.location_src_id.id, context=context)
|
||||
|
||||
@@ -854,7 +872,7 @@ class mrp_production(osv.osv):
|
||||
'company_id': production.company_id.id,
|
||||
}
|
||||
res_final_id = move_obj.create(cr, uid, data)
|
||||
|
||||
|
||||
self.write(cr, uid, [production.id], {'move_created_ids': [(6, 0, [res_final_id])]})
|
||||
moves = []
|
||||
for line in production.product_lines:
|
||||
|
||||
+71
-15
@@ -67,16 +67,38 @@
|
||||
<field name="group_id" select="1"/>
|
||||
<field name="composition" select="1"/>
|
||||
<separator colspan="4" string="Description"/>
|
||||
<field colspan="4" name="description"/>
|
||||
<field colspan="4" name="description" nolabel="1"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_mrp_property_search" model="ir.ui.view">
|
||||
<field name="name">mrp.property.search</field>
|
||||
<field name="model">mrp.property</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search">
|
||||
<group col='15' colspan='4'>
|
||||
<field name="name"/>
|
||||
<field name="group_id" widget="selection" />
|
||||
<field name="composition"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By..." colspan="4" col="20">
|
||||
<filter string="Property Group" icon="terp-personal" domain="[]" context="{'group_by':'group_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="mrp_property_action" model="ir.actions.act_window">
|
||||
<field name="name">Properties</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.property</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="view_mrp_property_search"/>
|
||||
</record>
|
||||
<menuitem name="Master Bill of Materials"
|
||||
id="menu_mrp_property"
|
||||
@@ -105,6 +127,9 @@
|
||||
<tree string="Work Center">
|
||||
<field name="code"/>
|
||||
<field name="name"/>
|
||||
<field name="resource_id"/>
|
||||
<field name="resource_type"/>
|
||||
<field name="company_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
@@ -148,12 +173,37 @@
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Search Views -->
|
||||
|
||||
<record id="view_mrp_workcenter_search" model="ir.ui.view">
|
||||
<field name="name">mrp.workcenter.search</field>
|
||||
<field name="model">mrp.workcenter</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search for mrp workcenter">
|
||||
<group col='15' colspan='4'>
|
||||
<field name="code"/>
|
||||
<field name="name"/>
|
||||
<field name="resource_type"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By..." colspan="4" col="20" groups="base.group_extended">
|
||||
<filter string="Type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'resource_type'}"/>
|
||||
<filter string="Company" icon="terp-go-home" domain="[]" context="{'group_by':'company_id'}"/>
|
||||
<filter string="Resource" icon="terp-personal" domain="[]" context="{'group_by':'resource_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_workcenter_action" model="ir.actions.act_window">
|
||||
<field name="name">Work Centers</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.workcenter</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="mrp_workcenter_tree_view"/>
|
||||
<field name="search_view_id" ref="view_mrp_workcenter_search"/>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
@@ -186,7 +236,8 @@
|
||||
<field name="workcenter_id" select="1"/>
|
||||
<field name="cycle_nbr"/>
|
||||
<field name="hour_nbr"/>
|
||||
<field colspan="4" name="note"/>
|
||||
<separator colspan="4" string="Description"/>
|
||||
<field colspan="4" name="note" nolabel="1"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
@@ -298,15 +349,22 @@
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Bill Of Material">
|
||||
<group col='4' colspan='4'>
|
||||
<field name="name"/>
|
||||
<field name="code" string="Reference"/>
|
||||
<field name="product_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="name"/>
|
||||
<field name="code" string="Reference"/>
|
||||
<field name="product_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By" colspan="4" col="8" groups="base.group_extended">
|
||||
<filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/>
|
||||
<filter string="Routing" icon="terp-stock_align_left_24" domain="[]" context="{'group_by':'routing_id'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string='Default UOM' icon="terp-mrp" domain="[]" context="{'group_by' : 'product_uom'}" />
|
||||
<separator orientation="vertical"/>
|
||||
<filter string='Type' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'type'}" />
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_start'}"/>
|
||||
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
@@ -325,10 +383,11 @@
|
||||
<field name="product_id"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="product_uom"/>
|
||||
<field name="method"/>
|
||||
<field name="type"/>
|
||||
<field name="method" groups="base.group_extended"/>
|
||||
<field name="routing_id" groups="base.group_extended"/>
|
||||
<field name="date_start"/>
|
||||
<field name="date_stop"/>
|
||||
<field name="date_start" groups="base.group_extended"/>
|
||||
<field name="date_stop" groups="base.group_extended"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
@@ -405,7 +464,8 @@
|
||||
<field colspan="1" name="indice"/>
|
||||
<field colspan="1" name="date"/>
|
||||
<field name="author_id" readonly="1"/>
|
||||
<field colspan="4" name="description"/>
|
||||
<separator colspan="4" string="Description"/>
|
||||
<field colspan="4" name="description" nolabel="1"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
@@ -589,11 +649,7 @@
|
||||
<field name="product_qty" string="Qty"/>
|
||||
<field name="product_uom" string="UOM"/>
|
||||
<field name="location_id" string="Source Loc."/>
|
||||
<field name="state" invisible="1"/>
|
||||
<button name="%(stock.move_consume)d"
|
||||
string="Consume Products" type="action"
|
||||
icon="gtk-go-forward" context="{'consume': True}"
|
||||
states="draft,waiting,confirmed,assigned" />
|
||||
<field name="state" invisible="1"/>
|
||||
<button name="%(stock.move_scrap)d"
|
||||
string="Scrap Products" type="action"
|
||||
icon="gtk-convert" context="{'scrap': True}"
|
||||
|
||||
+28
-2
@@ -24,17 +24,43 @@ 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={}):
|
||||
""" 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, False)
|
||||
|
||||
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
|
||||
|
||||
res = {}
|
||||
res.update({'stock_account_input': stock_input_acc})
|
||||
res.update({'stock_account_output': stock_output_acc})
|
||||
res.update({'stock_journal': journal_id})
|
||||
|
||||
return res
|
||||
|
||||
|
||||
_columns = {
|
||||
"bom_ids": fields.one2many('mrp.bom', 'product_id','Bill of Materials'),
|
||||
}
|
||||
|
||||
def do_change_standard_price(self, cr, uid, ids, datas, context={}):
|
||||
""" Changes the Standard Price of Product and parent products 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:
|
||||
"""
|
||||
#TODO : TO Check
|
||||
res = super(product_product, self).do_change_standard_price(cr, uid, ids, datas, context=context)
|
||||
bom_obj = self.pool.get('mrp.bom')
|
||||
def _compute_price(bom):
|
||||
|
||||
@@ -27,3 +27,4 @@
|
||||
"access_mrp_production_order","mrp.production.order","model_mrp_production_order","mrp.group_mrp_user",1,0,0,0
|
||||
"access_report_workcenter_load","report.workcenter.load","model_report_workcenter_load","mrp.group_mrp_manager",1,0,0,0
|
||||
"access_report_mrp_inout","report.mrp.inout","model_report_mrp_inout","mrp.group_mrp_manager",1,0,0,0
|
||||
"access_product_product_manager","product.product manager","model_product_product","mrp.group_mrp_manager",1,1,1,1
|
||||
|
||||
|
@@ -20,6 +20,9 @@
|
||||
type: product
|
||||
uom_id: product_uom_litre0
|
||||
uom_po_id: product_uom_litre0
|
||||
property_stock_inventory: stock.location_inventory
|
||||
property_stock_procurement: stock.location_procurement
|
||||
property_stock_production: stock.location_production
|
||||
-
|
||||
I create record for product Orange.
|
||||
-
|
||||
@@ -35,6 +38,9 @@
|
||||
type: product
|
||||
uom_id: product.product_uom_kgm
|
||||
uom_po_id: product.product_uom_kgm
|
||||
property_stock_inventory: stock.location_inventory
|
||||
property_stock_procurement: stock.location_procurement
|
||||
property_stock_production: stock.location_production
|
||||
-
|
||||
I create record for product Sugar.
|
||||
-
|
||||
@@ -50,6 +56,9 @@
|
||||
type: product
|
||||
uom_id: product.product_uom_kgm
|
||||
uom_po_id: product.product_uom_kgm
|
||||
property_stock_inventory: stock.location_inventory
|
||||
property_stock_procurement: stock.location_procurement
|
||||
property_stock_production: stock.location_production
|
||||
-
|
||||
I create record for product Water.
|
||||
-
|
||||
@@ -61,6 +70,9 @@
|
||||
type: consu
|
||||
uom_id: product_uom_litre0
|
||||
uom_po_id: product_uom_litre0
|
||||
property_stock_inventory: stock.location_inventory
|
||||
property_stock_procurement: stock.location_procurement
|
||||
property_stock_production: stock.location_production
|
||||
-
|
||||
I define the BoM to produce an orange juice.
|
||||
-
|
||||
|
||||
@@ -221,8 +221,7 @@
|
||||
-
|
||||
!record {model: stock.partial.picking, id: stock_partial_picking0}:
|
||||
date: '2010-04-30 16:53:36'
|
||||
partner_id: base.res_partner_maxtor
|
||||
address_id: base.res_partner_address_wong
|
||||
|
||||
-
|
||||
I make my picking done.
|
||||
-
|
||||
@@ -231,8 +230,6 @@
|
||||
picking_ids = pick_obj.search(cr, uid, [('address_id.name','=','Wong'),('state','=','assigned')])
|
||||
partial = self.browse(cr, uid, 1, 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
|
||||
}
|
||||
for pick in pick_obj.browse(cr, uid, picking_ids):
|
||||
@@ -260,8 +257,7 @@
|
||||
-
|
||||
!record {model: stock.partial.picking, id: stock_partial_picking0}:
|
||||
date: '2010-04-30 16:53:36'
|
||||
partner_id: base.res_partner_maxtor
|
||||
address_id: base.res_partner_address_wong
|
||||
|
||||
-
|
||||
I make my picking done.
|
||||
-
|
||||
@@ -270,8 +266,6 @@
|
||||
picking_ids = pick_obj.search(cr, uid, [('address_id.name','=','Tang'),('state','=','assigned')])
|
||||
partial = self.browse(cr, uid, 1, 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
|
||||
}
|
||||
for pick in pick_obj.browse(cr, uid, picking_ids):
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
<field name="product_qty"/>
|
||||
<newline/>
|
||||
<group col="2" colspan="4">
|
||||
<button icon='gtk-cancel' special="cancel"
|
||||
string="Cancel" />
|
||||
<button icon='gtk-close' special="cancel"
|
||||
string="Close" />
|
||||
<button name="change_prod_qty" string="Validate"
|
||||
colspan="1" type="object" icon="gtk-ok" />
|
||||
</group>
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
<field name="number"/>
|
||||
<newline/>
|
||||
<group col="2" colspan="4">
|
||||
<button icon='gtk-cancel' special="cancel"
|
||||
string="Cancel" />
|
||||
<button icon='gtk-close' special="cancel"
|
||||
string="Close" />
|
||||
<button name="print_report" string="Print"
|
||||
colspan="1" type="object" icon="gtk-ok" />
|
||||
</group>
|
||||
@@ -27,7 +27,7 @@
|
||||
src_model="product.product"
|
||||
view_mode="form"
|
||||
target="new"
|
||||
key2="client_action_multi"
|
||||
key2="client_print_multi"
|
||||
id="action_view_mrp_product_price_wizard"/>
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -43,6 +43,7 @@ class mrp_product_produce(osv.osv_memory):
|
||||
context['active_id'], context=context)
|
||||
done = 0.0
|
||||
for move in prod.move_created_ids2:
|
||||
if not move.scraped:
|
||||
done += move.product_qty
|
||||
return (prod.product_qty - done) or prod.product_qty
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
<separator string="" colspan="4" />
|
||||
<label string="" colspan="2" />
|
||||
<group col="2" colspan="1">
|
||||
<button icon='gtk-cancel' special="cancel"
|
||||
string="Cancel" />
|
||||
<button icon='gtk-close' special="cancel"
|
||||
string="Close" />
|
||||
<button name="do_produce" string="Confirm"
|
||||
colspan="1" type="object" icon="gtk-ok" />
|
||||
</group>
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
<field name="measure_unit"/>
|
||||
<newline/>
|
||||
<group col="2" colspan="4">
|
||||
<button icon='gtk-cancel' special="cancel"
|
||||
string="Cancel" />
|
||||
<button icon='gtk-close' special="cancel"
|
||||
string="Close" />
|
||||
<button name="print_report" string="Print"
|
||||
colspan="1" type="object" icon="gtk-ok" />
|
||||
</group>
|
||||
@@ -28,8 +28,8 @@
|
||||
res_model="mrp.workcenter.load"
|
||||
src_model="mrp.workcenter"
|
||||
view_mode="form"
|
||||
target="new"
|
||||
key2="client_action_multi"
|
||||
target="new"
|
||||
key2="client_print_multi"
|
||||
id="action_mrp_workcenter_load_wizard"/>
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -72,10 +72,10 @@
|
||||
<group colspan="8" col="8">
|
||||
<field name="state"/>
|
||||
<button name="button_draft" string="Set Draft" states="cancel" icon="gtk-convert"/>
|
||||
<button name="button_start_working" string="Start" states="draft" icon="gtk-execute"/>
|
||||
<button name="button_start_working" string="Start" states="draft" icon="gtk-go-forward"/>
|
||||
<button name="button_resume" string="Resume" states="pause" icon="gtk-media-pause"/>
|
||||
<button name="button_cancel" string="Cancel" states="draft,startworking" icon="gtk-cancel"/>
|
||||
<button name="button_pause" string="Pause" states="startworking" icon="gtk-execute"/>
|
||||
<button name="button_pause" string="Pause" states="startworking" icon="gtk-media-pause"/>
|
||||
<button name="button_done" string="Finished" states="startworking" icon="gtk-ok"/>
|
||||
</group>
|
||||
</page>
|
||||
@@ -89,16 +89,33 @@
|
||||
<field name="model">mrp.production.workcenter.line</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Work Orders">
|
||||
<group col='6' colspan='4'>
|
||||
<field name="name"/>
|
||||
<field name="workcenter_id"/>
|
||||
<field name="production_id"/>
|
||||
</group>
|
||||
<search string="Search Work Orders">
|
||||
<group col='9' colspan='4'>
|
||||
<filter icon="terp-document-new" string="Draft"
|
||||
domain="[('state','=','draft')]"/>
|
||||
<filter icon="terp-check" string="In Progress" name="Current"
|
||||
default="1"
|
||||
domain="[('state','=','startworking')]"/>
|
||||
<filter icon="terp-gtk-media-pause" string="Pending"
|
||||
domain="[('state','=','pause')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter icon="terp-gnome-cpu-frequency-applet+" string="Late"
|
||||
domain="['&', ('date_planned::date','<', current_date), ('state', 'in', ('draft', 'confirmed', 'ready'))]"
|
||||
help="Production started late" />
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name"/>
|
||||
<field name="workcenter_id" widget="selection"/>
|
||||
<field name="production_id" />
|
||||
<field name="state" />
|
||||
<field name="date_planned" widget="date"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By" colspan="10" col="8" groups="base.group_extended">
|
||||
<filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product'}"/>
|
||||
<filter string="Workcenter" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'workcenter_id'}"/>
|
||||
<filter string="Production" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'production_id'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_planned'}"/>
|
||||
</group>
|
||||
</search>
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
'mrp_repair_report.xml',
|
||||
],
|
||||
'demo_xml': [],
|
||||
'test': ['test/test_mrp_repair.yml'],
|
||||
'installable': True,
|
||||
'active': False,
|
||||
'certificate': '0060814381277',
|
||||
|
||||
@@ -344,7 +344,7 @@ class mrp_repair(osv.osv):
|
||||
'origin': invoice.origin+', '+repair.name,
|
||||
'comment':(comment and (invoice.comment and invoice.comment+"\n"+comment or comment)) or (invoice.comment and invoice.comment or ''),
|
||||
}
|
||||
invoice_obj.write(cr, uid, [inv_id], invoice_vals, context=context)
|
||||
inv_obj.write(cr, uid, [inv_id], invoice_vals, context=context)
|
||||
else:
|
||||
if not repair.partner_id.property_account_receivable:
|
||||
raise osv.except_osv(_('Error !'), _('No account defined for partner "%s".') % repair.partner_id.name )
|
||||
|
||||
@@ -100,8 +100,8 @@
|
||||
<group col="13" colspan="4">
|
||||
<field name="state"/>
|
||||
<button name="repair_confirm" states="draft" string="Confirm Repair" icon="gtk-apply"/>
|
||||
<button name="repair_ready" states="confirmed" string="Start Repair" icon="gtk-execute"/>
|
||||
<button name="action_repair_start" states="ready" string="Start Repair" icon="gtk-execute"/>
|
||||
<button name="repair_ready" states="confirmed" string="Start Repair" icon="gtk-go-forward"/>
|
||||
<button name="action_repair_start" states="ready" string="Start Repair" icon="gtk-go-forward"/>
|
||||
<button name="action_repair_end" states="under_repair" string="End Repair" icon="gtk-ok"/>
|
||||
<button name="invoice_recreate" states="invoice_except" string="Recreate Invoice" icon="gtk-convert"/>
|
||||
<button name="invoice_corrected" states="invoice_except" string="Invoice Corrected" icon="gtk-apply"/>
|
||||
@@ -179,26 +179,30 @@
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Reair Orders">
|
||||
<group col='4' colspan='4'>
|
||||
<field name="name" />
|
||||
<field name="product_id" />
|
||||
<filter icon="terp-document-new" string="Quotations" domain="[('state','=','draft')]"/>
|
||||
<filter icon="terp-check" string="Confirmed" domain="[('state','=', 'confirmed)]" name="current" />
|
||||
<filter icon="terp-emblem-important" string="Ready To Repair" domain="[('state','=','ready')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter icon="terp-dolar" string="invoiced" domain="[('state','=','2binvoiced')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name"/>
|
||||
<field name="product_id"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="state" />
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By..." colspan="10" col="8" groups="base.group_extended">
|
||||
<filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/>
|
||||
<filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Partner" icon="terp-personal" domain="[]" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'guarantee_limit'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_repair_order_form" model="ir.actions.act_window">
|
||||
<field name="name">New Repair</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.repair</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form,tree</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="action_repair_order_tree" model="ir.actions.act_window">
|
||||
<field name="name">Repair Orders</field>
|
||||
@@ -207,49 +211,9 @@
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="view_repair_order_form_filter"/>
|
||||
</record>
|
||||
</record>
|
||||
|
||||
<record id="action_repair_quotation_tree" model="ir.actions.act_window">
|
||||
<field name="name">Repairs in quotation</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.repair</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('state','=','draft')]</field>
|
||||
<field name="filter" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="action_repair_progress_tree" model="ir.actions.act_window">
|
||||
<field name="name">Repairs in progress</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.repair</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('state','=','under_repair')]</field>
|
||||
<field name="filter" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="action_repair_ready_tree" model="ir.actions.act_window">
|
||||
<field name="name">Repairs Ready to Start</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.repair</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('state','!=','draft'),('state','!=','under_repair'),('state','!=','2binvoiced'),('state','!=','invoice_except'),('state','!=','done'),('state','!=','cancel'),]</field>
|
||||
<field name="filter" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="action_repair_2binvoiced_tree" model="ir.actions.act_window">
|
||||
<field name="name">Repairs to be invoiced</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.repair</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('state','=','2binvoiced')]</field>
|
||||
<field name="filter" eval="True"/>
|
||||
</record>
|
||||
|
||||
<menuitem action="action_repair_order_tree" id="menu_repair_order" parent="mrp.menu_mrp_manufacturing" name="Repairs" sequence="50"/>
|
||||
<menuitem action="action_repair_order_tree" id="menu_repair_order" parent="mrp.menu_mrp_manufacturing" name="Repair Orders" sequence="50"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
- |
|
||||
In order to test "mrp_repair" module, I start with creating repairt order, confirm it, and start repair.
|
||||
|
||||
- |
|
||||
Given that I have already stock move line created.
|
||||
-
|
||||
!record {model: stock.move, id: stock_move_pcbasicpc0}:
|
||||
company_id: base.main_company
|
||||
date: '2010-06-24 20:10:28'
|
||||
date_expected: '2010-06-24 20:10:55'
|
||||
date_planned: '2010-06-24 20:10:28'
|
||||
location_dest_id: stock.stock_location_stock
|
||||
location_id: stock.stock_location_stock
|
||||
name: '[PC1] Basic PC'
|
||||
product_id: product.product_product_pc1
|
||||
product_qty: 1.0
|
||||
product_uom: product.product_uom_unit
|
||||
product_uos_qty: 1.0
|
||||
|
||||
- |
|
||||
I start by creating new Repair order for "Basic Pc" product.
|
||||
-
|
||||
!record {model: mrp.repair, id: mrp_repair_rma0}:
|
||||
address_id: base.res_partner_address_1
|
||||
guarantee_limit: '2010-06-24'
|
||||
invoice_method: 'after_repair'
|
||||
partner_invoice_id: base.res_partner_address_1
|
||||
location_dest_id: stock.stock_location_14
|
||||
location_id: stock.stock_location_14
|
||||
move_id: 'stock_move_pcbasicpc0'
|
||||
name: RMA00004
|
||||
operations:
|
||||
- location_dest_id: stock.location_production
|
||||
location_id: stock.stock_location_stock
|
||||
name: '[HDD1] HDD Seagate 7200.8 80GB'
|
||||
price_unit: 50.0
|
||||
product_id: product.product_product_hdd1
|
||||
product_uom: product.product_uom_unit
|
||||
product_uom_qty: 1.0
|
||||
state: draft
|
||||
to_invoice: 1
|
||||
type: add
|
||||
partner_id: base.res_partner_9
|
||||
product_id: product.product_product_pc1
|
||||
|
||||
- |
|
||||
I check that Repair order is in "Draft" state.
|
||||
-
|
||||
!assert {model: mrp.repair, id: mrp_repair_rma0}:
|
||||
- state == 'draft'
|
||||
|
||||
- |
|
||||
I confirm This Repair order.
|
||||
-
|
||||
!workflow {model: mrp.repair, action: repair_confirm, ref: mrp_repair_rma0}
|
||||
|
||||
- |
|
||||
I start the repairing process by click on "Start Repair" Button.
|
||||
-
|
||||
!workflow {model: mrp.repair, action: repair_ready, ref: mrp_repair_rma0}
|
||||
|
||||
- |
|
||||
I check that state is "Under Repair".
|
||||
-
|
||||
!assert {model: mrp.repair, id: mrp_repair_rma0}:
|
||||
- state == 'under_repair'
|
||||
- |
|
||||
Repairing Process for product is Done and I End Repair process by click on "End Repair" button.
|
||||
-
|
||||
!workflow {model: mrp.repair, action: action_repair_end, ref: mrp_repair_rma0}
|
||||
- |
|
||||
I select invoiced after repair option in this "RMA00004" Repair order.
|
||||
so I create Invoice by click on "Make Invoice" wizard.
|
||||
-
|
||||
!record {model: mrp.repair.make_invoice, id: mrp_repair_make_invoice_0}:
|
||||
group: 1
|
||||
- |
|
||||
I click on "Create Invoice" button of this wizard to make invoice.
|
||||
-
|
||||
!python {model: mrp.repair.make_invoice}: |
|
||||
self.make_invoices(cr, uid, [ref("mrp_repair_make_invoice_0")], {"active_ids": [ref("mrp_repair.mrp_repair_rma0")]})
|
||||
- |
|
||||
I check that Invoice is created for this repair order.
|
||||
-
|
||||
!python {model: mrp.repair}: |
|
||||
obj_lines = self.pool.get('account.invoice.line')
|
||||
inv_obj = self.pool.get('account.invoice')
|
||||
repair_id = self.browse(cr, uid, [ref('mrp_repair_rma0')], context=context)[0]
|
||||
invoice_ids = inv_obj.search(cr, uid, [('partner_id', '=', repair_id.partner_invoice_id.id)])
|
||||
invoice_id = inv_obj.browse(cr, uid, invoice_ids)[0]
|
||||
|
||||
assert repair_id.partner_invoice_id == invoice_id.partner_id
|
||||
|
||||
for operation in repair_id.operations:
|
||||
if operation.to_invoice == True:
|
||||
line_ids = obj_lines.search(cr, uid, [('product_id', '=', operation.product_id.id), ('invoice_id', '=', invoice_id.id), ('price_unit', '=', operation.price_unit)])
|
||||
if line_ids:
|
||||
line_id = obj_lines.browse(cr, uid, line_ids)[0]
|
||||
assert line_id.product_id == operation.product_id
|
||||
@@ -10,12 +10,12 @@
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Create invoices">
|
||||
<separator colspan="4" string="Do you really want to create the invoice(s) ?" />
|
||||
<field name="group"/>
|
||||
<newline/>
|
||||
<group col="2" colspan="4">
|
||||
<button icon='gtk-cancel' special="cancel"
|
||||
string="Cancel" />
|
||||
<separator colspan="4" string="Do you really want to create the invoice(s) ?" />
|
||||
<field name="group"/>
|
||||
<newline/>
|
||||
<group col="2" colspan="4">
|
||||
<button icon='gtk-close' special="cancel"
|
||||
string="Close" />
|
||||
<button name="make_invoices" string="Create Invoice"
|
||||
colspan="1" type="object" icon="gtk-ok" />
|
||||
</group>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<field name="model">procurement.order</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Procurement Lines" colors="red:date_planned<current_date and state in ('exception');black:state=='running';green:state=='confirmed';gray:state in ['done','cancel'];blue:state in ('ready')">
|
||||
<tree string="Procurement Lines" colors="red:date_planned<current_date and state in ('exception');black:state=='running';darkgreen:state=='confirmed';gray:state in ['done','cancel'];blue:state in ('ready')">
|
||||
<field name="date_planned" widget="date"/>
|
||||
<field name="origin"/>
|
||||
<field name="product_id"/>
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
<field name="manager"/>
|
||||
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By..." colspan="4" col="20">
|
||||
<filter string="Manager" icon="terp-personal" domain="[]" context="{'group_by':'manager'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
@@ -58,6 +62,8 @@
|
||||
<group expand="0" string="Group By..." colspan="4" col="20">
|
||||
<filter string="Resource" icon="terp-personal" domain="[]" context="{'group_by':'resource_id'}"/>
|
||||
<filter string="Company" icon="terp-go-home" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_from'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
|
||||
+9
-10
@@ -69,6 +69,8 @@ class product_product(osv.osv):
|
||||
property_obj=self.pool.get('ir.property')
|
||||
product_obj=self.browse(cr,uid,ids)[0]
|
||||
account_variation = product_obj.categ_id.property_stock_variation
|
||||
account_variation_id = account_variation and account_variation.id or False
|
||||
if not account_variation_id: raise osv.except_osv(_('Error!'), _('Variation Account is not specified for Product Category: %s' % (product_obj.categ_id.name)))
|
||||
move_ids = []
|
||||
loc_ids = location_obj.search(cr, uid,[('usage','=','internal')])
|
||||
for rec_id in ids:
|
||||
@@ -82,13 +84,10 @@ class product_product(osv.osv):
|
||||
product = self.browse(cr, uid, rec_id, context=c)
|
||||
qty = product.qty_available
|
||||
diff = product.standard_price - new_price
|
||||
assert diff, _("Could not find any difference between standard price and new price!")
|
||||
if not diff: raise osv.except_osv(_('Error!'), _("Could not find any difference between standard price and new price!"))
|
||||
if qty:
|
||||
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')
|
||||
if not company_id: raise osv.except_osv(_('Error!'), _('Company is not specified in Location'))
|
||||
#
|
||||
# Accounting Entries
|
||||
#
|
||||
@@ -129,8 +128,8 @@ class product_product(osv.osv):
|
||||
'move_id': move_id,
|
||||
})
|
||||
move_line_obj.create(cr, uid, {
|
||||
'name': location.name,
|
||||
'account_id': location_account,
|
||||
'name': product.categ_id.name,
|
||||
'account_id': account_variation_id,
|
||||
'credit': amount_diff,
|
||||
'move_id': move_id
|
||||
})
|
||||
@@ -155,8 +154,8 @@ class product_product(osv.osv):
|
||||
'move_id': move_id
|
||||
})
|
||||
move_line_obj.create(cr, uid, {
|
||||
'name': location.name,
|
||||
'account_id': location_account,
|
||||
'name': product.categ_id.name,
|
||||
'account_id': account_variation_id,
|
||||
'debit': amount_diff,
|
||||
'move_id': move_id
|
||||
})
|
||||
@@ -429,7 +428,7 @@ class product_category(osv.osv):
|
||||
'property_stock_variation': fields.property('account.account',
|
||||
type='many2one',
|
||||
relation='account.account',
|
||||
string="Stock variation 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 ",),
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
<separator string="Accounting Stock Properties" colspan="2"/>
|
||||
<field name="property_stock_account_input_categ" domain="[('type','<>','view'),('type','<>','consolidation')]"/>
|
||||
<field name="property_stock_account_output_categ" domain="[('type','<>','view'),('type','<>','consolidation')]"/>
|
||||
<field name="property_stock_variation"/>
|
||||
<field name="property_stock_journal"/>
|
||||
</group>
|
||||
</form>
|
||||
|
||||
@@ -170,7 +170,7 @@
|
||||
country_id: base.in
|
||||
partner_id: stock.res_partner_diasorinltd0
|
||||
street: Ash House, Ash Road
|
||||
title: Ms.
|
||||
title: base.res_partner_title_miss
|
||||
|
||||
|
||||
-
|
||||
@@ -270,8 +270,7 @@
|
||||
- name: '00001'
|
||||
quantity: 5
|
||||
product_id: stock.product_product_hpcdwriters0
|
||||
|
||||
|
||||
|
||||
-
|
||||
I Split into production line.
|
||||
-
|
||||
@@ -327,7 +326,6 @@
|
||||
"partner", "active_ids": [ref("stock.menu_action_picking_tree6")], "active_id":
|
||||
ref("stock.menu_action_picking_tree6"), })
|
||||
|
||||
|
||||
-
|
||||
I confirm the picking.
|
||||
-
|
||||
|
||||
Reference in New Issue
Block a user