"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: 2010-07-07 09:59+0000\n"
+"PO-Revision-Date: 2010-07-09 06:46+0000\n"
"Last-Translator: Bojan Markovic <Unknown>\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-07-08 03:50+0000\n"
+"X-Launchpad-Export-Date: 2010-07-10 04:02+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account_report
#. module: account_report
#: wizard_field:print.indicators.pdf,init,file:0
msgid "Select a PDF File"
-msgstr ""
+msgstr "Odaberi PDF datoteku"
#. module: account_report
#: constraint:ir.actions.act_window:0
msgid "Invalid model name in the action definition."
-msgstr ""
+msgstr "Neispravan naziv modela u definiciji zadatka."
#. module: account_report
#: view:account.report.report:0
msgid "Operators:"
-msgstr ""
+msgstr "Operatori:"
#. module: account_report
#: field:account.report.report,parent_id:0
#. module: account_report
#: field:account.report.report,disp_graph:0
msgid "Display As Graph"
-msgstr ""
+msgstr "Prikaži kao grafikon"
#. module: account_report
#: view:account.report.report:0
msgid "Account Debit:"
-msgstr ""
+msgstr "Dugovanje konta:"
#. module: account_report
#: selection:account.report.report,type:0
#. module: account_report
#: rml:print.indicators:0
msgid "Tabular Summary"
-msgstr ""
+msgstr "Tablični sažetak"
#. module: account_report
#: view:account.report.report:0
msgid "Notes"
-msgstr ""
+msgstr "Bilješke"
#. module: account_report
#: view:account.report.report:0
_columns = {
'name': fields.many2one('ir.model', 'Object', required=True),
- 'max_level': fields.integer('Max Level', help='Specifies maximum level.'),
'create_date': fields.datetime('Create Date', readonly=1),
'active': fields.boolean('Active', help="If the active field is set to False,\
it will allow you to hide the rule without removing it."),
\nNote: This is case sensitive search."),
'server_action_id': fields.many2one('ir.actions.server', 'Server Action', help="Describes the action name.\neg:on which object which action to be taken on basis of which condition"),
'filter_id':fields.many2one('ir.filters', 'Filter', required=False),
- 'domain':fields.char('Domain', size=124, required=False, readonly=False),
}
_defaults = {
'active': lambda *a: True,
- 'max_level': lambda *a: 15,
'trg_date_type': lambda *a: 'none',
'trg_date_range_type': lambda *a: 'day',
'act_mail_to_user': lambda *a: 0,
'act_remind_partner': lambda *a: 0,
'act_remind_user': lambda *a: 0,
'act_mail_to_watchers': lambda *a: 0,
- 'domain': lambda *a: '[]'
}
_order = 'sequence'
@param uid: the current user’s ID for security checks,
@param context: A standard dictionary for contextual values """
ok = True
- if eval(action.domain):
- obj_ids = obj._table.search(cr, uid, eval(action.domain), context=context)
- if not obj.id in obj_ids:
+ if action.filter_id:
+ if action.name.model == action.filter_id.model_id:
+ context.update(eval(action.filter_id.context))
+ obj_ids = obj._table.search(cr, uid, eval(action.filter_id.domain), context=context)
+ if not obj.id in obj_ids:
+ ok = False
+ else:
ok = False
if hasattr(obj, 'user_id'):
ok = ok and (not action.trg_user_id.id or action.trg_user_id.id==obj.user_id.id)
if not scrit:
scrit = []
for action in self.browse(cr, uid, ids):
- level = action.max_level
- if not level:
- break
model_obj = self.pool.get(action.name.model)
for obj in objects:
ok = self.do_check(cr, uid, action, obj, context=context)
if ok:
self.do_action(cr, uid, action, model_obj, obj, context)
break
- level -= 1
context.update({'action': False})
return True
<field name="name" select="1"/>
<field name="active"/>
<field name="sequence"/>
- <field name="max_level" />
- <field name="domain"/>
<field name="filter_id"/>
<notebook colspan="4">
<page string="Conditions">
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Action Rule">
- <field name="name" colspan="4"/>
<field name="sequence"/>
- <field name="max_level"/>
- <field name="domain"/>
+ <field name="name" colspan="4"/>
+ <field name="filter_id"/>
</tree>
</field>
</record>
'wizard/crm_forward_to_partner_view.xml',
'wizard/crm_send_email_view.xml',
+ 'wizard/crm_custom_create_menu_view.xml',
+
'crm_view.xml',
'crm_action_rule_view.xml',
<field name="arch" type="xml">
<graph string="Opportunities By Stage" type="bar">
<field name="stage_id"/>
- <field name="nbr" operator="+"/>
+ <field name="planned_revenue" operator="+"/>
<field name="user_id" group="True"/>
</graph>
</field>
</record>
<record model="ir.actions.act_window" id="act_oppor_stage_user">
- <field name="res_model">Number of Opportunities by stage</field>
+ <field name="res_model">Planned revenue by user and stage</field>
<field name="res_model">crm.lead.report</field>
<field name="view_type">form</field>
<field name="view_mode">graph,tree,form</field>
<child2>
<action
- string="Number of Opportunities by Stage and User"
+ string="Planned Revenue by Stage and User"
name="%(act_oppor_stage_user)d"
colspan="4"/>
<field name="view_type">form</field>
<field name="view_mode">graph,tree,form</field>
<field name="view_id" ref="view_report_crm_oppor_graph"/>
- <field name="domain">['&', ('user_id','=',uid), '!' , '&', ('state', '=', 'done'), ('date_closed','>',(datetime.date.today()-datetime.timedelta(days=30)).strftime('%Y-%m-%d'))]</field>
+ <field name="domain">['&', '&', ('user_id','=',uid), ('type', '=', 'opportunity'), '!' , '&', ('state', '=', 'done'), ('date_closed','>',(datetime.date.today()-datetime.timedelta(days=30)).strftime('%Y-%m-%d'))]</field>
</record>
<record model="ir.actions.act_window" id="act_sales_pipeline">
</child1>
<child2>
<action
- string="Revenues by stage"
+ string="Planned Revenues by Stage"
name="%(act_my_oppor_stage)d"
colspan="4"/>
<action
- string="Win/Lost Ratio for the last Year"
+ string="Win/Lost Ratio for the Last Year"
name="%(act_sales_pipeline)d"
colspan="4"/>
</child2>
}
res_partner()
+
+class crm_case_section_custom(osv.osv):
+ _name = "crm.case.section.custom"
+ _description = 'Custom CRM Case Section'
+
+ _columns = {
+ 'name': fields.char('Case Section',size=64, required=True, translate=True),
+ 'code': fields.char('Section Code',size=8),
+ 'active': fields.boolean('Active'),
+ 'allow_unlink': fields.boolean('Allow Delete', help="Allows to delete non draft cases"),
+ 'sequence': fields.integer('Sequence'),
+ 'user_id': fields.many2one('res.users', 'Responsible User'),
+ 'reply_to': fields.char('Reply-To', size=64, help="The email address put in the 'Reply-To' of all emails sent by Open ERP about cases in this section"),
+ 'parent_id': fields.many2one('crm.case.section.custom', 'Parent Section'),
+ 'note': fields.text('Notes'),
+ }
+
+ _defaults = {
+ 'active': 1,
+ 'allow_unlink': 1,
+ }
+
+ _sql_constraints = [
+ ('code_uniq', 'unique (code)', 'The code of the section must be unique !')
+ ]
+
+ def _check_recursion(self, cr, uid, ids):
+ level = 100
+ while len(ids):
+ cr.execute('SELECT DISTINCT parent_id FROM crm_case_section_custom '\
+ 'WHERE id IN %s',
+ (tuple(ids),))
+ ids = filter(None, map(lambda x:x[0], cr.fetchall()))
+ if not level:
+ return False
+ level -= 1
+ return True
+ _constraints = [
+ (_check_recursion, 'Error ! You cannot create recursive sections.', ['parent_id'])
+ ]
+
+crm_case_section_custom()
+
+
+class crm_case_custom(osv.osv, crm_case):
+ _name = 'crm.case.custom'
+ _inherit = 'mailgate.thread'
+ _description = "Custom CRM Case"
+
+ _columns = {
+ 'id': fields.integer('ID', readonly=True),
+ 'name': fields.char('Name',size=64,required=True),
+ 'priority': fields.selection(AVAILABLE_PRIORITIES, 'Priority'),
+ 'active': fields.boolean('Active'),
+ 'description': fields.text('Description'),
+ 'section_id': fields.many2one('crm.case.section.custom', 'Section', required=True, select=True),
+ 'probability': fields.float('Probability (%)'),
+ 'email_from': fields.char('Partner Email', size=128),
+ 'email_cc': fields.char('CC', size=252),
+ 'partner_id': fields.many2one('res.partner', 'Partner'),
+ 'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', domain="[('partner_id','=',partner_id)]"),
+ 'date': fields.datetime('Date'),
+ 'create_date': fields.datetime('Created' ,readonly=True),
+ 'date_deadline': fields.datetime('Deadline'),
+ 'date_closed': fields.datetime('Closed', readonly=True),
+ 'user_id': fields.many2one('res.users', 'Responsible'),
+ 'state': fields.selection(AVAILABLE_STATES, 'Status', size=16, readonly=True),
+ 'ref' : fields.reference('Reference', selection=_links_get, size=128),
+ 'date_action_last': fields.datetime('Last Action', readonly=1),
+ 'date_action_next': fields.datetime('Next Action', readonly=1),
+ }
+
+ _defaults = {
+ 'active': 1,
+ 'state': 'draft',
+ 'priority': AVAILABLE_PRIORITIES[2][0],
+ 'date': time.strftime('%Y-%m-%d %H:%M:%S'),
+ }
+
+crm_case_custom()
+
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<menuitem id="base.next_id_64" name="Reporting"
parent="base.menu_base_partner" sequence="11" />
+ <menuitem action="crm_custom_create_menu_action"
+ id="crm_case_create_custom_menu"
+ parent="base.menu_crm_config_sales"
+ groups="base.group_extended"
+ name="Create Menu for Custom Cases" />
+
+
<!-- Case Sections Form View -->
<record id="crm_case_section_view_form" model="ir.ui.view">
</field>
</field>
</record>
+
+
+ <!-- Custom Case Sections -->
+ <record id="crm_case_section_custom_view_form" model="ir.ui.view">
+ <field name="name">crm.case.section.custom.form</field>
+ <field name="model">crm.case.section.custom</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="Custom Case Section">
+ <group col="6" colspan="4">
+ <field name="name" select="1" colspan="2"/>
+ <field name="parent_id" select="2" widget="selection"/>
+ <field name="code" select="1"/>
+ <newline/>
+ <field name="user_id" select="2"/>
+ <field name="active" select="2"/>
+ </group>
+ <notebook colspan="4">
+ <page string="Information">
+ <group col="2" colspan="1">
+ <separator string="Mailgateway" colspan="2"/>
+ <field name="reply_to" select="2"/>
+ </group>
+ <group col="2" colspan="1">
+ <separator string="Configuration" colspan="2"/>
+ <field name="allow_unlink" select="2"/>
+ </group>
+ </page>
+ <page string="Notes">
+ <field name="note" select="1" colspan="4" nolabel="1"/>
+ </page>
+ </notebook>
+ </form>
+ </field>
+ </record>
+ <record id="crm_case_section_custom_view_tree" model="ir.ui.view">
+ <field name="name">crm.case.section.custom.tree</field>
+ <field name="model">crm.case.section.custom</field>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree string="Custom Case Section">
+ <field name="name" select="1"/>
+ <field name="code" select="1"/>
+ <field name="user_id" select="1"/>
+ </tree>
+ </field>
+ </record>
+
+ <!-- Custom crm case-->
+
+ <record id="crm_case_custom_tree_view" model="ir.ui.view">
+ <field name="name">Custom Cases - Tree</field>
+ <field name="model">crm.case.custom</field>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree colors="red:date_deadline<current_date and state=='open'" string="Custom Cases">
+ <field name="id"/>
+ <field name="date"/>
+ <field name="date_deadline"/>
+ <field name="name"/>
+ <field name="partner_id"/>
+ <field name="user_id"/>
+ <field name="priority"/>
+ <field name="state"/>
+ <field name="create_date" invisible="1"/>
+ </tree>
+ </field>
+ </record>
+
+ <record id="crm_case_custom_form_view" model="ir.ui.view">
+ <field name="name">Custom Cases - Form</field>
+ <field name="model">crm.case.custom</field>
+ <field name="type">form</field>
+ <field name="priority" eval="1"/>
+ <field name="arch" type="xml">
+ <form string="Custom Cases">
+ <group colspan="4" col="6">
+ <field name="name" select="1"/>
+ <field name="section_id" widget="selection"/>
+ <field name="user_id" select="1"/>
+ <field name="priority"/>
+ <field name="date" select="1"/>
+ <field name="date_deadline" select="2"/>
+ </group>
+ <notebook colspan="4">
+ <page string="General">
+ <group col="4" colspan="4">
+ <separator string="Communication" colspan="4"/>
+ <field name="partner_id" on_change="onchange_partner_id(partner_id, email_from)" select="1"/>
+ <field name="partner_address_id" on_change="onchange_partner_address_id(partner_address_id, email_from)" select="2"/>
+ <newline/>
+ <field name="email_from" select="2"/>
+ </group>
+
+ <separator string="Notes" colspan="4"/>
+ <field colspan="4" name="description" nolabel="1" select="2"/>
+
+ <separator colspan="4"/>
+ <group col="8" colspan="4">
+ <field name="state"/>
+ <button name="case_open" string="Open"
+ states="draft,pending" type="object"
+ icon="gtk-go-forward" />
+ <button name="case_close" string="Close"
+ states="open,draft,pending" type="object"
+ icon="gtk-close" />
+ <button name="case_pending" string="Pending"
+ states="draft,open" type="object"
+ icon="gtk-media-pause" />
+ <button name="case_cancel" string="Cancel"
+ states="draft,open,pending" type="object"
+ icon="gtk-cancel" />
+ <button name="case_reset"
+ string="Reset to Draft" states="done,cancel"
+ type="object" icon="gtk-convert" />
+ </group>
+ </page>
+ <page string="Extra Info">
+ <separator colspan="4" string="Dates"/>
+ <field name="create_date"/>
+ <field name="date_closed"/>
+ <field name="date_action_last"/>
+ <field name="date_action_next"/>
+ <separator colspan="4" string="Others"/>
+ <field name="id" select="1"/>
+ <field name="active" select="2"/>
+ <separator colspan="4" string="References"/>
+ <field colspan="4" name="ref"/>
+ <field colspan="4" name="log_ids" nolabel="1">
+ <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>
+ <page string="Emails" groups="base.group_extended">
+ <group colspan="4">
+ <field colspan="4" name="email_cc" string="CC" widget="char" size="512"/>
+ </group>
+ <field name="message_ids" colspan="4" nolabel="1" mode="form,tree">
+ <form string="Communication history">
+ <group col="4" colspan="4">
+ <field name="email_from"/>
+ <field name="date"/>
+ <field name="email_to" widget="char" size="512"/>
+ <field name="email_cc" widget="char" size="512"/>
+ <field name="name" colspan="4" widget="char" size="512"/>
+ </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"
+ name="%(crm.action_crm_send_mail)d"
+ context="{'mail':'reply', 'model': 'crm.case.custom', '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="2" string="Send New Email"
+ name="%(crm.action_crm_send_mail)d"
+ context="{'mail':'new', 'model': 'crm.case.custom'}"
+ icon="gtk-go-forward" type="action" />
+ <button colspan="2" string="Forward to Partner"
+ name="%(crm_lead_forward_to_partner_act)d"
+ icon="gtk-go-forward" type="action" />
+ </page>
+ </notebook>
+ </form>
+ </field>
+ </record>
+
+ <record model="ir.ui.view" id="crm_case_custom_calendar_view">
+ <field name="name">Custom Cases - Calendar</field>
+ <field name="model">crm.case.custom</field>
+ <field name="type">calendar</field>
+ <field name="priority" eval="2"/>
+ <field name="arch" type="xml">
+ <calendar string="Cases"
+ date_start="date" color="user_id">
+ <field name="name" />
+ <field name="partner_id" />
+ </calendar>
+ </field>
+ </record>
+
+ <!-- Custom Cases Search View -->
+
+ <record id="crm_case_custom_search_view" model="ir.ui.view">
+ <field name="name">Custom Cases - Search</field>
+ <field name="model">crm.case.custom</field>
+ <field name="type">search</field>
+ <field name="arch" type="xml">
+ <search string="Search Cases">
+ <filter icon="terp-check"
+ string="Current"
+ default="1" name="current"
+ domain="[('state','in',('draft','open'))]"/>
+ <filter icon="terp-camera_test"
+ string="Open"
+ domain="[('state','=','open')]"/>
+ <filter icon="terp-gtk-media-pause"
+ string="Pending"
+ 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 00:00:00'))]"
+ help="Todays' Cases" />
+ <filter icon="terp-go-week" string="7 Days"
+ help="Cases 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"/>
+ <field name="user_id">
+ <filter icon="terp-personal-"
+ domain="[('user_id','=', False)]"
+ help="Unassigned Cases" />
+ </field>
+ <newline/>
+ <group expand="0" string="Extended options..." groups="base.group_extended">
+ <field name="create_date" string="Creation Date"/>
+ <field name="date_closed"/>
+ </group>
+ <newline/>
+ <group expand="0" string="Group By...">
+ <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/>
+ <filter string="Priority" icon="terp-rating-rated"
+ domain="[]" context="{'group_by':'priority'}" />
+ <separator orientation="vertical"/>
+ <filter string="Salesman" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
+ <filter string="Partner" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}"/>
+ <separator orientation="vertical"/>
+ <filter string="Creation" icon="terp-go-month"
+ domain="[]" context="{'group_by':'create_date'}" />
+ </group>
+ </search>
+ </field>
+ </record>
</data>
</openerp>
"access_res_partner_category","res.partner.category.crm.user","base.model_res_partner_category","crm.group_crm_user",1,0,0,0
"mail_gateway_mailgate_message","mail_gateway.mailgate.message","mail_gateway.model_mailgate_message","crm.group_crm_user",1,1,1,1
"mail_gateway_mailgate_thread","mail_gateway.mailgate.thread","mail_gateway.model_mailgate_thread","crm.group_crm_user",1,1,1,1
+"access_crm_case_section_custom_user","crm.case.section.custom.user","model_crm_case_section_custom","crm.group_crm_user",1,0,0,0
+"access_crm_case_section_custom_manager","crm.case.section.custom.manager","model_crm_case_section_custom","crm.group_crm_manager",1,1,1,1
+"access_crm_case_custom_user","crm.case.custom.user","model_crm_case_custom","crm.group_crm_user",1,1,1,1
+"access_crm_case_custom_manager","crm.case.custom.manager","model_crm_case_custom","crm.group_crm_manager",1,1,1,1
!python {model: crm.lead2opportunity}: |
self.action_apply(cr, uid, [ref('crm_lead2opportunity_stonage_0')], {'active_id': ref('crm_lead_newcustomer0')})
-- |
- I can check that a lead and a business opportunity is now assigned to this
- lead.
-#-
-# !python {model: crm.lead, id: crm_lead_newcustomer0}:
-# - opportunity_id == False
-
- |
- I check that the partner associated to this lead as the same country, phone number
- and name than the opportunity.
+ In order to check the opportunity is created or not, I check type.
-
!python {model: crm.lead}: |
lead = self.browse(cr, uid, ref("crm_lead_newcustomer0"))
- obj_opportunity = self.pool.get('crm.lead')
- ids = obj_opportunity.search(cr, uid, [('name', '=', lead.partner_name)])
- opportunity = obj_opportunity.browse(cr, uid, ids)[0]
- assert lead.partner_name == opportunity.partner_id.name
- assert lead.phone == opportunity.phone
+ assert lead.type == 'opportunity'
#-
# |
-
!record {model: crm.lead, id: crm_opportunity_abcfuelcounits0}:
email_from: info@balmerinc.be
- name: 'ABC FUEL CO 829264 - 10002 units '
+ name: 'ABC FUEL CO 829264 - 10002 units'
partner_address_id: base.res_partner_address_1
partner_id: base.res_partner_9
probability: 1.0
then I click on the date on which I want schedule meeting.
I fill proper data for that meeting and save it
-
- !record {model: crm.meeting, id: crm_meeting_abcfuelcounits0}:
- alarm_id: base_calendar.alarm3
+ !record {model: crm.meeting, id: crm_meeting_abcfuelcounits0}:
date: '2010-04-16 00:00:00'
date_deadline: '2010-04-16 08:00:00'
duration: 8.0
email_from: info@balmerinc.be
- name: 'ABC FUEL CO 829264 - 10002 units '
+ name: 'ABC FUEL CO 829264 - 10002 units'
opportunity_id: 'crm_opportunity_abcfuelcounits0'
partner_address_id: base.res_partner_address_1
partner_id: base.res_partner_9
- rrule_type: weekly
section_id: crm.section_sales_department
state: open
- |
-
!record {model: crm.opportunity2phonecall, id: crm_opportunity2phonecall_abcfuelcounits0}:
date: '2010-04-17 11:15:00'
- name: 'ABC FUEL CO 829264 - 10002 units '
+ name: 'ABC FUEL CO 829264 - 10002 units'
section_id: crm.section_sales_department
user_id: base.user_demo
- |
I check that phonecall record is created for that opportunity.
-
!python {model: crm.phonecall}: |
- ids = self.search(cr, uid, [('name', '=', 'ABC FUEL CO 829264 - 10002 units')])
- assert len(ids)
+ phone_obj = self.pool.get('crm.phonecall')
+ ids = phone_obj.search(cr, uid, [('name', '=', 'ABC FUEL CO 829264 - 10002 units')])
+ assert len(ids)
- |
I can see phonecall record after click on "Schedule call" wizard.
-
partner_address_id: base.res_partner_address_1
partner_id: base.res_partner_9
section_id: crm.section_sales_department
-
\ No newline at end of file
+
-
!python {model: crm.phonecall2opportunity}: |
self.action_apply(cr, uid, [ref("crm_phonecall2opportunity_interviewcall0")], {"active_id": ref("crm_phonecall_interviewcall0")})
--
- # This is not working, find a way to do that in YAML
-
+
- |
I can see that a business opportunity is now assigned to this phonecall
-
!assert {model: crm.phonecall, id: crm_phonecall_interviewcall0}:
- - opportunity_id == True
+ - opportunity_id != False
- |
And I check that the phonecall and the newly created business opportunity is linked
to same partner
-
!python {model: crm.phonecall}: |
- xid= ref('crm_phonecall_interviewcall0')
- obj_phonecall = self.browse(cr, uid, xid)
+ obj_phonecall = self.browse(cr, uid, ref('crm_phonecall_interviewcall0'))
ids = self.pool.get('crm.lead').search(cr, uid, [('name', '=', obj_phonecall.opportunity_id.name)])
obj_opp = self.pool.get('crm.lead').browse(cr, uid, ids)[0]
assert obj_phonecall.partner_id == obj_opp.partner_id
phonecall_id: 'crm_phonecall_interviewcall0'
rrule_type: weekly
state: open
-
--
- #This is not working for yaml
-- |
- I can jump to this meeting by "Meetings" shortcut from my phonecall's form view
--
- |
In order to schedule other phonecall to the partner
import crm_phonecall_to_opportunity
import crm_partner_to_opportunity
+import crm_custom_create_menu
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
--- /dev/null
+# -*- 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/>.
+#
+##############################################################################
+
+from osv import fields,osv
+
+
+class crm_case_custom_create_menu(osv.osv_memory):
+ '''
+ Create menu for custom Cases
+ '''
+ _name = 'crm.custom.create.menu'
+ _description = 'Create menu for custom Cases'
+
+ _columns = {
+ 'name': fields.char('Menu Name', size=64, required=True),
+ 'menu_parent_id': fields.many2one('ir.ui.menu', 'Parent Menu', required=True),
+ 'section_id': fields.many2one('crm.case.section.custom', 'Section', required=True),
+ 'view_form': fields.many2one('ir.ui.view', 'Form View', domain=[('type','=','form'),('model','=','crm.case.custom')]),
+ 'view_tree': fields.many2one('ir.ui.view', 'Tree View', domain=[('type','=','tree'),('model','=','crm.case.custom')]),
+ 'view_calendar': fields.many2one('ir.ui.view', 'Calendar View', domain=[('type','=','calendar'),('model','=','crm.case.custom')]),
+ 'view_search': fields.many2one('ir.ui.view', 'Search View', domain=[('type','=','search'),('model','=','crm.case.custom')]),
+ }
+
+ def menu_create(self, cr, uid, ids, context=None):
+ """
+ Creates Menus for selected custom section
+ """
+ data_obj = self.pool.get('ir.model.data')
+ for this in self.browse(cr, uid, ids, context=context):
+ domain = [('section_id', '=', this.section_id.id)]
+ view_mode = [this.view_tree and 'tree', this.view_form and 'form', this.view_calendar and 'calendar']
+ view_mode = filter(None , view_mode)
+ action_id = self.pool.get('ir.actions.act_window').create(cr,uid, {
+ 'name': this.name,
+ 'res_model': 'crm.case.custom',
+ 'domain': domain,
+ 'view_type': 'form',
+ 'view_mode': ','.join(view_mode),
+ 'search_view_id': this.view_search.id or False,
+ 'context': {'default_section_id': this.section_id.id, 'default_user_id': uid}
+ })
+ menu_id=self.pool.get('ir.ui.menu').create(cr, uid, {
+ 'name': this.name,
+ 'parent_id': this.menu_parent_id.id,
+ 'icon': 'STOCK_JUSTIFY_FILL'
+ })
+ self.pool.get('ir.values').create(cr, uid, {
+ 'name': 'Custom Cases',
+ 'key2': 'tree_but_open',
+ 'model': 'ir.ui.menu',
+ 'res_id': menu_id,
+ 'value': 'ir.actions.act_window,%d'%action_id,
+ 'object': True
+ })
+ return {}
+
+crm_case_custom_create_menu()
+
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+ <data>
+ <record model="ir.ui.view" id="crm_custom_create_menu_form">
+ <field name="name">crm.custom.create.menu.form</field>
+ <field name="model">crm.custom.create.menu</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="Create Menu for Custom Cases">
+ <separator string="Menu Information" colspan="4"/>
+ <field name="name"/>
+ <field name="menu_parent_id"/>
+ <field name="section_id"/>
+ <label string="This wizard will create all sub-menus, within the selected menu." align="0.0" colspan="4"/>
+ <label string="You may want to create a new parent menu to put all the created menus in." align="0.0" colspan="4"/>
+ <separator string="Select Views (Empty for default)" colspan="4"/>
+ <field name="view_form"/>
+ <field name="view_tree"/>
+ <field name="view_calendar"/>
+ <field name="view_search"/>
+ <separator string="" colspan="4"/>
+ <label string="" colspan="2"/>
+ <button special="cancel" string="_Cancel" icon="gtk-cancel"/>
+ <button name="menu_create" string="Create _Menu" type="object" icon='gtk-ok'/>
+ </form>
+ </field>
+ </record>
+
+ <record model="ir.actions.act_window" id="crm_custom_create_menu_action">
+ <field name="name">Create Menu</field>
+ <field name="res_model">crm.custom.create.menu</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ <field name="target">new</field>
+ </record>
+
+ </data>
+</openerp>
_defaults = {
'name' : 'email',
- 'history': 'latest',
+ 'history': 'info',
'add_cc': True,
'email_from': lambda self, cr, uid, *a: self.pool.get('res.users')._get_email_from(cr, uid, uid)[uid]
}
!assert {model: crm.claim, id: crm_claim_damagedproduct0}:
- state == 'draft'
- |
- Now I make sure that claim is at "Accepted" stage.
--
- !assert {model: crm.claim, id: crm_claim.crm_claim_damagedproduct0}:
- stage_id: crm_claim.stage_claim1
-- |
I can change that stage by next button right on it
-
!python {model: crm.claim}: |
!python {model: crm.helpdesk}: |
self.case_open(cr, uid, [ref('crm_helpdesk_somefunctionalquestion0')])
- |
- I can see that "Send Reminder" button is visible, which is used to send reminder to partner from
- responsible person or send reminder to responsible person from partner.
--
- #this is not work for yaml.
--
-# !python {model: crm.helpdesk}: |
-# self.remind_user(cr, uid, [ref('crm_helpdesk_somefunctionalquestion0')], context={}, attach=False, destination=True)
-- |
After a proper communication for the request via email I make sure that the request is fulfilled and
I close this HelpDesk Request by clicking on "Close" button.
-
!python {model: crm.helpdesk}: |
- self.case_close(cr, uid, [ref('crm_helpdesk_somefunctionalquestion0')])
--
+ self.case_close(cr, uid, [ref('crm_helpdesk_somefunctionalquestion0')])
contact_id = self.pool.get('res.partner.contact').browse(cr, uid, contact)
data['badge_name'] = contact_id.name
- data['badge_title'] = contact_id.title
+ data['badge_title'] = contact_id.title.name
if partner:
partner_addresses = self.pool.get('res.partner.address').search(cr, uid, [('partner_id', '=', partner)])
job_ids = self.pool.get('res.partner.job').search(cr, uid, [('contact_id', '=', contact), ('address_id', 'in', partner_addresses)])
data_event = self.pool.get('event.event').browse(cr, uid, event_id)
context['currency_id'] = data_event.currency_id.id
-
+ if data_event.user_id.id:
+ return {'value': {'user_id':data_event.user_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]
data_event = self.pool.get('event.event').browse(cr, uid, event_id)
if data_event.product_id:
+ data['event_product']=data_event.product_id.name
if not partner_invoice_id:
data['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': data}
return False
def check_produce_service(self, cr, uid, procurement, context=[]):
- return True
+ """ Checks project_mrp install or not.
+ @return: True or False"""
+ obj_module = self.pool.get('ir.module.module')
+ module_id = obj_module.search(cr, uid, [('name', '=', 'project_mrp'),('state', '=', 'installed')])
+ if module_id:
+ return True
+ cr.execute('update procurement_order set message=%s where id=%s', (_('Project_mrp module not installed !'), procurement.id))
+ return False
def check_produce_product(self, cr, uid, procurement, context=[]):
""" Finds BoM of a product if not found writes exception message.
return True
def _check_make_to_stock_service(self, cr, uid, procurement, context={}):
+ """
+ This method may be overrided by objects that override procurement.order
+ for computing their own purpose
+ @return: True"""
return True
def _check_make_to_stock_product(self, cr, uid, procurement, context={}):
_columns = {
'name': fields.char('Name', size=128, required=True, translate=True, select=True),
- 'product_manager': fields.many2one('res.users','Product Manager'),
+ 'product_manager': fields.many2one('res.users','Product Manager',help="This is use as task responsible"),
'description': fields.text('Description',translate=True),
'description_purchase': fields.text('Purchase Description',translate=True),
'description_sale': fields.text('Sale Description',translate=True),
import wizard
import res_partner
-
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
"author": "Tiny",
"website": "http://www.openerp.com",
"category": "Generic Modules/Projects & Services",
- "depends": ["product", "analytic", "process", "mail_gateway","board"],
- "description": """Project management module that track multi-level projects, tasks,
+ "depends": ["product", "analytic", "mail_gateway", "board"],
+ "description": """Project management module tracks multi-level projects, tasks,
work done on tasks, eso. It is able to render planning, order tasks, eso.
Dashboard for project members that includes:
* List of my open tasks
"wizard/project_task_delegate_view.xml",
"security/ir.model.access.csv",
"project_data.xml",
- "project_wizard.xml",
"project_view.xml",
"project_report.xml",
"process/task_process.xml",
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
-
-
+
<!--
Administrator shortcut
Demo user startup menu
<field name="sequence">3</field>
<field name="res_id" ref="menu_board_project"/>
</record-->
+
<record id="base.user_root" model="res.users">
<field name="action_id" ref="open_board_project"/>
</record>
<field name="name">Project</field>
</record>
- <record id="view_task_tree" model="ir.ui.view">
- <field name="name">project.task.tree</field>
- <field name="model">project.task</field>
- <field name="type">tree</field>
- <field eval="99" name="priority"/>
- <field name="arch" type="xml">
- <tree colors="red:date_deadline<current_date;blue:date_deadline==current_date;black:date_deadline>current_date" string="My Tasks">
- <field name="name"/>
- <field name="project_id"/>
- <field name="date_deadline"/>
- <field name="planned_hours"/>
- <field name="effective_hours"/>
- <field name="priority"/>
- </tree>
- </field>
- </record>
<!-- Editable My task -->
<record id="view_task_tree" model="ir.ui.view">
<field name="name">project.task.tree</field>
</tree>
</field>
</record>
+
<record id="action_view_task_tree" model="ir.actions.act_window">
<field name="name">My Open Tasks</field>
<field name="res_model">project.task</field>
<field name="domain">[('user_id','=',uid),('state','=','open')]</field>
<field name="view_id" ref="view_task_tree"/>
</record>
+
<record id="action_view_pending_task_tree" model="ir.actions.act_window">
<field name="name">My Pending Tasks</field>
<field name="res_model">project.task</field>
<field name="domain">[('user_id','=',uid),('state','=','pending')]</field>
<field name="view_id" ref="view_task_tree"/>
</record>
+
<record id="action_view_task_tree_deadline" model="ir.actions.act_window">
<field name="name">My Task's Deadlines</field>
<field name="res_model">project.task</field>
<field name="usage">menu</field>
<field name="view_id" ref="board_project_form"/>
</record>
+
<menuitem
id="next_id_86"
name="Dashboard"
icon="terp-graph"
sequence="0"
parent="base.menu_project_report"/>
+
<menuitem
action="open_board_project"
icon="terp-graph"
id="menu_board_project"
parent="next_id_86"
sequence="1"/>
+
</data>
</openerp>
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
+
from osv import fields, osv
class project_installer(osv.osv_memory):
_columns = {
# Project Management
- 'project_long_term': fields.boolean('Long Term Planning',
+ 'project_long_term': fields.boolean(
+ 'Long Term Planning',
help="Enables long-term projects tracking, including "
"multiple-phase projects and resource allocation handling."),
'project_wiki': fields.boolean('Specifications in a Wiki',
help="Tracks and helps employees encode and validate timesheets "
"and attendance."),
'hr_timesheet_invoice': fields.boolean('Invoice Based on Hours',
- help="Helps generate invoice based on based on human resources "
+ help="Helps generate invoice based on human resources "
"costs and general expenses."),
'account_budget': fields.boolean('Budgets',
help="Helps accountants manage analytic and crossover budgets."),
help="Implements and tracks the concepts and task types defined "
"in the SCRUM methodology."),
'project_gtd': fields.boolean('Getting Things Done',
- help="Embeds the Getting Things Done concepts into OpenERP's "
+ help="Embeds the 'Getting Things Done concepts' into OpenERP's "
"project management."),
}
+
_defaults={
- 'project_crm': True,
+ 'project_crm': True,
}
+
project_installer()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
+
from lxml import etree
-import datetime
import time
from tools.translate import _
_defaults = {
'sequence': 1
}
+
project_task_type()
class project(osv.osv):
_inherits = {'account.analytic.account':"category_id"}
def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False):
- if context is None:
- context = {}
if user == 1:
- return super(project, self).search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count)
+ return super(project, self).search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count)
if context and context.has_key('user_prefence') and context['user_prefence']:
cr.execute("""SELECT project.id FROM project_project project
LEFT JOIN account_analytic_account account ON account.id = project.category_id
context=context, count=count)
def _complete_name(self, cr, uid, ids, name, args, context=None):
- if context is None:
- context = {}
res = {}
for m in self.browse(cr, uid, ids, context=context):
res[m.id] = (m.parent_id and (m.parent_id.name + '/') or '') + m.name
parent=parent)
def onchange_partner_id(self, cr, uid, ids, part=False, context=None):
- if context is None:
- context = {}
partner_obj = self.pool.get('res.partner')
if not part:
return {'value':{'contact_id': False, 'pricelist_id': False}}
return {'value':{'contact_id': addr['contact'], 'pricelist_id': pricelist_id}}
def _progress_rate(self, cr, uid, ids, names, arg, context=None):
- if context is None:
- context = {}
res = {}.fromkeys(ids, 0.0)
progress = {}
if not ids:
'type_ids': fields.many2many('project.task.type', 'project_task_type_rel', 'project_id', 'type_id', 'Tasks Stages'),
'project_escalation_id': fields.many2one('project.project','Project Escalation', help='If any issue is escalated from the current Project, it will be listed under the project selected here.'),
}
+
_order = "sequence"
+
_defaults = {
'active': True,
'priority': 1,
'sequence': 10,
'warn_manager': True,
}
+
def _check_dates(self, cr, uid, ids):
leave = self.read(cr, uid, ids[0], ['date_start', 'date'])
if leave['date_start'] and leave['date']:
(_check_dates, 'Error! project start-date must be lower then project end-date.', ['date_start', 'date']),
(_check_escalation, 'Error! You cannot assign escalation to the same project!', ['project_escalation_id'])
]
+
def set_template(self, cr, uid, ids, context=None):
res = self.setActive(cr, uid, ids, value=False, context=context)
return res
'search_view_id': search_view['res_id'],
'nodestroy': True
}
-# return result
# set active value for a project, its sub projects and its tasks
def setActive(self, cr, uid, ids, value=True, context=None):
- if context is None:
- context = {}
task_obj = self.pool.get('project.task')
for proj in self.browse(cr, uid, ids, context=None):
- if context is None:
- context = {}
self.write(cr, uid, [proj.id], {'state': value and 'open' or 'template'}, context)
cr.execute('select id from project_task where project_id=%s', (proj.id,))
tasks_id = [x[0] for x in cr.fetchall()]
child_ids = self.search(cr, uid, [('parent_id','=', proj.id)])
if child_ids:
self.setActive(cr, uid, child_ids, value, context=None)
- if context is None:
- context = {}
return True
+
project()
class task(osv.osv):
_date_name = "date_start"
def _str_get(self, task, level=0, border='***', context=None):
- if context is None:
- context = {}
return border+' '+(task.user_id and task.user_id.name.upper() or '')+(level and (': L'+str(level)) or '')+(' - %.1fh / %.1fh'%(task.effective_hours or 0.0,task.planned_hours))+' '+border+'\n'+ \
border[0]+' '+(task.name or '')+'\n'+ \
(task.description or '')+'\n\n'
# Compute: effective_hours, total_hours, progress
def _hours_get(self, cr, uid, ids, field_names, args, context=None):
- if context is None:
- context = {}
res = {}
cr.execute("SELECT task_id, COALESCE(SUM(hours),0) FROM project_task_work WHERE task_id IN %s GROUP BY task_id",(tuple(ids),))
hours = dict(cr.fetchall())
return {'value':{'remaining_hours': planned - effective}}
def _default_project(self, cr, uid, context=None):
+ if context is None:
+ context = {}
if 'project_id' in context and context['project_id']:
return int(context['project_id'])
return False
#]
def copy_data(self, cr, uid, id, default={}, context=None):
- if context is None:
- context = {}
default = default or {}
default['work_ids'] = []
return super(task, self).copy_data(cr, uid, id, default, context)
def _check_dates(self, cr, uid, ids, context=None):
- if context is None:
- context = {}
task = self.read(cr, uid, ids[0], ['date_start', 'date_end'])
if task['date_start'] and task['date_end']:
if task['date_start'] > task['date_end']:
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of tasks."),
'type': fields.many2one('project.task.type', 'Stage',),
'state': fields.selection([('draft', 'Draft'),('open', 'In Progress'),('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')], 'State', readonly=True, required=True,
- help='If the task is created the state \'Draft\'.\n If the task is started, the state becomes \'In Progress\'.\n If review is needed the task is in \'Pending\' state.\
+ help='If the task is created the state is \'Draft\'.\n If the task is started, the state becomes \'In Progress\'.\n If review is needed the task is in \'Pending\' state.\
\n If the task is over, the states is set to \'Done\'.'),
'date_start': fields.datetime('Starting Date'),
'date_end': fields.datetime('Ending Date'),
'manager_id': fields.related('project_id', 'category_id', 'user_id', type='many2one', relation='res.users', string='Project Manager'),
'company_id': fields.many2one('res.company', 'Company'),
}
+
_defaults = {
'state': 'draft',
'priority': '2',
'project_id': _default_project,
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c)
}
+
_order = "sequence, priority, date_start, id"
_constraints = [
#
# Override view according to the company definition
#
+
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
users_obj = self.pool.get('res.users')
- if context is None:
- context = {}
obj_tm = users_obj.browse(cr, uid, uid, context).company_id.project_time_mode_id
tm = obj_tm and obj_tm.name or 'Hours'
mod_obj = self.pool.get('ir.model.data')
request = self.pool.get('res.request')
tasks = self.browse(cr, uid, ids)
+ task_id = ids[0]
+ cntx = {}
+ if len(args):
+ cntx = args[0]
for task in tasks:
project = task.project_id
if project:
'ref_doc1': 'project.task,%d'% (task.id,),
'ref_doc2': 'project.project,%d'% (project.id,),
})
- elif project.warn_manager:
- task_id = ids[0]
+ elif project.warn_manager and cntx.get('mail_send',False):
mail_send = True
message = _('Task ') + " '" + task.name + "' "+ _("is Done.")
self.log(cr, uid, task.id, message)
if mail_send:
model_data_ids = mod_obj.search(cr,uid,[('model','=','ir.ui.view'),('name','=','view_project_close_task')])
resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'])[0]['res_id']
- args[0].update({'task_id': task_id})
+ cntx.update({'task_id': task_id})
return {
'name': _('Email Send to Customer'),
'view_type': 'form',
- 'context': args[0], # improve me
+ 'context': cntx, # improve me
'view_mode': 'tree,form',
'res_model': 'close.task',
'views': [(resource_id,'form')],
'target': 'new',
'nodestroy': True
}
- return True
+ else:
+ self.write(cr, uid, [task_id], {'state': 'done', 'date_end':time.strftime('%Y-%m-%d %H:%M:%S'), 'remaining_hours': 0.0})
+ return False
def do_reopen(self, cr, uid, ids, *args):
request = self.pool.get('res.request')
'user_id': fields.many2one('res.users', 'Done by', required=True),
'company_id': fields.related('task_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True)
}
+
_defaults = {
'user_id': lambda obj, cr, uid, context: uid,
'date': time.strftime('%Y-%m-%d %H:%M:%S')
}
+
_order = "date desc"
+
def create(self, cr, uid, vals, *args, **kwargs):
if 'hours' in vals and (not vals['hours']):
vals['hours'] = 0.00
for work in self.browse(cr, uid, ids):
cr.execute('update project_task set remaining_hours=remaining_hours + %s where id=%s', (work.hours, work.task_id.id))
return super(project_work,self).unlink(cr, uid, ids, *args, **kwargs)
+
project_work()
class config_compute_remaining(osv.osv_memory):
_name='config.compute.remaining'
+
def _get_remaining(self,cr, uid, ctx):
task_obj = self.pool.get('project.task')
if 'active_id' in ctx:
class message(osv.osv):
_name = "project.message"
_description = "Message"
+
_columns = {
'subject': fields.char('Subject', size=128, required="True"),
'project_id': fields.many2one('project.project', 'Project', ondelete='cascade'),
_defaults = {
'user_id': lambda self,cr,uid,ctx: uid,
- 'date': lambda self,cr,uid,ctx: time.strftime('%Y-%m-%d'),
+ 'date': time.strftime('%Y-%m-%d'),
'project_id': _default_project
}
_columns = {
'context_project_id': fields.many2one('project.project', 'Project')
}
+
users()
class account_analytic_account(osv.osv):
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
+
<!--
Requests Links
-->
<record id="project_project_22" model="project.project">
<field name="priority">20</field>
<field name="parent_id" ref="project_project_9"/>
- <field name="name">Specific Developements</field>
+ <field name="name">Specific Developments</field>
<field name="manager" ref="base.user_root"/>
<field eval="[(6, 0, [ref('project_tt_specification'), ref('project_tt_development')])]" name="type_ids"/>
</record>
<field name="type" ref="project_tt_development"/>
<field name="user_id" ref="base.user_root"/>
<field name="project_id" ref="project_project_22"/>
- <field name="description">BoM, After sales returns, interventions. Tracability.</field>
+ <field name="description">BoM, After sales returns, interventions. Traceability.</field>
<field name="name">Specific adaptation to MRP</field>
</record>
<record id="project_task_130" model="project.task">
<field name="remaining_hours">24.0</field>
<field name="user_id" ref="base.user_root"/>
<field name="project_id" ref="project_project_21"/>
- <field name="name">MRP; functionnal layer</field>
+ <field name="name">MRP; functional layer</field>
<field name="state">done</field>
<field eval="time.strftime('%Y-%m-%d 12:12')" name="date_close"/>
</record>
<field name="remaining_hours">32.0</field>
<field model="res.users" name="user_id" search="[('login','=','demo')]"/>
<field name="project_id" ref="project_project_22"/>
- <field name="name">Customer docs</field>
+ <field name="name">Customer doc</field>
</record>
<record id="project_task_197" model="project.task">
<field name="sequence">30</field>
- Create Users</field>
<field name="subject">Configuration steps</field>
</record>
+
</data>
</openerp>
<openerp>
<data>
+
<record id="view_project_installer" model="ir.ui.view">
<field name="name">project.installer.view</field>
<field name="model">project.installer</field>
<field name="type">form</field>
<field name="inherit_id" ref="base.res_config_installer"/>
<field name="arch" type="xml">
- <data>
+ <data>
<form position="attributes">
<attribute name="string">Project Modules Installation</attribute>
</form>
<xpath expr='//separator[@string="vsep"]' position='attributes'>
<attribute name='string'></attribute>
</xpath>
- <xpath expr="//label[@string='description']"
- position="attributes">
- <attribute name="string">Various OpenERP applications are available to bring your project management to the next levels of control and flexibility.</attribute>
+ <xpath expr="//label[@string='description']" position="attributes">
+ <attribute name="string">Various OpenERP applications are available to bring your project management to the next levels of control and flexibility.</attribute>
</xpath>
<xpath expr="//button[@string='Install Modules']" position="attributes">
- <attribute name="string">Configure</attribute>
+ <attribute name="string">Configure</attribute>
</xpath>
<group colspan="8">
<field name="project_crm"/>
</xpath>
</field>
</record>
+
</data>
</openerp>
#
##############################################################################
-import time
-import re
-import os
-
-import mx.DateTime
-import base64
-
-from tools.translate import _
-
-import tools
-from osv import fields,osv,orm
-from osv.orm import except_orm
+from osv import fields,osv
class project_tasks(osv.osv):
_name = "project.task"
_inherit = "project.task"
- def msg_new(self, cr, uid, msg):
+ def msg_new(self, cr, uid, msg):
mailgate_obj = self.pool.get('mail.gateway')
msg_body = mailgate_obj.msg_body_get(msg)
data = {
if msg_actions['priority'] in ('1','2','3','4','5'):
data['priority'] = msg_actions['priority']
-
self.write(cr, uid, [id], data)
getattr(self,act)(cr, uid, [id])
return True
def message_followers(self, cr, uid, ids, context=None):
- if context is None:
- context = {}
res = []
if isinstance(ids, (str, int, long)):
select = [ids]
return res
def msg_send(self, cr, uid, id, *args, **argv):
- return True
+ return True
project_tasks()
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
+# -*- 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 pooler
import datetime
-def timeformat_convert(cr, uid, time_string, context=None):
+def timeformat_convert(cr, uid, time_string):
# Function to convert input time string:: 8.5 to output time string 8:30
- if context is None:
- context = {}
split_list = str(time_string).split('.')
hour_part = split_list[0]
mins_part = split_list[1]
converted_string = hour_part + ':' + str(round_mins)[0:2]
return converted_string
-def leaves_resource(cr,uid,calendar_id,resource_id=False,resource_calendar=False):
+def leaves_resource(cr, uid, calendar_id, resource_id=False, resource_calendar=False):
# To get the leaves for the resource_ids working on phase
pool = pooler.get_pool(cr.dbname)
leaves.sort()
return leaves
-def compute_working_calendar(cr,uid,calendar_id):
+def compute_working_calendar(cr, uid, calendar_id):
# To change the format of working calendar to bring it into 'faces' format
pool = pooler.get_pool(cr.dbname)
resource_week_pool = pool.get('resource.calendar.week')
time_range = "8:00-8:00"
non_working = ""
- wk = {"0":"mon","1":"tue","2":"wed","3":"thu","4":"fri","5":"sat","6":"sun"}
+ wk = {"0":"mon", "1":"tue", "2":"wed", "3":"thu", "4":"fri", "5":"sat", "6":"sun"}
wk_days = {}
wk_time = {}
wktime_list = []
wktime_cal = []
week_ids = resource_week_pool.search(cr, uid, [('calendar_id','=',calendar_id)])
- week_obj = resource_week_pool.read(cr, uid, week_ids, ['dayofweek','hour_from','hour_to'])
+ week_obj = resource_week_pool.read(cr, uid, week_ids, ['dayofweek', 'hour_from', 'hour_to'])
# Converting time formats into appropriate format required
# and creating a list like [('mon', '8:00-12:00'), ('mon', '13:00-18:00')]
wktime_cal.append((non_working[:-1],time_range))
return wktime_cal
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
+
<menuitem
icon="terp-project" id="base.menu_main_pm"
name="Project" sequence="10"
<field name="name" string="Project Name"/>
<field name="user_id" string="Project Manager"/>
<field name="partner_id" string="Partner"/>
+ <field name="parent_id" invisible="1"/>
<field name="planned_hours" widget="float_time"/>
<field name="total_hours" widget="float_time"/>
<field name="effective_hours" widget="float_time"/>
<act_window domain="[('user_id', '=', active_id),('date', '>=', time.strftime('%Y-%m-01'))]" id="act_res_users_2_project_task_work_month" name="Month works" res_model="project.task.work" src_model="res.users" view_mode="tree,form" view_type="form"/>
<act_window domain="[('project_id', '=', active_id)]" id="act_project_messages" name="Messages" res_model="project.message" src_model="project.project"/>
+
</data>
</openerp>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<openerp>
- <data>
- <!--<wizard id="wizard_close_task" menu="False" model="project.task" name="project.task.close" string="Close Task"/>-->
- <!--<wizard id="wizard_delegate_task" menu="False" model="project.task" name="project.task.delegate" string="Delegate Task"/>-->
- <!--<wizard
- id="wizard_duplicate_template"
- menu="False"
- model="project.project"
- name="project.duplicate.template" string="Duplicate Template"/>
--->
- </data>
-</openerp>
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
+
import project_report
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
t.type
""")
+
report_project_task_user()
#This class is generated for project deshboard purpose
GROUP BY pur.uid,aaa.state,aaa.name
)
""")
+
project_vs_remaining_hours()
class task_by_days(osv.osv):
to_char(pt.create_date, 'YYYY-MM-DD'),pt.state,pt.project_id
)
""")
+
task_by_days()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
+
<menuitem id="base.menu_project_report" name="Reporting" parent="base.menu_main_pm" sequence="50"/>
<record id="view_task_project_user_tree" model="ir.ui.view">
<field name="model">report.project.task.user</field>
<field name="type">graph</field>
<field name="arch" type="xml">
- <graph string="Tasks Analysis" type="bar">
- <field name="name"/>
- <field name="state" group="True"/>
- <field name="no_of_days" operator="+"/>
- </graph>
- </field>
- </record>
+ <graph string="Tasks Analysis" type="bar">
+ <field name="name"/>
+ <field name="state" group="True"/>
+ <field name="no_of_days" operator="+"/>
+ </graph>
+ </field>
+ </record>
<record id="view_task_project_user_search" model="ir.ui.view">
<field name="name">report.project.task.user.search</field>
</field>
</record>
- <record id="action_project_vs_remaining_hours_graph" model="ir.actions.act_window">
+ <record id="action_project_vs_remaining_hours_graph" model="ir.actions.act_window">
<field name="name">Project and remaining hours</field>
<field name="res_model">project.vs.remaining.hours</field>
<field name="view_type">form</field>
</record>
<!-- Views and action for project issue dashboard -->
- <record id="view_task_by_days_tree" model="ir.ui.view">
+ <record id="view_task_by_days_tree" model="ir.ui.view">
<field name="name">task.by.days.tree</field>
<field name="model">task.by.days</field>
<field name="type">tree</field>
class res_partner(osv.osv):
- """ Inherits partner and adds CRM information in the partner form """
+ """ Inherits partner and adds Tasks information in the partner form """
_inherit = 'res.partner'
_columns = {
'task_ids': fields.one2many('project.task', 'partner_id', 'Tasks'),
</page>
</field>
</record>
+
</data>
</openerp>
#
##############################################################################
-from osv import fields, osv
+import time
+from osv import fields, osv
from tools.translate import _
from tools import email_send as email
if 'task_id' in context:
task = self.pool.get('project.task').browse(cr, uid, context['task_id'])
partner_id = task.partner_id or task.project_id.partner_id
- if partner_id and partner_id.address[0].email:
+ if partner_id and len(partner_id.address) and partner_id.address[0].email:
email = partner_id.address[0].email
return email
return task.description or task.name
return ''
- _defaults={
+ _defaults = {
'email': _get_email,
'description': _get_desc,
}
+
+ def close(self, cr, uid, ids, context=None):
+ if 'task_id' in context:
+ self.pool.get('project.task').write(cr, uid, [context['task_id']], {'state': 'done', 'date_end':time.strftime('%Y-%m-%d %H:%M:%S'), 'remaining_hours': 0.0})
+ return {}
def confirm(self, cr, uid, ids, context=None):
if context is None:
close_task = self.read(cr, uid, ids[0], [])
to_adr = close_task['email']
description = close_task['description']
+
if 'task_id' in context:
- for task in self.pool.get('project.task').browse(cr, uid, [context['task_id']], context=context):
+ task_obj = self.pool.get('project.task')
+ for task in task_obj.browse(cr, uid, [context['task_id']], context=context):
project = task.project_id
subject = "Task '%s' closed" % task.name
if task.user_id and task.user_id.address_id and task.user_id.address_id.email:
footer = (project.warn_footer or '') % val
body = u'%s\n%s\n%s\n\n-- \n%s' % (header, description, footer, signature)
email(from_adr, [to_adr], subject, body.encode('utf-8'), email_bcc=[from_adr])
+ task_obj.write(cr, uid, [task.id], {'state': 'done', 'date_end':time.strftime('%Y-%m-%d %H:%M:%S'), 'remaining_hours': 0.0})
else:
- raise osv.except_osv(_('Error'), _("Couldn't send mail because the contact for this task (%s) has no email address!") % contact.name)
+ raise osv.except_osv(_('Error'), _("Please specify the email address of partner."))
return {}
project_close_task()
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<newline/>
<field name="description" />
</group>
- <group colspan="4" col="6">
- <button icon="gtk-cancel" special="cancel" string="_Close"/>
- <button icon="gtk-ok" name="confirm" string="Send Mail" type="object"/>
+ <separator string="" colspan="6"/>
+ <group colspan="6" col="6">
+ <button icon="gtk-ok" name="confirm" string="Send and Close" type="object"/>
+ <button icon="gtk-ok" string="Close" name="close" type="object"/>
+ <button icon="gtk-cancel" special="cancel" string="_Cancel"/>
</group>
</form>
</field>
'description': delegate_data['new_task_description'] or '',
'child_ids': [],
'work_ids': []
- })
+ }, context)
task_obj.write(cr, uid, [task.id], {
'remaining_hours': delegate_data['planned_hours_me'],
'planned_hours': delegate_data['planned_hours_me'] + (task.effective_hours or 0.0),
'name': newname,
- })
+ }, context)
if delegate_data['state'] == 'pending':
- task_obj.do_pending(cr, uid, [task.id])
+ task_obj.do_pending(cr, uid, [task.id], context)
else:
- task_obj.do_close(cr, uid, [task.id])
- delegrate_user = user_obj.browse(cr, uid, delegate_data['user_id'], context=context)
- message = _('Task ') + " '" + delegate_data['name'] + "' "+ _("is Delegated to User:") +" '"+ delegrate_user.name +"' "
- self.log(cr, uid, task.id, message)
+ context.update({'mail_send': False} )
+ task_obj.do_close(cr, uid, [task.id], context)
+ delegrate_user = user_obj.browse(cr, uid, delegate_data['user_id'], context=context)
+ message = _('Task ') + " '" + delegate_data['name'] + "' "+ _("is Delegated to User:") +" '"+ delegrate_user.name +"' "
+ self.log(cr, uid, task.id, message)
return {}
project_task_delegate()
'crm',
'project',
'hr_timesheet_sheet',
- 'resource'
],
'init_xml': [
'project_issue_data.xml'
'create_date': fields.datetime('Creation Date', readonly=True),
'write_date': fields.datetime('Update Date', readonly=True),
'date_deadline': fields.date('Deadline'),
- 'date_closed': fields.datetime('Closed', readonly=True),
'section_id': fields.many2one('crm.case.section', 'Sales Team', \
select=True, help='Sales team to which Case belongs to.\
Define Responsible user and Email account for mail gateway.'),
res = self.write(cr, uid, ids, vals)
return res
-
def msg_send(self, cr, uid, id, *args, **argv):
""" Send The Message
'timesheet_ids': fields.one2many('hr.analytic.timesheet', 'issue_id', 'Timesheets'),
'analytic_account_id': fields.related('project_id', 'category_id', string='Analytic Account')
}
+
project_issue()
class account_analytic_line(osv.osv):
</field>
</record>
</data>
-</openerp>
+</openerp>
\ No newline at end of file
"author": "Tiny",
"website": "http://www.openerp.com",
"category": "Generic Modules/Projects & Services",
- "depends": ["project", "resource"],
+ "depends": ["resource", "project"],
"description": """
Long Term Project management module that tracks planning, scheduling, resources allocation.
'responsible_id': lambda obj,cr,uid,context: uid,
'state': 'draft',
'sequence': 10,
- 'product_uom': lambda self,cr,uid,c: self.pool.get('product.uom').search(cr, uid, [('name', '=', 'Day')], context=c)[0]
+ 'product_uom': lambda self,cr,uid,c: self.pool.get('product.uom').search(cr, uid, [('name', '=', 'day')], context=c)[0]
}
_order = "name"
_constraints = [
resource_obj = self.pool.get('resource.resource')
uom_obj = self.pool.get('product.uom')
phase_resource_obj = False
-
if context is None:
context = {}
if phase:
if context is None:
context = {}
- project_obj = self.pool.get('project.project')
phase_obj = self.pool.get('project.phase')
data = self.read(cr, uid, ids, [], context=context)[0]
if not data['project_id'] and data['target_project'] == 'one':
raise osv.except_osv(_('Error!'), _('Please Specify Project to be schedule'))
if data['project_id']: # If project mentioned find its phases
- project_id = project_obj.browse(cr, uid, data['project_id'], context=context)
- phase_ids = phase_obj.search(cr, uid, [('project_id', '=', project_id.id),
+ project_id = data['project_id']
+ phase_ids = phase_obj.search(cr, uid, [('project_id', '=', project_id),
('state', 'in', ['draft', 'open', 'pending']),
('previous_phase_ids', '=', False)
])
return {}
project_schedule_task()
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
"depends": ["project"],
"author": "Tiny",
"description": """
- This module provides the functionality to send messages within a project.'
- A user can send messages individually to other user also he can broadcast
+ This module provides the functionality to send messages within a project.
+ A user can send messages individually to other user. He can even broadcast
it to all the users.
""",
'website': 'http://www.openerp.com',
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
-import mrp
+import project_procurement
import project_mrp
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+++ /dev/null
-# -*- 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/>.
-#
-##############################################################################
-
-from osv import fields, osv, orm
-
-import tools
-
-class procurement_order(osv.osv):
- _name = "procurement.order"
- _inherit = "procurement.order"
- _columns = {
- 'task_id': fields.many2one('project.task', 'Task')
- }
-
- def action_produce_assign_service(self, cr, uid, ids, context=None):
- if context is None:
- context = {}
- for procurement in self.browse(cr, uid, ids):
- sline = self.pool.get('sale.order.line')
- product_obj=self.pool.get('product.product')
- content = ''
- sale_order = self.pool.get('sale.order')
- so_ref = procurement.name.split(':')[0]
- order_ids = sale_order.search(cr, uid, [('name', '=', so_ref)], context)
-
- if order_ids:
- sale_ids = sale_order.read(cr, uid, order_ids[0], ['order_line'], context=context)['order_line']
- else:
- so_ref = procurement.origin.split(':')[0]
- sale_ids = sline.search(cr, uid, [('procurement_id', '=',procurement.id)], context)
- l = None
- project_id = None
- analytic_account_id = False
- partner_id = False
-
- for line in sline.browse(cr, uid, sale_ids, context=context):
- content += (line.notes or '')
- l = line
- partner_id = line.order_id.partner_id.id
- if line.order_id.project_id:
- analytic_account_id = line.order_id.project_id.id
- partner_id = line.order_id.partner_id.id
- content+="\n\n"+line.order_id.project_id.complete_name
- break
-
- # Creating a project for task.Project is created from Procurement.
- project_obj = self.pool.get('project.project')
- proj_name = tools.ustr(so_ref)
- proj_exist_id = project_obj.search(cr, uid, [('name', '=', proj_name)], context=context)
- if not proj_exist_id:
- project_id = project_obj.create(cr, uid, {'name': proj_name, 'partner_id': partner_id})
- else:
- project_id = proj_exist_id[0]
-
- self.write(cr, uid, [procurement.id], {'state': 'running'})
-
- name_task = ('','')
- planned_hours=0.0
- if procurement.product_id.type == 'service':
- proc_name = procurement.name
- if procurement.origin == proc_name:
- proc_name = procurement.product_id.name
-
- name_task = (procurement.origin, proc_name or '')
- else:
- name_task = (procurement.product_id.name or procurement.origin, procurement.name or '')
- planned_hours= procurement.product_id.sale_delay +procurement.product_id. produce_delay
- task_id = self.pool.get('project.task').create(cr, uid, {
- 'name': '%s:%s' % name_task,
- 'date_deadline': procurement.date_planned,
- 'planned_hours':planned_hours,
- 'remaining_hours': planned_hours,
- 'user_id': procurement.product_id.product_manager.id,
- 'notes': "b"+(l and l.order_id.note or ''),
- 'procurement_id': procurement.id,
- 'description': content,
- 'date_deadline': procurement.date_planned,
- 'state': 'draft',
- 'partner_id': l and l.order_id.partner_id.id or False,
- 'company_id': procurement.company_id.id,
- 'project_id': project_id,
- },context=context)
- self.write(cr, uid, [procurement.id],{'task_id':task_id})
- product_obj.write(cr,uid,[procurement.product_id.id],{'user_id':uid,'project_id':project_id})
- return task_id
-
-procurement_order()
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
class product_product(osv.osv):
_inherit = "product.product"
_columns = {
- 'user_id': fields.many2one('res.users', 'Responsible', ondelete='set null',help='Project Manager'),
'project_id': fields.many2one('project.project', 'Project', ondelete='set null',)
}
product_product()
<field name="inherit_id" ref="product.product_normal_form_view"/>
<field name="arch" type="xml">
<field name="company_id" position="after">
- <field name="user_id" attrs="{'readonly':[('type','!=','service')]}"/>
<field name="project_id" attrs="{'readonly':[('type','!=','service')]}" />
</field>
</field>
--- /dev/null
+# -*- 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/>.
+#
+##############################################################################
+
+from osv import fields, osv, orm
+
+import tools
+
+class procurement_order(osv.osv):
+ _name = "procurement.order"
+ _inherit = "procurement.order"
+ _columns = {
+ 'task_id': fields.many2one('project.task', 'Task')
+ }
+
+ def action_produce_assign_service(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+ for procurement in self.browse(cr, uid, ids):
+ sline = self.pool.get('sale.order.line')
+ product_obj=self.pool.get('product.product')
+ content = ''
+ sale_order = self.pool.get('sale.order')
+ so_ref = procurement.name.split(':')[0]
+ order_ids = sale_order.search(cr, uid, [('name', '=', so_ref)], context)
+
+ if order_ids:
+ sale_ids = sale_order.read(cr, uid, order_ids[0], ['order_line'], context=context)['order_line']
+ else:
+ so_ref = procurement.origin.split(':')[0]
+ sale_ids = sline.search(cr, uid, [('procurement_id', '=',procurement.id)], context)
+ l = None
+ project_id = None
+ analytic_account_id = False
+ partner_id = False
+
+ for line in sline.browse(cr, uid, sale_ids, context=context):
+ content += (line.notes or '')
+ l = line
+ partner_id = line.order_id.partner_id.id
+ if line.order_id.project_id:
+ analytic_account_id = line.order_id.project_id.id
+ partner_id = line.order_id.partner_id.id
+ content+="\n\n"+line.order_id.project_id.complete_name
+ break
+
+ # Creating a project for task.Project is created from Procurement.
+ project_obj = self.pool.get('project.project')
+ proj_name = tools.ustr(so_ref)
+ product_project_id =procurement.product_id.project_id and procurement.product_id.project_id.id or False
+ proj_exist_id = project_obj.search(cr, uid, [('name', '=', proj_name)], context=context)
+ if not proj_exist_id:
+ project_id = project_obj.create(cr, uid, {'name': proj_name, 'partner_id': partner_id,'parent_id':product_project_id})
+ else:
+ project_id = proj_exist_id[0]
+
+ self.write(cr, uid, [procurement.id], {'state': 'running'})
+
+ name_task = ('','')
+ planned_hours=0.0
+ if procurement.product_id.type == 'service':
+ proc_name = procurement.name
+ if procurement.origin == proc_name:
+ proc_name = procurement.product_id.name
+
+ name_task = (procurement.origin, proc_name or '')
+ else:
+ name_task = (procurement.product_id.name or procurement.origin, procurement.name or '')
+ planned_hours= procurement.product_id.sale_delay +procurement.product_id. produce_delay
+ task_id = self.pool.get('project.task').create(cr, uid, {
+ 'name': '%s:%s' % name_task,
+ 'date_deadline': procurement.date_planned,
+ 'planned_hours':planned_hours,
+ 'remaining_hours': planned_hours,
+ 'user_id': procurement.product_id.product_manager.id,
+ 'notes': "b"+(l and l.order_id.note or ''),
+ 'procurement_id': procurement.id,
+ 'description': content,
+ 'date_deadline': procurement.date_planned,
+ 'state': 'draft',
+ 'partner_id': l and l.order_id.partner_id.id or False,
+ 'company_id': procurement.company_id.id,
+ 'project_id': project_id,
+ },context=context)
+ self.write(cr, uid, [procurement.id],{'task_id':task_id})
+ product_obj.write(cr,uid,[procurement.product_id.id],{'project_id':project_id})
+ return task_id
+
+procurement_order()
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
WHERE user_id=%s and account_id=%s and date>=%s and date<=%s''', (line.user_id.id, line.account_id.id, line.planning_id.date_from, line.planning_id.date_to))
else:
cr.execute('SELECT sum(unit_amount) FROM account_analytic_line WHERE account_id=%s AND date>=%s AND date<=%s', (line.account_id.id, line.planning_id.date_from, line.planning_id.date_to))
- result[line.id] = cr.fetchone()[0] * div2
+
+ sum = cr.fetchone()
+ if sum and sum[0]:
+ result[line.id] = sum[0] * div2
return result
def _sum_amount_tasks(self, cr, uid, ids, name, args, context=None):
WHERE
''' + where + '''
project_id IN (select id from project_project where category_id=%s) AND
- date_close>=%s AND
- date_close<=%s''', (
+ date_end>=%s AND
+ date_end<=%s''', (
line.account_id.id,
line.planning_id.date_from,
line.planning_id.date_to)
)
- result[line.id] = cr.fetchone()[0] /div * div2
+ sum = cr.fetchone()
+ if sum and sum[0]:
+ result[line.id] = sum[0] /div * div2
return result
_columns = {
for task in prj.tasks:
start_dt = (datetime(*time.strptime(task.date_start,'%Y-%m-%d %H:%M:%S')[:6])+(new_end_date-old_end_date)).strftime('%Y-%m-%d %H:%M:%S')
if task.date_deadline:
- deadline_dt = (datetime(*time.strptime(task.date_deadline,'%Y-%m-%d %H:%M:%S')[:6])+(c-d)).strftime('%Y-%m-%d %H:%M:%S')
+ deadline_dt = (datetime(*time.strptime(task.date_deadline,'%Y-%m-%d')[:6])+(new_end_date-old_end_date)).strftime('%Y-%m-%d %H:%M:%S')
self.pool.get('project.task').write(cr, uid, task.id, {'date_start':start_dt, 'date_deadline':deadline_dt})
else:
self.pool.get('project.task').write(cr, uid, task.id, {'date_start':start_dt})
return super(project_project,self).write(cr, uid, ids, vals, *args, **kwargs)
project_project()
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
!record {model: project.project, id: project_project_retroplanning0}:
company_id: base.main_company
- date: '2010-06-11'
+ date: !eval time.strftime('%Y-%m-%d')
name: Retro Planning
-
-
Create task 'Plan all projects'
-
project_id: project_project_retroplanning0
remaining_hours: 24.0
state: draft
-
-
Check if task deadline_date and start_date changes upon changing its project's end_date
-
!python {model: project.project}: |
- from datetime import datetime, date
+ from datetime import datetime, date, timedelta
import time
data_project = self.browse(cr,uid,[ref("project_project_retroplanning0")])
prj = data_project[0]
if prj.date:
old_end_date = date(*time.strptime(prj.date,'%Y-%m-%d')[:3])
if old_end_date:
- new_end_date = date(*time.strptime('2010-06-10','%Y-%m-%d')[:3])
+ new_end_date = date.today()+timedelta(1)
res={}
for task in prj.tasks:
start_dt = (datetime(*time.strptime(task.date_start,'%Y-%m-%d %H:%M:%S')[:6])+(new_end_date-old_end_date)).strftime('%Y-%m-%d %H:%M:%S')
deadline_dt=''
if task.date_deadline:
- deadline_dt = (datetime(*time.strptime(task.date_deadline,'%Y-%m-%d')[:6])+(new_end_date-old_end_date)).strftime('%Y-%m-%d')
+ deadline_dt = (datetime(*time.strptime(task.date_deadline,'%Y-%m-%d')[:6])+(new_end_date-old_end_date)).strftime('%Y-%m-%d')
res[task.id]=[start_dt,deadline_dt]
- self.write(cr, uid, [ref("project_project_retroplanning0")], {'date':'2010-06-10'})
+ self.write(cr, uid, [ref("project_project_retroplanning0")], {'date' : (datetime.now()+timedelta(1)).strftime('%Y-%m-%d')})
data_project = self.browse(cr,uid,[ref("project_project_retroplanning0")])
prj = data_project[0]
+
for task in prj.tasks:
assert task.date_start == res[task.id][0], "task start date differs, expected %s, got %s"%(res[task.id][0], task.date_start)
assert task.date_deadline == res[task.id][1], "task deadline date differs, expected %s, got %s"%(res[task.id][1], task.date_deadline)
\ No newline at end of file
timeline_id = obj_timesheet.create(cr, uid, vals=vals_line, context=kwargs['context'])
# Compute based on pricetype
- amount_unit=obj_timesheet.on_change_unit_amount(cr, uid, timeline_id,
+ amount_unit = obj_timesheet.on_change_unit_amount(cr, uid, timeline_id,
prod_id, amount, unit, context=kwargs['context'])
-
- vals_line['amount'] = (-1) * vals['hours']* (amount_unit['value']['amount'] or 0.0)
+ if amount_unit:
+ vals_line['amount'] = (-1) * vals['hours']* (amount_unit.get('value',{}).get('amount',0.0) or 0.0)
obj_timesheet.write(cr, uid, [timeline_id], vals_line, {})
vals['hr_analytic_timesheet_id'] = timeline_id
return super(project_work,self).create(cr, uid, vals, *args, **kwargs)
unit = False
amount_unit=obj.on_change_unit_amount(cr, uid, line_id,
vals_line['product_id'], vals_line['unit_amount'], unit, context=context)
-
- vals_line['amount'] = (-1) * vals['hours'] * (amount_unit['value']['amount'] or 0.0)
+
+ if amount_unit:
+ vals_line['amount'] = (-1) * vals['hours'] * (amount_unit.get('value',{}).get('amount',0.0) or 0.0)
+
obj.write(cr, uid, [line_id], vals_line, context=context)
return super(project_work,self).write(cr, uid, ids, vals, context)
'test/purchase_from_order.yml',
'test/purchase_from_manual.yml',
# 'test/purchase_from_picking.yml',
- 'purchase_unit_test.xml'
+ 'purchase_unit_test.xml',
+ 'test/procurement_buy.yml',
],
'demo': ['purchase_demo.xml'],
'installable': True,
<record id="trans_confirmed_router" model="workflow.transition">
<field name="act_from" ref="act_confirmed"/>
<field name="act_to" ref="act_router"/>
+ <field name="signal">purchase_approve</field>
</record>
<record id="trans_router_picking" model="workflow.transition">
<field name="act_from" ref="act_router"/>
--- /dev/null
+-
+ In order to test the procurement with product type buy in OpenERP, I will create product
+ and then I will create procurement for this product.
+-
+ I create product.
+-
+ !record {model: product.product, id: product_product_cddrive0}:
+ categ_id: product.product_category_3
+ cost_method: standard
+ mes_type: fixed
+ name: CD drive
+ procure_method: make_to_order
+ supply_method: buy
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+ valuation: manual_periodic
+ volume: 0.0
+ warranty: 0.0
+ weight: 0.0
+ weight_net: 0.0
+ seller_ids:
+ - delay: 1
+ name: base.res_partner_asus
+ qty: 5.0
+-
+ I create procurement order.
+-
+ !record {model: procurement.order, id: procurement_order_testcase0}:
+ company_id: base.main_company
+ date_planned: '2010-07-07 15:38:53'
+ location_id: stock.stock_location_stock
+ name: Test Case
+ priority: '1'
+ procure_method: make_to_order
+ product_id: product_product_cddrive0
+ product_qty: 5.0
+ product_uom: product.product_uom_unit
+ product_uos: product.product_uom_unit
+ product_uos_qty: 0.0
+ state: draft
+-
+ I confirm on procurement order.
+-
+ !workflow {model: procurement.order, action: button_confirm, ref: procurement_order_testcase0}
+-
+ I run the scheduler.
+-
+ !workflow {model: procurement.order, action: button_check, ref: procurement_order_testcase0}
+-
+ I check that purchase order is generated.
+-
+ !python {model: procurement.order}: |
+ from tools.translate import _
+ proc_ids = self.browse(cr, uid, [ref('procurement_order_testcase0')])[0]
+ assert(proc_ids.purchase_id), _('Purchase Order is not Created!')
+-
+ I check the state is running.
+-
+ !python {model: procurement.order}: |
+ from tools.translate import _
+ proc_ids = self.browse(cr, uid, [ref('procurement_order_testcase0')])[0]
+ assert(proc_ids.state == 'running'), _('Exception')
+-
+ I confirm and Approve the purchase order.
+-
+ !python {model: purchase.order}: |
+ procurement_obj = self.pool.get('procurement.order')
+ proc_ids = procurement_obj.browse(cr, uid, [ref('procurement_order_testcase0')])[0]
+ import netsvc
+ wf_service = netsvc.LocalService("workflow")
+ wf_service.trg_validate(uid, 'purchase.order',proc_ids.purchase_id.id,'purchase_confirm', cr)
+ wf_service.trg_validate(uid, 'purchase.order',proc_ids.purchase_id.id,'purchase_approve', cr)
+-
+ I receive the order of the supplier ASUStek from the Incoming Shipments menu.
+-
+ !python {model: stock.picking }: |
+ import time
+ procurement_obj = self.pool.get('procurement.order')
+ proc_ids = procurement_obj.browse(cr, uid, [ref('procurement_order_testcase0')])[0]
+ picking_id = self.search(cr, uid, [('origin', '=', proc_ids.purchase_id.name)])
+ if picking_id:
+ pick=self.browse(cr,uid,picking_id[0])
+ move =pick.move_lines[0]
+ partial_datas = {
+ 'partner_id':pick.address_id.partner_id.id,
+ 'address_id': pick.address_id.id,
+ 'delivery_date' : time.strftime('%Y-%m-%d')
+ }
+ partial_datas['move%s'%(move.id)]= {
+ 'product_id': move.product_id,
+ 'product_qty': move.product_qty,
+ 'product_uom': move.product_uom.id,
+ }
+ self.do_partial(cr, uid, picking_id,partial_datas)
+-
+ I confirm the Reservation.
+-
+ !python {model: stock.move }: |
+ procurement_obj = self.pool.get('procurement.order')
+ proc_ids = procurement_obj.browse(cr, uid, [ref('procurement_order_testcase0')])[0]
+ self.action_done(cr,uid,[proc_ids.move_id.id])
+-
+ I check the state is Done.
+-
+ !python {model: procurement.order}: |
+ from tools.translate import _
+ proc_ids = self.browse(cr, uid, [ref('procurement_order_testcase0')])[0]
+ assert(proc_ids.state == 'done'), _('Order is not in done state')
_("You cannot make an advance on a sale order \
that is defined as 'Automatic Invoice after delivery'."))
val = obj_lines.product_id_change(cr, uid, [], sale_adv_obj.product_id.id,
- uom = False, partner_id = sale.partner_id.id, fiscal_position = sale.fiscal_position.id)
+ uom = False, partner_id = sale.partner_id.id, fposition_id = sale.fiscal_position.id)
line_id =obj_lines.create(cr, uid, {
'name': val['value']['name'],
'account_id': val['value']['account_id'],
'author': 'Tiny & Axelor',
'website': 'http://openerp.com',
'depends': ['knowledge'],
+ 'web_depends': ['widget_wiki'],
'init_xml': [],
'update_xml': [
'wizard/wiki_wiki_page_open_view.xml',