Remove follows and set activities

This commit is contained in:
oscar alvarez 2023-10-30 15:23:03 -05:00
parent 54aa08e7f5
commit a9ef856596
14 changed files with 224 additions and 129 deletions

View File

@ -1,2 +1,6 @@
ALTER TABLE crm_opportunity_line RENAME time_ammount TO billing_frecuency;
ALTER TABLE crm_opportunity DROP COLUMN source;
DROP TABLE crm_activity;
DROP TABLE crm_opportunity_follow_up;

View File

@ -31,10 +31,11 @@ def register():
party.Party,
sale.Sale,
activity.Activity,
opportunity.Prospect,
opportunity.Opportunity,
opportunity.LeadOrigin,
opportunity.CrmOpportunityLine,
opportunity.CrmOpportunityFollowUp,
# opportunity.CrmOpportunityFollowUp,
opportunity.OpportunityCancellReason,
opportunity.OpportunitySaleConditions,
ir.Cron,

View File

@ -1,13 +1,8 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from __future__ import with_statement
from trytond.model import Workflow, ModelView, ModelSQL, fields
from trytond.pyson import Eval, If, In, Get
from trytond.transaction import Transaction
from trytond.pool import Pool
from .exceptions import CrmConfigurationError
from trytond.i18n import gettext
from trytond.pyson import Eval
STATES = {
'readonly': (Eval('state') != 'draft'),
@ -15,33 +10,36 @@ STATES = {
class Activity(Workflow, ModelSQL, ModelView):
'Activity'
'CRM Activity'
__name__ = 'crm.activity'
_rec_name = 'number'
number = fields.Char('Number', readonly=True)
contact = fields.Char('Contact', states=STATES, required=True, select=True)
customer = fields.Many2One('party.party', 'Customer', states=STATES, select=True)
subject = fields.Char('Subject', states=STATES, select=True)
media = fields.Selection([
('phone', 'Phone'),
('mobile', 'Mobile'),
('videochat', 'Videochat'),
_rec_name = 'subject'
opportunity = fields.Many2One('crm.opportunity', 'Opportunity',
required=True, readonly=True)
subject = fields.Char('Subject', states={
'readonly': (Eval('state') == 'done'),
})
type_= fields.Selection([
('call', 'Call'),
('on_site_appointment', 'On-Site Appointment'),
('virtual_appointment', 'Virtual Appointment'),
('chat', 'Chat'),
('email', 'Email'),
], 'Media', states=STATES, depends=['state'], required=True)
media_info = fields.Char('Media Info', states=STATES)
], 'Type', states=STATES, depends=['state'], required=True)
type_info = fields.Char('Type Info', states=STATES)
planned_date = fields.Date('Planned Date', states=STATES, required=True)
planned_time = fields.Time('Planned Time', states=STATES)
duration = fields.Integer('Duration', help="In minutes", states=STATES)
effective_date = fields.Date('Effective Date', states=STATES)
notes = fields.Text('Notes', states=STATES)
company = fields.Many2One('company.company', 'Company', required=True,
states=STATES, domain=[ ('id', If(In('company',
Eval('context', {})), '=', '!='), Get(Eval('context', {}),
'company', 0)), ])
description = fields.Text('Description', states=STATES)
agent = fields.Many2One('commission.agent', 'Agent', required=False)
customer = fields.Function(fields.Many2One(
'crm.prospect', 'Customer', required=False), 'get_customer')
state = fields.Selection([
('draft', 'Draft'),
('pending', 'Pending'),
('planned', 'Planned'),
('done', 'Done'),
('cancelled', 'Cancelled'),
], 'State', readonly=True, required=True)
], 'State', required=True)
state_string = state.translated('state')
@classmethod
@ -50,12 +48,12 @@ class Activity(Workflow, ModelSQL, ModelView):
cls._order.insert(0, ('planned_date', 'DESC'))
cls._order.insert(1, ('id', 'DESC'))
cls._transitions |= set((
('draft', 'pending'),
('pending', 'done'),
('pending', 'draft'),
('pending', 'cancelled'),
('cancelled', 'draft'),
))
('draft', 'pending'),
('pending', 'done'),
('pending', 'draft'),
('pending', 'cancelled'),
('cancelled', 'draft'),
))
cls._buttons.update({
'draft': {
'invisible': Eval('state').in_(['draft', 'done']),
@ -104,18 +102,8 @@ class Activity(Workflow, ModelSQL, ModelView):
def draft(cls, records):
pass
def set_number(self):
'''
Set sequence number
'''
if self.number:
return
pool = Pool()
Config = pool.get('crm.configuration')
config = Config.get_configuration()
if not config.activity_sequence:
raise CrmConfigurationError(
gettext('crm.msg_missing_sequence_activity'))
seq = config.activity_sequence.get()
self.write([self], {'number': seq})
def get_customer(self, name=None):
if self.opportunity and self.opportunity.prospect:
return self.opportunity.prospect.id
else:
return self.opportunity.contact

View File

@ -3,7 +3,6 @@
this repository contains the full copyright notices and license terms. -->
<tryton>
<data>
<record model="ir.ui.view" id="activity_view_tree">
<field name="model">crm.activity</field>
<field name="type">tree</field>
@ -15,22 +14,79 @@ this repository contains the full copyright notices and license terms. -->
<field name="type">form</field>
<field name="name">activity_form</field>
</record>
<record model="ir.action.act_window" id="act_activity_tree">
<record model="ir.action.act_window" id="act_activity_form">
<field name="name">Activity</field>
<field name="res_model">crm.activity</field>
</record>
<record model="ir.action.act_window.view" id="act_activity_tree_view1">
<field name="sequence" eval="1"/>
<field name="view" ref="activity_view_tree"/>
<field name="act_window" ref="act_activity_tree"/>
<field name="act_window" ref="act_activity_form"/>
</record>
<record model="ir.action.act_window.view" id="act_activity_tree_view2">
<field name="sequence" eval="2"/>
<field name="view" ref="activity_view_form"/>
<field name="act_window" ref="act_activity_tree"/>
<field name="act_window" ref="act_activity_form"/>
</record>
<menuitem parent="crm.menu_crm" sequence="20"
action="act_activity_tree" id="menu_activity_tree"/>
action="act_activity_form" id="menu_crm_activity"/>
<record model="ir.action.act_window.domain"
id="act_crm_activity_form_domain_today">
<field name="name">Today</field>
<field name="sequence" eval="10"/>
<field name="domain"
eval="[
('planned_date', '=', Date()),
]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_activity_form"/>
</record>
<record model="ir.action.act_window.domain"
id="act_crm_activity_form_domain_week">
<field name="name">This Week</field>
<field name="sequence" eval="10"/>
<field name="domain"
eval="[
('planned_date', '>=', Date()),
('planned_date', '&lt;', Date(delta_days=7)),
]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_activity_form"/>
</record>
<record model="ir.action.act_window.domain"
id="act_crm_activity_form_domain_draft">
<field name="name">Draft</field>
<field name="sequence" eval="20"/>
<field name="domain" eval="[('state', '=', 'draft')]" pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_activity_form"/>
</record>
<record model="ir.action.act_window.domain"
id="act_crm_activity_form_domain_planned">
<field name="name">Planned</field>
<field name="sequence" eval="30"/>
<field name="domain" eval="[('state', '=', 'planned')]" pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_activity_form"/>
</record>
<record model="ir.action.act_window.domain"
id="act_crm_activity_form_domain_done">
<field name="name">Done</field>
<field name="sequence" eval="40"/>
<field name="domain" eval="[('state', '=', 'done')]" pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_activity_form"/>
</record>
<record model="ir.action.act_window.domain"
id="act_crm_activity_form_domain_all">
<field name="name">All</field>
<field name="sequence" eval="9999"/>
<field name="domain"></field>
<field name="count" eval="True"/>
<field name="act_window" ref="act_activity_form"/>
</record>
<record model="ir.model.access" id="access_crm_activity">
<field name="model" search="[('model', '=', 'crm.activity')]"/>

View File

@ -25,13 +25,12 @@ class Configuration(ModelSQL, ModelView):
# 'Activity Sequence', required=True)
# domain=[('sequence_type', '=', Id('crm', 'sequence_type_activity'))])
opportunity_sequence = fields.Many2One(
'ir.sequence', "Opportunity Sequence", required=True,
domain=[
('company', 'in', [Eval('context', {}).get('company', -1),
None]),
('sequence_type', '=',
Id('crm', 'sequence_type_crm_opportunity')),
])
'ir.sequence', "Opportunity Sequence", required=True,
domain=[
('company', 'in', [Eval('context', {}).get('company', -1), None]),
('sequence_type', '=',
Id('crm', 'sequence_type_crm_opportunity')),
])
efficay_hour_limit = fields.Integer('Efficay Hour Limit')
@staticmethod

View File

@ -28,6 +28,15 @@ class LeadOrigin(ModelSQL, ModelView):
name = fields.Char("Lead Origin")
class Prospect(ModelSQL, ModelView):
'CRM Prospect'
__name__ = 'crm.prospect'
name = fields.Char("Name", required=True)
phone = fields.Char('Contact Phone')
email = fields.Char('Email')
agent = fields.Many2One('commission.agent', 'Agent')
class Opportunity(
Workflow, ModelSQL, ModelView,
AttachmentCopyMixin, NoteCopyMixin):
@ -49,6 +58,7 @@ class Opportunity(
}
_depends_stop = ['state']
number = fields.Char('Number', readonly=True, required=True)
prospect = fields.Many2One('crm.prospect', 'Prospect', required=True)
party_contact = fields.Char('Party Contact', states=_states_opp)
contact_phone = fields.Char('Contact Phone', states=_states_opp)
contact_email = fields.Char('Email')
@ -126,11 +136,9 @@ class Opportunity(
'readonly': Eval('state').in_(['won', 'lost']),
# 'required': ~Eval('state').in_(['lead', 'lost', 'cancelled']),
})
follow_ups = fields.One2Many('crm.opportunity.follow_up',
'opportunity', 'Follow-Ups',
activities = fields.One2Many('crm.activity', 'opportunity', 'Activities',
states={
'readonly': Eval('state').in_(['won', 'lost']),
# 'required': ~Eval('state').in_(['lead', 'lost', 'cancelled']),
})
conversion_probability = fields.Float('Conversion Probability',
digits=(1, 4), required=True,
@ -654,23 +662,23 @@ class OpportunityCancellReason(ModelSQL, ModelView):
# opportunity = fields.Many2One('crm.opportunity', 'Opportunity')
class CrmOpportunityFollowUp(sequence_ordered(), ModelSQL, ModelView):
'CRM Opportunity FollowUp'
__name__ = "crm.opportunity.follow_up"
opportunity = fields.Many2One('crm.opportunity', 'Opportunity',
required=True)
follow_date = fields.Date('Follow Date')
action = fields.Char('Action')
notes = fields.Text('Notes')
done_by = fields.Many2One('res.user', 'Done By')
state = fields.Selection([
('draft', "Draft"),
('done', "Done"),
], "State", required=False, readonly=True)
@staticmethod
def default_state():
return 'draft'
# class CrmOpportunityFollowUp(sequence_ordered(), ModelSQL, ModelView):
# 'CRM Opportunity FollowUp'
# __name__ = "crm.opportunity.follow_up"
# opportunity = fields.Many2One('crm.opportunity', 'Opportunity',
# required=True)
# follow_date = fields.Date('Follow Date')
# action = fields.Char('Action')
# notes = fields.Text('Notes')
# done_by = fields.Many2One('res.user', 'Done By')
# state = fields.Selection([
# ('draft', "Draft"),
# ('done', "Done"),
# ], "State", required=False, readonly=True)
#
# @staticmethod
# def default_state():
# return 'draft'
class CrmOpportunityLine(sequence_ordered(), ModelSQL, ModelView):

View File

@ -29,27 +29,43 @@ this repository contains the full copyright notices and license terms. -->
<field name="group" ref="sale.group_sale_admin"/>
</record>
<record model="ir.ui.view" id="crm_prospect_view_form">
<field name="model">crm.prospect</field>
<field name="type">form</field>
<field name="name">prospect_form</field>
</record>
<record model="ir.ui.view" id="crm_prospect_view_tree">
<field name="model">crm.prospect</field>
<field name="type">tree</field>
<field name="name">prospect_tree</field>
</record>
<record model="ir.action.act_window" id="act_crm_prospect_form">
<field name="name">Prospect</field>
<field name="res_model">crm.prospect</field>
</record>
<record model="ir.action.act_window.view" id="act_crm_prospect_form_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="crm_prospect_view_tree"/>
<field name="act_window" ref="act_crm_prospect_form"/>
</record>
<record model="ir.action.act_window.view" id="act_crm_prospect_form_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="crm_prospect_view_form"/>
<field name="act_window" ref="act_crm_prospect_form"/>
</record>
<menuitem parent="crm.menu_crm" action="act_crm_prospect_form"
sequence="5" id="menu_crm_prospect_form"/>
<record model="ir.ui.view" id="crm_opportunity_view_form">
<field name="model">crm.opportunity</field>
<field name="type">form</field>
<field name="name">opportunity_form</field>
</record>
<record model="ir.ui.view" id="crm_opportunity_view_tree">
<field name="model">crm.opportunity</field>
<field name="type">tree</field>
<field name="name">opportunity_tree</field>
</record>
<!-- <record model="ir.sequence.type" id="sequence_type_sale_crm_opportunity">
<field name="name">Sale Opportunity</field>
</record>
<record model="ir.sequence" id="sequence_sale_crm_opportunity">
<field name="name">Sale Opportunity</field>
<field name="sequence_type" ref="sequence_type_sale_crm_opportunity"/>
</record> -->
<record model="ir.action.act_window" id="act_crm_opportunity_form">
<field name="name">Opportunities</field>
<field name="res_model">crm.opportunity</field>

View File

@ -1,5 +1,5 @@
[tryton]
version=6.0.16
version=6.0.17
depends:
party
sale

View File

@ -2,33 +2,30 @@
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form>
<label name="contact"/>
<field name="contact"/>
<label name="company"/>
<field name="company"/>
<label name="subject"/>
<field name="subject"/>
<label name="opportunity"/>
<field name="opportunity" widget="selection"/>
<label name="customer"/>
<field name="customer"/>
<label name="number"/>
<field name="number"/>
<label name="media"/>
<field name="media" widget="selection"/>
<label name="media_info"/>
<field name="media_info"/>
<label name="planned_date"/>
<field name="planned_date"/>
<label name="effective_date"/>
<field name="effective_date"/>
<newline/>
<label name="subject"/>
<field name="subject" colspan="3"/>
<separator name="notes" colspan="4"/>
<field name="notes" colspan="4"/>
<notebook colspan="4">
<page string="Sales" id="sales">
</page>
<page string="Deals" id="deals">
</page>
</notebook>
<label name="type_"/>
<field name="type_"/>
<label name="type_info"/>
<field name="type_info"/>
<group col="6" colspan="4" id="dates">
<label name="planned_date"/>
<field name="planned_date"/>
<label name="planned_time"/>
<field name="planned_time"/>
<label name="effective_date"/>
<field name="effective_date"/>
</group>
<label name="agent"/>
<field name="agent"/>
<label name="duration"/>
<field name="duration"/>
<separator name="description" colspan="4"/>
<field name="description" colspan="4"/>
<group col="4" colspan="4" id="state_buttons">
<label name="state"/>
<field name="state"/>
@ -37,7 +34,7 @@ this repository contains the full copyright notices and license terms. -->
icon="tryton-cancel"/>
<button name="draft" string="Draft"
icon="tryton-clear"/>
<button name="pending" string="Pending"
<button name="planned" string="Planned"
icon="tryton-ok"/>
<button name="done" string="Done"
icon="tryton-ok"/>

View File

@ -2,12 +2,13 @@
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tree>
<field name="number"/>
<field name="contact"/>
<field name="customer"/>
<field name="media"/>
<field name="planned_date"/>
<field name="effective_date"/>
<field name="state"/>
<field name="company"/>
<field name="opportunity" expand="1"/>
<field name="customer" expand="1"/>
<field name="type_" expand="1"/>
<field name="subject" expand="1"/>
<field name="planned_date" expand="1"/>
<field name="planned_time" expand="1"/>
<field name="effective_date" expand="1"/>
<field name="agent" expand="1"/>
<field name="state" expand="1"/>
</tree>

View File

@ -2,6 +2,8 @@
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form col="6">
<label name="prospect"/>
<field name="prospect"/>
<label name="party_contact"/>
<field name="party_contact"/>
<label name="contact_phone"/>
@ -34,19 +36,19 @@ this repository contains the full copyright notices and license terms. -->
<field name="description" colspan="3"/>
<label name="city"/>
<field name="city" widget="selection"/>
<label name="party_category"/>
<field name="party_category" widget="selection"/>
<notebook colspan="6">
<page string="Opportunity" id="opportunity">
<label name="payment_term"/>
<field name="payment_term" widget="selection"/>
<label name="company"/>
<field name="company"/>
<field name="company" widget="selection"/>
<label name="start_date"/>
<field name="start_date"/>
<label name="end_date"/>
<field name="end_date"/>
<label name="party_category"/>
<field name="party_category" widget="selection"/>
<field name="follow_ups" colspan="4"/>
<field name="activities" colspan="4"/>
<separator name="comment" colspan="4"/>
<field name="comment" colspan="4"/>
<label name="cancelled_reason"/>

View File

@ -6,6 +6,7 @@ this repository contains the full copyright notices and license terms. -->
<field name="reference" expand="1"/>
<field name="start_date"/>
<field name="end_date"/>
<field name="prospect" expand="1"/>
<field name="party_contact" expand="1"/>
<field name="contact_phone" expand="1"/>
<field name="agent" expand="1"/>

13
view/prospect_form.xml Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form>
<label name="name"/>
<field name="name"/>
<label name="phone"/>
<field name="phone"/>
<label name="email"/>
<field name="email"/>
<label name="agent"/>
<field name="agent" widget="selection"/>
</form>

9
view/prospect_tree.xml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tree>
<field name="name" expand="1"/>
<field name="phone" expand="1"/>
<field name="email" expand="1"/>
<field name="agent" expand="1"/>
</tree>