Re-engineering

This commit is contained in:
oscar alvarez 2023-05-18 22:51:13 -05:00
parent 13398f774b
commit 827db71f79
19 changed files with 351 additions and 161 deletions

View File

@ -13,11 +13,12 @@ from . import party_validation
from . import contract
from . import ir
from . import company
from . import dash
from . import commission
def register():
Pool.register(
# exceptions.IncompletePartyValidation,
survey.SurveyGroup,
survey.SurveyTemplate,
survey.SurveyTemplateLine,
@ -33,26 +34,20 @@ def register():
activity.Activity,
opportunity.Opportunity,
opportunity.CrmOpportunityLine,
#opportunity.PartyValidationOpportunity,
#opportunity.OpportunityTraceability,
#opportunity.OpportunityKind,
#opportunity.OpportunityKindConcept,
opportunity.CrmOpportunityFollowUp,
opportunity.OpportunityCancellReason,
ir.Cron,
# opportunity.PartyEvaluationConcept,
# opportunity.PartyEvaluation,
# party_validation.Validation,
# party_validation.ValidationGroup,
party_validation.ValidationTemplate,
party_validation.ValidationTemplateAsk,
party_validation.OpportunityValidation,
party_validation.ValidationHistoryAsk,
contract.Contract,
company.Company,
# opportunity.OpportunityEmployee,
# opportunity.OpportunityEmployeeContext,
# opportunity.OpportunityMonthly,
# opportunity.OpportunityEmployeeMonthly,
dash.DashApp,
dash.AppCRMSales,
dash.AppCRMService,
dash.AppCRMMarketing,
commission.Agent,
module='crm', type_='model')
Pool.register(
customer_service.CustomerServiceReport,

10
commission.py Normal file
View File

@ -0,0 +1,10 @@
# 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 trytond.pool import PoolMeta
from trytond.model import fields
class Agent(metaclass=PoolMeta):
__name__ = 'commission.agent'
employee = fields.Many2One('company.employee', 'Employee',
help="Associates the employee with the agent")

19
commission.xml Normal file
View File

@ -0,0 +1,19 @@
<?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. -->
<tryton>
<data>
<record model="ir.ui.view" id="agent_view_form">
<field name="model">commission.agent</field>
<field name="inherit" ref="commission.agent_view_form"/>
<field name="name">agent_form</field>
</record>
<!-- <record model="ir.ui.view" id="commission_agent_view_list">
<field name="model">commission.agent</field>
<field name="inherit" ref="commission.commission_agent_view_list"/>
<field name="name">agent_list</field>
</record> -->
</data>
</tryton>

View File

@ -1,5 +1,6 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# 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 trytond.model import ModelView, ModelSQL, fields
from trytond.transaction import Transaction
from trytond.pyson import Id
@ -9,22 +10,19 @@ from trytond.pyson import Eval
class Configuration(ModelSQL, ModelView):
'CRM Configuration'
__name__ = 'crm.configuration'
company = fields.Many2One('company.company', 'Company', required=True)
customer_service_sequence = fields.Many2One('ir.sequence',
'Customer Service Sequence', required=True,
domain=[('sequence_type', '=',
Id('crm', 'sequence_type_crm'))])
domain=[('sequence_type', '=', Id('crm', 'sequence_type_crm'))])
survey_sequence = fields.Many2One('ir.sequence',
'Survey Sequence', required=True,
domain=[('sequence_type', '=',
Id('crm', 'sequence_type_survey_service'))])
efficay_hour_limit = fields.Integer('Efficay Hour Limit',
required=True)
response_time_customer = fields.Integer('Response Time Customer',
required=True, help="Limit in hours for response to customer")
activity_sequence = fields.Many2One('ir.sequence',
'Activity Sequence', required=True,
domain=[('sequence_type', '=',
Id('crm', 'sequence_type_activity'))])
company = fields.Many2One('company.company', 'Company', required=True)
domain=[('sequence_type', '=', Id('crm', 'sequence_type_activity'))])
opportunity_sequence = fields.Many2One(
'ir.sequence', "Opportunity Sequence", required=True,
domain=[

View File

@ -30,7 +30,9 @@
<field name="group" ref="group_crm"/>
</record>
<menuitem name="Reports" parent="menu_crm" id="menu_reports" sequence="100" active="100"/>
<menuitem name="Reports" parent="menu_crm" id="menu_reports"
sequence="200"
active="100"/>
</data>
</tryton>

View File

@ -71,8 +71,9 @@ this repository contains the full copyright notices and license terms. -->
<field name="domain"></field>
<field name="act_window" ref="act_customer_service_form"/>
</record>
<menuitem parent="menu_crm" sequence="120"
action="act_customer_service_form" id="menu_customer_service_form"/>
<menuitem parent="menu_crm" sequence="40"
action="act_customer_service_form"
id="menu_customer_service_form"/>
<!-- Buttons -->
<record model="ir.model.button" id="customer_service_cancel_button">

47
dash.py Normal file
View File

@ -0,0 +1,47 @@
# 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 trytond.pool import PoolMeta
from trytond.modules.dash.dash import DashAppBase
class DashApp(metaclass=PoolMeta):
__name__ = "dash.app"
@classmethod
def _get_origin(cls):
origins = super(DashApp, cls)._get_origin()
origins.extend(
[
"dash.app.crm_sales",
"dash.app.crm_service",
"dash.app.crm_marketing",
]
)
return origins
@classmethod
def get_selection(cls):
options = super(DashApp, cls).get_selection()
options.extend(
[
("crm_sales", "CRM Sales"),
("crm_service", "CRM Service"),
("crm_marketing", "CRM Marketing"),
]
)
return options
class AppCRMSales(DashAppBase):
"App CRM Sales"
__name__ = "dash.app.crm_sales"
class AppCRMService(DashAppBase):
"App CRM Service"
__name__ = "dash.app.crm_service"
class AppCRMMarketing(DashAppBase):
"App CRM Marketing"
__name__ = "dash.app.crm_marketing"

89
dash.xml Normal file
View File

@ -0,0 +1,89 @@
<?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. -->
<tryton>
<data noupdate="1">
<record model="dash.app.crm_sales" id="dash_app_crm_sales">
<field name="company">1</field>
<field name="icon">th</field>
<field name="kind">internal</field>
</record>
<record model="dash.app" id="app_crm_sales">
<field name="name">CRM Sales</field>
<field name="origin">dash.app.crm_sales,1</field>
<field name="active">True</field>
<field name="app_name">crm_sales</field>
</record>
<record model="dash.app.crm_service" id="dash_app_crm_service">
<field name="company">1</field>
<field name="icon">key</field>
<field name="kind">internal</field>
</record>
<record model="dash.app" id="app_crm_service">
<field name="name">CRM Service</field>
<field name="origin">dash.app.crm_service,1</field>
<field name="active">True</field>
<field name="app_name">crm_service</field>
</record>
<record model="dash.app.crm_marketing" id="dash_app_crm_marketing">
<field name="company">1</field>
<field name="icon">key</field>
<field name="kind">external</field>
</record>
<record model="dash.app" id="app_crm_marketing">
<field name="name">CRM Marketing</field>
<field name="origin">dash.app.crm_marketing,1</field>
<field name="active">True</field>
<field name="app_name">crm_marketing</field>
</record>
</data>
<data>
<!-- <record model="dash.report" id="dash_report_checkin_today">
<field name="name">Check-In Today</field>
<field name="model">hotel.folio</field>
<field name="type">card_info</field>
<field name="method">report_check_in_today</field>
</record>
<record model="dash.report" id="dash_report_checkout_today">
<field name="name">Check-Out Today</field>
<field name="model">hotel.folio</field>
<field name="type">card_info</field>
<field name="method">report_check_out_today</field>
</record>
<record model="dash.report" id="dash_report_occupation_by_room">
<field name="name">Occupation Today</field>
<field name="model">hotel.folio</field>
<field name="type">card_info</field>
<field name="method">report_occupation_by_room</field>
</record>
<record model="dash.report" id="dash_report_number_guests">
<field name="name">Number Guests</field>
<field name="model">hotel.folio</field>
<field name="type">card_info</field>
<field name="method">report_number_guests</field>
</record>
<record model="dash.report" id="dash_report_current_occupancy_rate">
<field name="name">Current Occupancy Rate</field>
<field name="model">hotel.folio</field>
<field name="type">card_info</field>
<field name="method">report_current_occupancy_rate</field>
</record>
<record model="dash.report" id="dash_report_month_occupancy_rate">
<field name="name">Month Occupancy Rate</field>
<field name="model">hotel.folio</field>
<field name="type">line</field>
<field name="method">report_month_occupancy_rate</field>
</record> -->
</data>
</tryton>

View File

@ -25,7 +25,7 @@ from trytond.exceptions import UserError
from .exceptions import IncompletePartyValidation, ChangeStateWarning
from trytond.ir.attachment import AttachmentCopyMixin
from trytond.ir.note import NoteCopyMixin
from trytond.modules.company.model import employee_field, set_employee
# from trytond.modules.company.model import employee_field, set_employee
class Opportunity(
@ -52,10 +52,9 @@ class Opportunity(
number = fields.Char('Number', readonly=True, required=True, select=True)
reference = fields.Char('Reference', select=True,
states={
'readonly': Eval('state').in_(['converted', 'won', 'cancelled', 'lost'])
})
states={
'readonly': Eval('state').in_(['converted', 'won', 'cancelled', 'lost'])
})
# kind_opportunity = fields.Many2One('crm.opportunity_kind_concept', 'Opportunity Kind Concept', select=True,
# states={
# 'readonly': ~Eval('state').in_(['prospecting', 'quote_revision', 'review'])
@ -71,6 +70,7 @@ class Opportunity(
depends=['state', 'company'], required=True)
contact = fields.Many2One(
'party.contact_mechanism', "Contact",
domain=[('party', '=', Eval('party'))],
context={
'company': Eval('company', -1),
},
@ -100,9 +100,9 @@ class Opportunity(
],
depends=_depends_stop)
currency = fields.Function(fields.Many2One('currency.currency',
'Currency'), 'get_currency')
'Currency'), 'get_currency')
currency_digits = fields.Function(fields.Integer('Currency Digits'),
'get_currency_digits')
'get_currency_digits')
amount = fields.Numeric('Amount', digits=(16, Eval('currency_digits', 2)),
states={
'readonly': ~Eval('state').in_(['won', 'lost']),
@ -110,18 +110,9 @@ class Opportunity(
}, depends=_depends_stop +
['currency_digits'],
help='Estimated revenue amount.')
time_ammount = fields.Selection([
('monthly', "Monthly"),
('bimonthly', "Bimonthly"),
('biannual', "Biannual"),
('annual', "Annual")], "Time Ammount", select=True, sort=False,
states={
'readonly': Eval('state').in_(['won', 'lost'])
})
payment_term = fields.Many2One('account.invoice.payment_term',
'Payment Term')
employee = fields.Many2One('company.employee', 'Employee',
agent = fields.Many2One('commission.agent', 'Agent',
states={
'readonly': Eval('state').in_(['won', 'lost'])
},
@ -132,16 +123,22 @@ class Opportunity(
end_date = fields.Date('End Date', select=True,
states=_states_stop, depends=_depends_stop)
description = fields.Char('Description',
states={
'readonly': Eval('state').in_(['won', 'lost']),
# 'required': ~Eval('state').in_(['lead', 'lost', 'cancelled']),
})
states={
'readonly': Eval('state').in_(['won', 'lost']),
# 'required': ~Eval('state').in_(['lead', 'lost', 'cancelled']),
})
comment = fields.Text('Comment', states=_states_stop, depends=_depends_stop)
lines = fields.One2Many('crm.opportunity.line', 'opportunity', 'Lines',
states={
'readonly': Eval('state').in_(['won', 'lost']),
# 'required': ~Eval('state').in_(['lead', 'lost', 'cancelled']),
})
states={
'readonly': Eval('state').in_(['won', 'lost']),
# 'required': ~Eval('state').in_(['lead', 'lost', 'cancelled']),
})
follow_ups = fields.One2Many('crm.opportunity.follow_up',
'opportunity', 'Follow-Ups',
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,
domain=[
@ -157,9 +154,8 @@ class Opportunity(
}, depends=['state'])
sales = fields.One2Many('sale.sale', 'origin', 'Sales')
contracts = fields.One2Many('sale.contract', 'origin', 'Contracts')
converted_by = employee_field(
"Converted By", states=['converted', 'won', 'lost'])
# converted_by = employee_field(
# "Converted By", states=['converted', 'won', 'lost'])
# state = fields.Selection([
# ('prospecting', "Prospecting"),
# ('analysis', "Analysis"),
@ -182,15 +178,13 @@ class Opportunity(
('lost', 'Lost'),
], "State", required=True, select=True,
sort=False, readonly=True)
type = fields.Selection([
('sale', 'Sale'),
('contract', 'Contract'),
], "Type", required=True, select=True,
states={
'readonly': Eval('state').in_(['won', 'lost'])
})
], "Type", required=True, select=True,
states={
'readonly': Eval('state').in_(['won', 'lost'])
})
source = fields.Selection([
('website', 'Website'),
('phone', 'Phone'),
@ -198,15 +192,13 @@ class Opportunity(
('whatsapp', 'WhatsApp'),
('salesman', 'Salesman'),
('referred', 'Referred'),
], "Source", required=True, select=True,
states={
'readonly': Eval('state').in_(['converted', 'won', 'lost'])
})
total = fields.Function(fields.Float('Total'),
'get_total_opportunity')
], "Source", required=True, select=True,
states={
'readonly': Eval('state').in_(['converted', 'won', 'lost'])
})
total = fields.Function(fields.Float('Total'), 'get_total_opportunity')
total_without_tax = fields.Function(fields.Float('Total'),
'get_total_without_tax_opportunity')
'get_total_without_tax_opportunity')
# cancelled_reason = fields.Selection([
# ('',''),
# ('Sin acuerdo', "No se llego a un acuerdo"),
@ -214,17 +206,16 @@ class Opportunity(
# states={
# 'invisible': ~Eval('state').in_(['analysis', 'review', 'quote_revision', 'cancelled', 'lost'])
# }, depends=['state'])
# states={
# 'readonly': ~Eval('state').in_(['prospecting', 'analysis'])
# }
cancelled_reason = fields.Many2One('crm.opportunity_cancelled_reason', 'Cancelled Reason Concept', select=True,
states={
#'readonly': ~Eval('state').in_(['prospecting', 'quote_revision', 'review']),
'invisible': ~Eval('state').in_(['won'])
}, depends=['state'])
cancelled_reason = fields.Many2One(
'crm.opportunity_cancelled_reason', 'Cancelled Reason Concept',
select=True,
states={
#'readonly': ~Eval('state').in_(['prospecting', 'quote_revision', 'review']),
'invisible': ~Eval('state').in_(['won'])
}, depends=['state'])
party_validations = fields.One2Many('crm.opportunity.validation',
'opportunity', 'Party Validations')
is_prospect = fields.Function(fields.Boolean('Is Prospect'), 'get_is_prospect')
@ -239,7 +230,7 @@ class Opportunity(
('opportunity', 'converted'),
('opportunity', 'cancelled'),
('cancelled', 'opportunity'),
('cancelled', 'converted'),
('cancelled', 'converted'),
('converted', 'cancelled'),
('converted', 'opportunity'),
('converted', 'won'),
@ -260,7 +251,6 @@ class Opportunity(
},
'lost': {
'invisible': ~Eval('state').in_(['converted']),
},
'cancelled': {
'invisible': Eval('state').in_(['lead', 'won', 'lost', 'cancelled']),
@ -289,8 +279,6 @@ class Opportunity(
# res = False
# return res
@staticmethod
def default_state():
return 'lead'
@ -308,10 +296,6 @@ class Opportunity(
def default_company():
return Transaction().context.get('company')
@staticmethod
def default_employee():
return Transaction().context.get('employee')
@classmethod
def default_payment_term(cls):
PaymentTerm = Pool().get('account.invoice.payment_term')
@ -363,6 +347,7 @@ class Opportunity(
default = default.copy()
default.setdefault('number', None)
default.setdefault('sales', None)
default.setdefault('contracts', None)
default.setdefault('converted_by')
return super(CrmOpportunity, cls).copy(opportunities, default=default)
@ -396,7 +381,7 @@ class Opportunity(
return {
'description':self.description,
'party':self.party,
'salesman':self.employee,
# 'salesman':self.employee,
'payment_term':self.payment_term,
'company':self.company,
'currency':self.company.currency,
@ -421,7 +406,7 @@ class Opportunity(
contact=self.contact,
payment_term=self.payment_term,
company=self.company,
salesman=self.employee,
# salesman=self.employee,
invoice_address=self.address,
shipment_address=self.address,
reference=self.reference,
@ -539,22 +524,22 @@ class Opportunity(
def quote_approbation(cls, records):
pass
@classmethod
@ModelView.button
@Workflow.transition('quotation')
@set_employee('converted_by')
def quotation(cls, records):
# Analyze if party validation is true in all lines
cls.get_party_validation(records)
# cls.procces_opportunity(records)
history = []
for record in records:
value = {
'opportunity':record.id,
'create_date':date.today(),
'action':'Cambio de estado a Cotización'
}
history.append(value)
# @classmethod
# @ModelView.button
# @Workflow.transition('quotation')
# @set_employee('converted_by')
# def quotation(cls, records):
# # Analyze if party validation is true in all lines
# cls.get_party_validation(records)
# # cls.procces_opportunity(records)
# history = []
# for record in records:
# value = {
# 'opportunity':record.id,
# 'create_date':date.today(),
# 'action':'Cambio de estado a Cotización'
# }
# history.append(value)
@property
def is_forecast(self):
@ -749,6 +734,16 @@ class OpportunityCancellReason(ModelSQL, ModelView):
# validated_by = fields.Many2One('res.user', 'User')
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.Char('Notes')
done_by = fields.Many2One('res.user', 'Done By')
class CrmOpportunityLine(sequence_ordered(), ModelSQL, ModelView):
'CRM Opportunity Line'
__name__ = "crm.opportunity.line"
@ -759,48 +754,47 @@ class CrmOpportunityLine(sequence_ordered(), ModelSQL, ModelView):
}
_depends = ['opportunity_state']
time_ammount = fields.Selection([
('monthly', "Monthly"),
('bimonthly', "Bimonthly"),
('biannual', "Biannual"),
('annual', "Annual")], "Time Ammount", select=True, sort=False,
states={
'readonly': Eval('state').in_(['won', 'lost'])
})
opportunity = fields.Many2One('crm.opportunity', 'Opportunity',
ondelete='CASCADE', select=True, required=True,
states={
'readonly': _states['readonly'] & Bool(Eval('opportunity')),
},
depends=_depends)
ondelete='CASCADE', select=True, required=True,
states={
'readonly': _states['readonly'] & Bool(Eval('opportunity')),
},
depends=_depends)
opportunity_state = fields.Function(
fields.Selection('get_opportunity_states', "Opportunity State"),
'on_change_with_opportunity_state')
product = fields.Many2One('product.product', 'Product', required=True,
domain=[('salable', '=', True)], states=_states, depends=_depends)
domain=[('salable', '=', True)], states=_states, depends=_depends)
quantity = fields.Float('Quantity', required=True,
digits=(16, Eval('unit_digits', 2)),
states=_states, depends=['unit_digits'] + _depends)
digits=(16, Eval('unit_digits', 2)),
states=_states, depends=['unit_digits'] + _depends)
unit = fields.Many2One('product.uom', 'Unit', required=True,
states=_states, depends=_depends)
states=_states, depends=_depends)
unit_digits = fields.Function(fields.Integer('Unit Digits'),
'on_change_with_unit_digits')
tax = fields.Function(fields.Float('Tax Line'),
'get_tax_line')
total_line = fields.Function(fields.Integer('Total Line'),
'get_total_line')
base_tax = fields.Function(fields.Float('Base Tax'),
'get_base_tax')
tax = fields.Function(fields.Float('Tax Line'), 'get_tax_line')
total_line = fields.Function(fields.Integer('Total Line'), 'get_total_line')
base_tax = fields.Function(fields.Float('Base Tax'), 'get_base_tax')
description = fields.Function(fields.Text('Description'),
'on_change_with_description')
'on_change_with_description')
unit_price = fields.Numeric('Unit Price', digits=(16, 2))
total_line_with_tax = fields.Function(fields.Integer('Total Line'),
'get_total_line_with_tax')
'get_total_line_with_tax')
del _states, _depends
@classmethod
def __setup__(cls):
super().__setup__()
cls.__access__.add('opportunity')
# @classmethod
# def __setup__(cls):
# super().__setup__()
# cls.__access__.add('opportunity')
@classmethod
def get_opportunity_states(cls):

View File

@ -253,6 +253,17 @@ this repository contains the full copyright notices and license terms. -->
<field name="name">opportunity_line_tree</field>
</record>
<record model="ir.ui.view" id="crm_opportunity_follow_up_view_form">
<field name="model">crm.opportunity.follow_up</field>
<field name="type">form</field>
<field name="name">opportunity_follow_up_form</field>
</record>
<record model="ir.ui.view" id="crm_opportunity_follow_up_view_tree">
<field name="model">crm.opportunity.follow_up</field>
<field name="type">tree</field>
<field name="name">opportunity_follow_up_tree</field>
</record>
<record model="ir.ui.view" id="crm_validation_template_view_form">
<field name="model">crm.validation_template</field>
<field name="type">form</field>

View File

@ -1,10 +1,11 @@
[tryton]
version=6.0.2
version=6.0.3
depends:
party
sale
sale_contract
company_department
commission
xml:
crm.xml
configuration.xml
@ -18,3 +19,5 @@ xml:
opportunity.xml
message.xml
company.xml
commission.xml
dash.xml

9
view/agent_form.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. -->
<data>
<xpath expr="/form/field[@name='currency']" position="after">
<label name="employee"/>
<field name="employee"/>
</xpath>
</data>

View File

@ -2,16 +2,16 @@
<!-- 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="customer_service_sequence"/>
<field name="customer_service_sequence"/>
<label name="company"/>
<field name="company"/>
<label name="survey_sequence"/>
<field name="survey_sequence"/>
<label name="activity_sequence"/>
<field name="activity_sequence"/>
<label name="customer_service_sequence"/>
<field name="customer_service_sequence"/>
<label name="opportunity_sequence"/>
<field name="opportunity_sequence"/>
<label name="efficay_hour_limit"/>
<field name="efficay_hour_limit"/>
<label name="activity_sequence"/>
<field name="activity_sequence"/>
<label name="survey_sequence"/>
<field name="survey_sequence"/>
<label name="response_time_customer"/>
<field name="response_time_customer"/>
</form>

View File

@ -2,9 +2,9 @@
<!-- 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="customer_service_sequence"/>
<field name="survey_sequence"/>
<field name="activity_sequence"/>
<field name="opportunity_sequence"/>
<field name="company"/>
<field name="company" expand="1"/>
<field name="customer_service_sequence" expand="1"/>
<field name="survey_sequence" expand="1"/>
<field name="activity_sequence" expand="1"/>
<field name="opportunity_sequence" expand="1"/>
</tree>

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="follow_date"/>
<field name="follow_date"/>
<label name="action"/>
<field name="action"/>
<label name="done_by"/>
<field name="done_by"/>
<separator name="notes" colspan="4"/>
<field name="notes" colspan="4"/>
</form>

View File

@ -0,0 +1,8 @@
<?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="follow_date" expand="1"/>
<field name="action" expand="1"/>
<field name="done_by" expand="1"/>
</tree>

View File

@ -8,25 +8,20 @@ this repository contains the full copyright notices and license terms. -->
<field name="contact"/>
<label name="number"/>
<field name="number"/>
<label name="address"/>
<field name="address"/>
<!-- <label name="kind_opportunity"/>
<field name="kind_opportunity"/> -->
<label name="agent"/>
<field name="agent"/>
<label name="description"/>
<field name="description"/>
<label name="type"/>
<field name="type"/>
<!-- <newline/> -->
<label name="source"/>
<field name="source"/>
<label name="reference"/>
<field name="reference"/>
<label name="amount"/>
<field name="amount" symbol="currency"/>
<label name="time_ammount"/>
<field name="time_ammount"/>
<label name="conversion_probability"/>
<group id="conversion_probability">
<field name="conversion_probability" factor="100" xexpand="0"/>
@ -36,22 +31,17 @@ this repository contains the full copyright notices and license terms. -->
<notebook colspan="6">
<page string="Opportunity" id="opportunity">
<label name="payment_term"/>
<field name="payment_term"/>
<label name="company"/>
<field name="company"/>
<newline/>
<label name="employee"/>
<field name="employee"/>
<label name="converted_by"/>
<field name="converted_by"/>
<label name="start_date"/>
<field name="start_date"/>
<label name="end_date"/>
<field name="end_date"/>
<label name="payment_term"/>
<field name="payment_term"/>
<label name="cancelled_reason"/>
<field name="cancelled_reason"/>
<field name="follow_ups" colspan="4"/>
<separator name="comment" colspan="4"/>
<field name="comment" colspan="4"/>
</page>

View File

@ -14,7 +14,8 @@ this repository contains the full copyright notices and license terms. -->
<field name="unit"/>
<label name="unit_price"/>
<field name="unit_price"/>
<newline />
<label name="description"/>
<field name="description" colspan="6"/>
<label name="time_ammount"/>
<field name="time_ammount"/>
<separator string="Description"/>
<field name="description" colspan="4"/>
</form>

View File

@ -6,7 +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="employee" expand="1"/>
<field name="agent" expand="1"/>
<field name="description" expand="1"/>
<field name="party" expand="1"/>
<field name="amount" symbol="currency"/>