[MERGE] forward port of branch 8.0 up to f654a77

This commit is contained in:
Christophe Simonis
2014-07-10 22:50:21 +02:00
83 changed files with 3053 additions and 365 deletions
@@ -98,6 +98,24 @@ class account_invoice_report(osv.osv):
}
_order = 'date desc'
_depends = {
'account.invoice': [
'account_id', 'amount_total', 'commercial_partner_id', 'company_id',
'currency_id', 'date_due', 'date_invoice', 'fiscal_position',
'journal_id', 'partner_bank_id', 'partner_id', 'payment_term',
'period_id', 'residual', 'state', 'type', 'user_id',
],
'account.invoice.line': [
'account_id', 'invoice_id', 'price_subtotal', 'product_id',
'quantity', 'uos_id',
],
'product.product': ['product_tmpl_id'],
'product.template': ['categ_id'],
'product.uom': ['category_id', 'factor', 'name', 'uom_type'],
'res.currency.rate': ['currency_id', 'name'],
'res.partner': ['country_id'],
}
def _select(self):
select_str = """
SELECT sub.id, sub.date, sub.product_id, sub.partner_id, sub.country_id,
@@ -700,7 +700,9 @@ class account_analytic_account(osv.osv):
def _prepare_invoice_lines(self, cr, uid, contract, fiscal_position_id, context=None):
fpos_obj = self.pool.get('account.fiscal.position')
fiscal_position = fpos_obj.browse(cr, uid, fiscal_position_id, context=context)
fiscal_position = None
if fiscal_position_id:
fiscal_position = fpos_obj.browse(cr, uid, fiscal_position_id, context=context)
invoice_lines = []
for line in contract.recurring_invoice_line_ids:
@@ -804,6 +806,12 @@ class account_analytic_account_summary_user(osv.osv):
'user': fields.many2one('res.users', 'User'),
}
_depends = {
'res.users': ['id'],
'account.analytic.line': ['account_id', 'journal_id', 'unit_amount', 'user_id'],
'account.analytic.journal': ['type'],
}
def init(self, cr):
openerp.tools.sql.drop_view_if_exists(cr, 'account_analytic_analysis_summary_user')
cr.execute('''CREATE OR REPLACE VIEW account_analytic_analysis_summary_user AS (
@@ -837,6 +845,11 @@ class account_analytic_account_summary_month(osv.osv):
'month': fields.char('Month', size=32, readonly=True),
}
_depends = {
'account.analytic.line': ['account_id', 'date', 'journal_id', 'unit_amount'],
'account.analytic.journal': ['type'],
}
def init(self, cr):
openerp.tools.sql.drop_view_if_exists(cr, 'account_analytic_analysis_summary_month')
cr.execute('CREATE VIEW account_analytic_analysis_summary_month AS (' \
@@ -42,6 +42,14 @@ class account_followup_stat_by_partner(osv.osv):
'company_id': fields.many2one('res.company', 'Company', readonly=True),
}
_depends = {
'account.move.line': [
'account_id', 'company_id', 'credit', 'date', 'debit',
'followup_date', 'followup_line_id', 'partner_id', 'reconcile_id',
],
'account.account': ['active', 'type'],
}
def init(self, cr):
tools.drop_view_if_exists(cr, 'account_followup_stat_by_partner')
# Here we don't have other choice but to create a virtual ID based on the concatenation
+1
View File
@@ -24,6 +24,7 @@ import crm_segmentation
import crm_lead
import sales_team
import calendar_event
import ir_http
import crm_phonecall
import report
import wizard
+67 -19
View File
@@ -19,13 +19,8 @@
#
##############################################################################
import calendar
from datetime import date, datetime
from dateutil import relativedelta
from openerp import tools
from openerp.osv import fields
from openerp.osv import osv
from openerp.osv import osv, fields
from openerp.http import request
AVAILABLE_PRIORITIES = [
('0', 'Very Low'),
@@ -35,8 +30,10 @@ AVAILABLE_PRIORITIES = [
('4', 'Very High'),
]
class crm_case_channel(osv.osv):
_name = "crm.case.channel"
class crm_tracking_medium(osv.Model):
# OLD crm.case.channel
_name = "crm.tracking.medium"
_description = "Channels"
_order = 'name'
_columns = {
@@ -47,6 +44,67 @@ class crm_case_channel(osv.osv):
'active': lambda *a: 1,
}
class crm_tracking_campaign(osv.Model):
# OLD crm.case.resource.type
_name = "crm.tracking.campaign"
_description = "Campaign"
_rec_name = "name"
_columns = {
'name': fields.char('Campaign Name', required=True, translate=True),
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
}
class crm_tracking_source(osv.Model):
_name = "crm.tracking.source"
_description = "Source"
_rec_name = "name"
_columns = {
'name': fields.char('Source Name', required=True, translate=True),
}
class crm_tracking_mixin(osv.AbstractModel):
"""Mixin class for objects which can be tracked by marketing. """
_name = 'crm.tracking.mixin'
_columns = {
'campaign_id': fields.many2one('crm.tracking.campaign', 'Campaign', # old domain ="['|',('section_id','=',section_id),('section_id','=',False)]"
help="This is a name that helps you keep track of your different campaign efforts Example: Fall_Drive, Christmas_Special"),
'source_id': fields.many2one('crm.tracking.source', 'Source', help="This is the source of the link Example: Search Engine, another domain, or name of email list"),
'medium_id': fields.many2one('crm.tracking.medium', 'Channel', help="This is the method of delivery. EX: Postcard, Email, or Banner Ad"),
}
def tracking_fields(self):
return [('utm_campaign', 'campaign_id'), ('utm_source', 'source_id'), ('utm_medium', 'medium_id')]
def tracking_get_values(self, cr, uid, vals, context=None):
for key, field in self.tracking_fields():
column = self._all_columns[field].column
value = vals.get(field) or (request and request.session.get(key)) # params.get sould be always in session by the dispatch from ir_http
if column._type in ['many2one'] and isinstance(value, basestring): # if we receive a string for a many2one, we search / create the id
if value:
Model = self.pool[column._obj]
rel_id = Model.name_search(cr, uid, value, context=context)
if not rel_id:
rel_id = Model.create(cr, uid, {'name': value}, context=context)
vals[field] = rel_id
# Here the code for other cases that many2one
else:
vals[field] = value
return vals
def _get_default_track(self, cr, uid, field, context=None):
return self.tracking_get_values(cr, uid, {}, context=context).get(field)
_defaults = {
'source_id': lambda self, cr, uid, ctx: self._get_default_track(cr, uid, 'source_id', ctx),
'campaign_id': lambda self, cr, uid, ctx: self._get_default_track(cr, uid, 'campaign_id', ctx),
'medium_id': lambda self, cr, uid, ctx: self._get_default_track(cr, uid, 'medium_id', ctx),
}
class crm_case_stage(osv.osv):
""" Model for case stages. This models the main stages of a document
management flow. Main CRM objects (leads, opportunities, project
@@ -106,16 +164,6 @@ class crm_case_categ(osv.osv):
'object_id' : _find_object_id
}
class crm_case_resource_type(osv.osv):
""" Resource Type of case """
_name = "crm.case.resource.type"
_description = "Campaign"
_rec_name = "name"
_columns = {
'name': fields.char('Campaign Name', required=True, translate=True),
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
}
class crm_payment_mode(osv.osv):
""" Payment Mode for Fund """
_name = "crm.payment.mode"
+21 -4
View File
@@ -13,18 +13,35 @@
<field name="state">open</field>
</record>
<record model="crm.case.channel" id="crm_case_channel_website">
<!-- Crm Source -->
<record model="crm.tracking.source" id="crm_source_search_engine">
<field name="name">Search engine</field>
</record>
<record model="crm.tracking.source" id="crm_source_mailing">
<field name="name">Mailing Partner</field>
</record>
<record model="crm.tracking.source" id="crm_source_newsletter">
<field name="name">Newsletter</field>
</record>
<!-- Crm Medium -->
<record model="crm.tracking.medium" id="crm_medium_website">
<field name="name">Website</field>
</record>
<record model="crm.case.channel" id="crm_case_channel_phone">
<record model="crm.tracking.medium" id="crm_medium_phone">
<field name="name">Phone</field>
</record>
<record model="crm.case.channel" id="crm_case_channel_direct">
<record model="crm.tracking.medium" id="crm_medium_direct">
<field name="name">Direct</field>
</record>
<record model="crm.case.channel" id="crm_case_channel_email">
<record model="crm.tracking.medium" id="crm_medium_email">
<field name="name">Email</field>
</record>
<record model="crm.tracking.medium" id="crm_medium_banner">
<field name="name">Banner Ad</field>
</record>
<record model="crm.case.section" id="sales_team.section_sales_department">
<field name="use_leads">True</field>
+4 -6
View File
@@ -32,13 +32,14 @@ from openerp.tools.translate import _
CRM_LEAD_FIELDS_TO_MERGE = ['name',
'partner_id',
'channel_id',
'campaign_id',
'company_id',
'country_id',
'section_id',
'state_id',
'stage_id',
'type_id',
'medium_id',
'source_id',
'user_id',
'title',
'city',
@@ -67,7 +68,7 @@ class crm_lead(format_address, osv.osv):
_name = "crm.lead"
_description = "Lead/Opportunity"
_order = "priority,date_action,id desc"
_inherit = ['mail.thread', 'ir.needaction_mixin']
_inherit = ['mail.thread', 'ir.needaction_mixin', 'crm.tracking.mixin']
_track = {
'stage_id': {
@@ -214,9 +215,6 @@ class crm_lead(format_address, osv.osv):
'write_date': fields.datetime('Update Date', readonly=True),
'categ_ids': fields.many2many('crm.case.categ', 'crm_lead_category_rel', 'lead_id', 'category_id', 'Tags', \
domain="['|', ('section_id', '=', section_id), ('section_id', '=', False), ('object_id.model', '=', 'crm.lead')]", help="Classify and analyze your lead/opportunity categories like: Training, Service"),
'type_id': fields.many2one('crm.case.resource.type', 'Campaign', \
domain="['|',('section_id','=',section_id),('section_id','=',False)]", help="From which campaign (seminar, marketing campaign, mass mailing, ...) did this contact come from?"),
'channel_id': fields.many2one('crm.case.channel', 'Channel', help="Communication channel (mail, direct, phone, ...)"),
'contact_name': fields.char('Contact Name', size=64),
'partner_name': fields.char("Customer Name", size=64,help='The name of the future partner company that will be created while converting the lead into opportunity', select=1),
'opt_out': fields.boolean('Opt-Out', oldname='optout',
-33
View File
@@ -68,39 +68,6 @@
(4, ref('stage_lead7'))]"/>
</record>
<!-- Crm campain -->
<record model="crm.case.resource.type" id="type_lead1">
<field name="name">Telesales</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
</record>
<record model="crm.case.resource.type" id="type_lead2">
<field name="name">Email Campaign - Services</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
</record>
<record model="crm.case.resource.type" id="type_lead3">
<field name="name">Email Campaign - Products</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
</record>
<record model="crm.case.resource.type" id="type_lead4">
<field name="name">Twitter Ads</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
</record>
<record model="crm.case.resource.type" id="type_lead5">
<field name="name">Google Adwords</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
</record>
<record model="crm.case.resource.type" id="type_lead6">
<field name="name">Banner Ads</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
</record>
<record model="crm.case.resource.type" id="type_lead7">
<field name="name">Television</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
</record>
<record model="crm.case.resource.type" id="type_lead8">
<field name="name">Newsletter</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
</record>
<!-- crm categories -->
<record model="crm.case.categ" id="categ_oppor1">
-46
View File
@@ -16,9 +16,7 @@
<field name="city">Paris</field>
<field name="zip">93190</field>
<field name="phone">+33 1 25 54 45 69</field>
<field name="type_id" ref="type_lead2"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor6])]"/>
<field name="channel_id" ref="crm_case_channel_email"/>
<field name="priority">1</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
<field name="user_id" ref="base.user_root"/>
@@ -51,9 +49,7 @@ Could you please send me the details ?</field>
<field name="function">Purchase Manager</field>
<field name="country_id" ref="base.fr"/>
<field name="city">Bordeaux</field>
<field name="type_id" ref="type_lead7"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor2])]"/>
<field name="channel_id" ref="crm_case_channel_website"/>
<field name="priority">1</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
<field name="user_id" ref="base.user_root"/>
@@ -80,9 +76,7 @@ Could you please send me the details ?</field>
<field name="partner_id" ref=""/>
<field name="country_id" ref="base.us"/>
<field name="city">New-York</field>
<field name="type_id" ref="type_lead5"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor4])]"/>
<field name="channel_id" ref=""/>
<field name="priority">2</field>
<field name="section_id" ref="sales_team.crm_case_section_1"/>
<field name="user_id" ref="base.user_demo"/>
@@ -101,9 +95,7 @@ Could you please send me the details ?</field>
<field name="partner_id" ref=""/>
<field name="country_id" ref="base.uk"/>
<field name="city">Drury</field>
<field name="type_id" ref="type_lead8"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor5])]"/>
<field name="channel_id" ref=""/>
<field name="priority">2</field>
<field name="section_id" ref="sales_team.crm_case_section_2"/>
<field name="user_id" ref="base.user_demo"/>
@@ -126,9 +118,7 @@ Could you please send me the details ?</field>
<field name="city">Franklinville</field>
<field name="zip">NJ 08322</field>
<field name="phone">+1 813 494 5005</field>
<field name="type_id" ref="type_lead3"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor1])]"/>
<field name="channel_id" ref="crm_case_channel_website"/>
<field name="priority">2</field>
<field name="section_id" ref="sales_team.crm_case_section_1"/>
<field name="user_id" ref=""/>
@@ -153,9 +143,7 @@ Contact: +1 813 494 5005</field>
<field name="function">Consultant</field>
<field name="country_id" ref="base.it"/>
<field name="city">Roma</field>
<field name="type_id" ref="type_lead3"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor3,categ_oppor4])]"/>
<field name="channel_id" ref=""/>
<field name="priority">2</field>
<field name="section_id" ref="sales_team.crm_case_section_2"/>
<field name="user_id" ref=""/>
@@ -171,9 +159,7 @@ Contact: +1 813 494 5005</field>
<field name="function">Journalist</field>
<field name="country_id" ref="base.ua"/>
<field name="city">Kiev</field>
<field name="type_id" ref="type_lead8"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor4])]"/>
<field name="channel_id" ref=""/>
<field name="priority">0</field>
<field name="section_id" ref="sales_team.crm_case_section_2"/>
<field name="user_id" ref="base.user_root"/>
@@ -190,9 +176,7 @@ Contact: +1 813 494 5005</field>
<field name="function">Sales</field>
<field name="country_id" ref="base.uk"/>
<field name="city">Cambridge</field>
<field name="type_id" ref="type_lead5"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor6,categ_oppor8])]"/>
<field name="channel_id" ref=""/>
<field name="priority">1</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
<field name="user_id" ref="base.user_root"/>
@@ -209,9 +193,7 @@ Contact: +1 813 494 5005</field>
<field name="function">Sales</field>
<field name="country_id" ref="base.uk"/>
<field name="city">Oxford</field>
<field name="type_id" ref="type_lead3"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor7])]"/>
<field name="channel_id" ref="crm_case_channel_phone"/>
<field name="priority">2</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
<field name="user_id" ref="base.user_demo"/>
@@ -227,9 +209,7 @@ Contact: +1 813 494 5005</field>
<field name="function">Medical illustrator</field>
<field name="country_id" ref="base.es"/>
<field name="city">Sevilla</field>
<field name="type_id" ref="type_lead8"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor1])]"/>
<field name="channel_id" ref="crm_case_channel_email"/>
<field name="priority">2</field>
<field name="section_id" ref="sales_team.crm_case_section_2"/>
<field name="user_id" ref="base.user_demo"/>
@@ -250,9 +230,7 @@ Andrew</field>
<field name="partner_id" ref="base.res_partner_1"/>
<field name="function">Functional Consultant</field>
<field name="country_id" ref=""/>
<field name="type_id" ref="type_lead3"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor7])]"/>
<field name="channel_id" ref="crm_case_channel_direct"/>
<field name="priority">2</field>
<field name="section_id" ref="sales_team.crm_case_section_1"/>
<field name="user_id" ref=""/>
@@ -268,9 +246,7 @@ Andrew</field>
<field name="partner_id" ref="base.res_partner_1"/>
<field name="country_id" ref="base.cn"/>
<field name="city">Shenzhen</field>
<field name="type_id" ref="type_lead3"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor1])]"/>
<field name="channel_id" ref="crm_case_channel_website"/>
<field name="priority">2</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
<field name="user_id" ref=""/>
@@ -303,9 +279,7 @@ Andrew</field>
<field name="street">1 rue Rockfeller</field>
<field name="country_id" ref="base.at"/>
<field name="city">Melbourne</field>
<field name="type_id" ref="type_lead3"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor1])]"/>
<field name="channel_id" ref="crm_case_channel_email"/>
<field name="priority">1</field>
<field eval="time.strftime('%Y-%m-25')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-12')" name="date_action"/>
@@ -328,9 +302,7 @@ Andrew</field>
<field name="country_id" ref="base.be"/>
<field name="city">Wavre</field>
<field name="zip">1300</field>
<field name="type_id" ref="type_lead3"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor2])]"/>
<field name="channel_id" ref="crm_case_channel_website"/>
<field name="priority">2</field>
<field eval="time.strftime('%Y-%m-23')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-10')" name="date_action"/>
@@ -350,7 +322,6 @@ Andrew</field>
<field name="city">Wavre</field>
<field name="email_from">virginie@agrolait.com</field>
<field name="partner_id" ref="base.res_partner_2"/>
<field name="type_id" ref="type_lead8"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor1])]"/>
<field name="priority">1</field>
<field eval="time.strftime('%Y-%m-12')" name="date_deadline"/>
@@ -377,7 +348,6 @@ Andrew</field>
<field name="country_id" ref="base.uk"/>
<field name="city">Liverpool</field>
<field name="zip">L25 4RL</field>
<field name="type_id" ref="type_lead5"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor5])]"/>
<field name="priority">2</field>
<field eval="time.strftime('%Y-%m-28')" name="date_deadline"/>
@@ -401,9 +371,7 @@ Andrew</field>
<field name="street">Rue des Palais 51, bte 33</field>
<field name="country_id" ref="base.be"/>
<field name="city">Brussels</field>
<field name="type_id" ref="type_lead3"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor3,categ_oppor4])]"/>
<field name="channel_id" ref="crm_case_channel_website"/>
<field name="priority">1</field>
<field eval="time.strftime('%Y-%m-8')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-3')" name="date_action"/>
@@ -429,7 +397,6 @@ Andrew</field>
<field name="street">3661 Station Street</field>
<field name="country_id" ref="base.uk"/>
<field name="partner_id" ref="base.res_partner_4"/>
<field name="type_id" ref="type_lead8"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor4,categ_oppor6])]"/>
<field name="priority">1</field>
<field eval="time.strftime('%Y-%m-13')" name="date_deadline"/>
@@ -456,7 +423,6 @@ Andrew</field>
<field name="country_id" ref="base.uk"/>
<field name="city">Liverpool</field>
<field name="zip">L25 4RL</field>
<field name="type_id" ref="type_lead3"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor1])]"/>
<field name="priority">1</field>
<field eval="time.strftime('%Y-%m-10')" name="date_deadline"/>
@@ -476,7 +442,6 @@ Andrew</field>
<field name="partner_name">Epic Technologies</field>
<field name="email_from">john.b@tech.info</field>
<field name="partner_id" ref="base.res_partner_5"/>
<field name="type_id" ref="type_lead3"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor4,categ_oppor8])]"/>
<field name="priority">2</field>
<field name="section_id" ref="sales_team.crm_case_section_1"/>
@@ -489,9 +454,7 @@ Andrew</field>
<field name="name">“Resource Planning” project develpment</field>
<field eval="350" name="planned_revenue"/>
<field name="partner_id" ref="base.res_partner_7"/>
<field name="type_id" ref="type_lead2"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor7])]"/>
<field name="channel_id" ref="crm_case_channel_phone"/>
<field name="priority">2</field>
<field name="section_id" ref="sales_team.crm_case_section_2"/>
<field name="user_id" ref="base.user_root"/>
@@ -507,9 +470,7 @@ Andrew</field>
<field name="contact_name">Benjamin Flores</field>
<field name="partner_name">Nebula Business</field>
<field name="partner_id" ref="base.res_partner_17"/>
<field name="type_id" ref="type_lead7"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor3])]"/>
<field name="channel_id" ref="crm_case_channel_email"/>
<field name="priority">1</field>
<field name="section_id" ref="sales_team.crm_case_section_2"/>
<field name="user_id" ref="base.user_root"/>
@@ -522,9 +483,7 @@ Andrew</field>
<field eval="2000" name="planned_revenue"/>
<field eval="80.0" name="probability"/>
<field name="partner_id" ref="base.res_partner_18"/>
<field name="type_id" ref="type_lead5"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor3])]"/>
<field name="channel_id" ref="crm_case_channel_direct"/>
<field name="priority">0</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
<field name="user_id" ref="base.user_demo"/>
@@ -540,9 +499,7 @@ Andrew</field>
<field name="email_from">info@mycompany.net</field>
<field name="country_id" ref="base.pe"/>
<field name="city">Lima</field>
<field name="type_id" ref="type_lead8"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor7])]"/>
<field name="channel_id" ref="crm_case_channel_website"/>
<field name="priority">0</field>
<field eval="time.strftime('%Y-%m-6')" name="date_deadline"/>
<field name="section_id" ref="sales_team.section_sales_department"/>
@@ -564,7 +521,6 @@ Andrew</field>
<field name="country_id" ref="base.ar"/>
<field name="city">Buenos Aires</field>
<field name="zip">B7313</field>
<field name="type_id" ref="type_lead4"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor4])]"/>
<field name="priority">2</field>
<field name="title_action">Conf call with technical service</field>
@@ -585,9 +541,7 @@ Andrew</field>
<field name="country_id" ref="base.be"/>
<field name="city">Wavre</field>
<field name="zip">1300</field>
<field name="type_id" ref="type_lead3"/>
<field name="categ_ids" eval="[(6, 0, [categ_oppor2])]"/>
<field name="channel_id" ref="crm_case_channel_website"/>
<field name="priority">2</field>
<field eval="time.strftime('%Y-%m-23')" name="date_deadline"/>
<field eval="time.strftime('%Y-%m-10')" name="date_action"/>
+5 -4
View File
@@ -230,9 +230,9 @@
<field name="partner_id" invisible="1"/>
<field name="section_id" groups="base.group_multi_salesteams"/>
<field name="probability" invisible="1"/>
<field name="type_id" invisible="1"/>
<field name="campaign_id" invisible="1"/>
<field name="referred" invisible="1"/>
<field name="channel_id" invisible="1"/>
<field name="medium_id" invisible="1"/>
<field name="message_unread" invisible="1"/>
</tree>
</field>
@@ -513,8 +513,9 @@
<field name="country_id"/>
<field name="date_action"/>
<field name="title_action"/>
<field name="channel_id" invisible="1"/>
<field name="type_id" invisible="1"/>
<field name="medium_id" invisible="1"/>
<field name="campaign_id" invisible="1"/>
<field name="source_id" invisible="1"/>
<field name="stage_id"/>
<field name="planned_revenue" sum="Expected Revenues"/>
<field name="probability" avg="Avg. of Probability"/>
+63 -23
View File
@@ -26,10 +26,10 @@
<menuitem id="base.next_id_64" name="Sales"
parent="base.menu_reporting" sequence="1"/>
<!-- crm.case.channel -->
<record id="crm_case_channel_view_tree" model="ir.ui.view">
<field name="name">crm.case.channel.tree</field>
<field name="model">crm.case.channel</field>
<!-- crm.tracking.medium -->
<record id="crm_tracking_medium_view_tree" model="ir.ui.view">
<field name="name">crm.tracking.medium.tree</field>
<field name="model">crm.tracking.medium</field>
<field name="arch" type="xml">
<tree string="Channels">
<field name="name"/>
@@ -37,9 +37,9 @@
</tree>
</field>
</record>
<record id="crm_case_channel_view_form" model="ir.ui.view">
<field name="name">crm.case.channel.form</field>
<field name="model">crm.case.channel</field>
<record id="crm_tracking_medium_view_form" model="ir.ui.view">
<field name="name">crm.tracking.medium.form</field>
<field name="model">crm.tracking.medium</field>
<field name="arch" type="xml">
<form string="Channel">
<group>
@@ -49,26 +49,66 @@
</form>
</field>
</record>
<record id="crm_case_channel_action" model="ir.actions.act_window">
<record id="crm_tracking_medium_action" model="ir.actions.act_window">
<field name="name">Channels</field>
<field name="res_model">crm.case.channel</field>
<field name="res_model">crm.tracking.medium</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to define a new channel.
</p><p>
Use channels to track the soure of your leads and opportunities. Channels
Use channels to track the type of source of your leads and opportunities. Channels
are mostly used in reporting to analyse sales performance
related to marketing efforts.
</p><p>
Some examples of channels: company website, phone call
campaign, reseller, etc.
campaign, reseller, banner, etc.
</p>
</field>
</record>
<menuitem action="crm_case_channel_action" id="menu_crm_case_channel" parent="base.menu_crm_config_lead" sequence="4" groups="base.group_no_one"/>
<!-- crm.tracking.source -->
<record id="crm_tracking_source_view_tree" model="ir.ui.view">
<field name="name">crm.tracking.source.tree</field>
<field name="model">crm.tracking.source</field>
<field name="arch" type="xml">
<tree string="Channels">
<field name="name"/>
</tree>
</field>
</record>
<record id="crm_tracking_source_view_form" model="ir.ui.view">
<field name="name">crm.tracking.source.form</field>
<field name="model">crm.tracking.source</field>
<field name="arch" type="xml">
<form string="Channel">
<group>
<field name="name"/>
</group>
</form>
</field>
</record>
<record id="crm_tracking_source_action" model="ir.actions.act_window">
<field name="name">Source</field>
<field name="res_model">crm.tracking.source</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to define a new source.
</p><p>
Use channels to track the source of your leads and opportunities. Channels
are mostly used in reporting to analyse sales performance
related to marketing efforts.
</p><p>
Some examples of channels: partner's website, google.com,
email list name, etc.
</p>
</field>
</record>
<menuitem action="crm_tracking_source_action" id="menu_crm_tracking_source" parent="base.menu_crm_config_lead" sequence="4" groups="base.group_no_one"/>
<!-- CRM Stage Tree View -->
@@ -155,9 +195,9 @@
<!-- Resource Type of case Tree View -->
<record model="ir.ui.view" id="crm_case_resource_type_tree">
<field name="name">crm.case.resource.type.tree</field>
<field name="model">crm.case.resource.type</field>
<record model="ir.ui.view" id="crm_tracking_campaign_tree">
<field name="name">crm.tracking.campaign.tree</field>
<field name="model">crm.tracking.campaign</field>
<field name="arch" type="xml">
<tree string="Campaign">
<field name="name"/>
@@ -168,9 +208,9 @@
<!-- Resource Type of case Form View -->
<record model="ir.ui.view" id="crm_case_resource_type_form">
<field name="name">crm.case.resource.type.form</field>
<field name="model">crm.case.resource.type</field>
<record model="ir.ui.view" id="crm_tracking_campaign_form">
<field name="name">crm.tracking.campaign.form</field>
<field name="model">crm.tracking.campaign</field>
<field name="arch" type="xml">
<form string="Campaign">
<group>
@@ -183,15 +223,15 @@
<!-- Resource Type of case Action -->
<record id="crm_case_resource_type_act" model="ir.actions.act_window">
<record id="crm_tracking_campaign_act" model="ir.actions.act_window">
<field name="name">Campaigns</field>
<field name="res_model">crm.case.resource.type</field>
<field name="res_model">crm.tracking.campaign</field>
<field name="view_type">form</field>
<field name="view_id" ref="crm_case_resource_type_tree"/>
<field name="view_id" ref="crm_tracking_campaign_tree"/>
</record>
<menuitem action="crm_case_resource_type_act"
id="menu_crm_case_resource_type_act" sequence="4"
<menuitem action="crm_tracking_campaign_act"
id="menu_crm_tracking_campaign_act" sequence="4"
groups="base.group_no_one"
parent="base.menu_crm_config_lead"/>
+13
View File
@@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
from openerp.http import request
from openerp.osv import orm
class ir_http(orm.AbstractModel):
_inherit = 'ir.http'
def _dispatch(self):
for var, dummy in self.pool['crm.tracking.mixin'].tracking_fields():
if var in request.params and (var not in request.session or request.session[var] != request.params[var]):
request.session[var] = request.params[var]
return super(ir_http, self)._dispatch()
+5 -5
View File
@@ -44,6 +44,7 @@ class crm_lead_report(osv.osv):
_auto = False
_description = "CRM Lead Analysis"
_rec_name = 'date_deadline'
_inherit = ["crm.tracking.mixin"]
_columns = {
'date_deadline': fields.date('Exp. Closing', readonly=True, help="Expected Closing"),
@@ -58,10 +59,8 @@ class crm_lead_report(osv.osv):
'delay_expected': fields.float('Overpassed Deadline',digits=(16,2),readonly=True, group_operator="avg"),
'user_id':fields.many2one('res.users', 'User', readonly=True),
'section_id':fields.many2one('crm.case.section', 'Sales Team', readonly=True),
'country_id':fields.many2one('res.country', 'Country', readonly=True),
'section_id':fields.many2one('crm.case.section', 'Sales Team', readonly=True),
'channel_id':fields.many2one('crm.case.channel', 'Channel', readonly=True),
'type_id':fields.many2one('crm.case.resource.type', 'Campaign', readonly=True),
'company_id': fields.many2one('res.company', 'Company', readonly=True),
'probability': fields.float('Probability',digits=(16,2),readonly=True, group_operator="avg"),
'planned_revenue': fields.float('Planned Revenue',digits=(16,2),readonly=True),
@@ -101,8 +100,9 @@ class crm_lead_report(osv.osv):
c.company_id,
c.priority,
c.section_id,
c.channel_id,
c.type_id,
c.campaign_id,
c.source_id,
c.medium_id,
c.partner_id,
c.country_id,
c.planned_revenue,
+6 -4
View File
@@ -74,13 +74,15 @@
<group expand="0" string="Extended Filters">
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="stage_id" domain="[('section_ids', '=', 'section_id')]" />
<field name="type_id"/>
<field name="channel_id"/>
<field name="campaign_id"/>
<field name="medium_id"/>
<field name="source_id"/>
<field name="company_id" groups="base.group_multi_company"/>
<separator orientation="vertical"/>
<field name="stage_id" widget="selection" domain="[('section_ids', '=', 'section_id')]" />
<field name="type_id" widget="selection"/>
<field name="channel_id" widget="selection"/>
<field name="campaign_id" widget="selection"/>
<field name="medium_id" widget="selection"/>
<field name="source_id" widget="selection"/>
<separator orientation="vertical"/>
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
<newline/>
+7 -5
View File
@@ -3,8 +3,10 @@ access_crm_segmentation_user,crm.segmentation user,model_crm_segmentation,base.g
access_crm_segmentation_line_user,crm.segmentation.line user,model_crm_segmentation_line,base.group_sale_salesman,1,0,0,0
access_crm_segmentation,crm.segmentation,model_crm_segmentation,base.group_sale_manager,1,1,1,1
access_crm_segmentation_line,crm.segmentation.line,model_crm_segmentation_line,base.group_sale_manager,1,1,1,1
access_crm_case_channel_user,crm.case.channel user,model_crm_case_channel,base.group_sale_salesman,1,0,0,0
access_crm_case_channel_manager,crm.case.channel manager,model_crm_case_channel,base.group_sale_manager,1,1,1,1
access_crm_tracking_medium_user,crm.tracking.medium user,model_crm_tracking_medium,base.group_sale_salesman,1,0,0,0
access_crm_tracking_medium_manager,crm.tracking.medium manager,model_crm_tracking_medium,base.group_sale_manager,1,1,1,1
access_crm_tracking_source_user,crm.tracking.source user,model_crm_tracking_source,base.group_sale_salesman,1,0,0,0
access_crm_tracking_source_manager,crm.tracking.source manager,model_crm_tracking_source,base.group_sale_manager,1,1,1,1
access_crm_case_categ,crm.case.categ,model_crm_case_categ,base.group_sale_salesman,1,1,1,0
access_crm_lead_manager,crm.lead.manager,model_crm_lead,base.group_sale_manager,1,1,1,1
access_crm_phonecall_manager,crm.phonecall.manager,model_crm_phonecall,base.group_sale_manager,1,1,1,1
@@ -13,8 +15,8 @@ access_crm_lead,crm.lead,model_crm_lead,base.group_sale_salesman,1,1,1,0
access_crm_phonecall,crm.phonecall,model_crm_phonecall,base.group_sale_salesman,1,1,1,0
access_crm_case_stage,crm.case.stage,model_crm_case_stage,,1,0,0,0
access_crm_case_stage_manager,crm.case.stage,model_crm_case_stage,base.group_sale_manager,1,1,1,1
access_crm_case_resource_type_user,crm_case_resource_type user,model_crm_case_resource_type,base.group_sale_salesman,1,1,1,0
access_crm_case_resource_type_manager,crm_case_resource_type manager,model_crm_case_resource_type,base.group_sale_manager,1,1,1,1
access_crm_tracking_campaign_user,crm_tracking_campaign user,model_crm_tracking_campaign,base.group_sale_salesman,1,1,1,0
access_crm_tracking_campaign_manager,crm_tracking_campaign manager,model_crm_tracking_campaign,base.group_sale_manager,1,1,1,1
access_crm_phonecall_report_user,crm.phonecall.report.user,model_crm_phonecall_report,base.group_sale_salesman,1,0,0,0
access_crm_phonecall_report_manager,crm.phonecall.report,model_crm_phonecall_report,base.group_sale_manager,1,1,1,1
access_res_partner_manager,res.partner.crm.manager,base.model_res_partner,base.group_sale_manager,1,0,0,0
@@ -29,4 +31,4 @@ access_res_partner_bank_type_crm_user,res.partner.bank.type.crm.user,base.model_
access_crm_lead_partner_manager,crm.lead.partner.manager,model_crm_lead,base.group_partner_manager,1,0,0,0
access_crm_phonecall_partner_manager,crm.phonecall.partner.manager,model_crm_phonecall,base.group_partner_manager,1,1,1,1
access_crm_payment_mode_user,crm.payment.mode,model_crm_payment_mode,base.group_sale_salesman,1,0,0,0
access_crm_payment_mode,crm.payment.mode,model_crm_payment_mode,base.group_sale_manager,1,1,1,1
access_crm_payment_mode,crm.payment.mode,model_crm_payment_mode,base.group_sale_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
3 access_crm_segmentation_line_user crm.segmentation.line user model_crm_segmentation_line base.group_sale_salesman 1 0 0 0
4 access_crm_segmentation crm.segmentation model_crm_segmentation base.group_sale_manager 1 1 1 1
5 access_crm_segmentation_line crm.segmentation.line model_crm_segmentation_line base.group_sale_manager 1 1 1 1
6 access_crm_case_channel_user access_crm_tracking_medium_user crm.case.channel user crm.tracking.medium user model_crm_case_channel model_crm_tracking_medium base.group_sale_salesman 1 0 0 0
7 access_crm_case_channel_manager access_crm_tracking_medium_manager crm.case.channel manager crm.tracking.medium manager model_crm_case_channel model_crm_tracking_medium base.group_sale_manager 1 1 1 1
8 access_crm_tracking_source_user crm.tracking.source user model_crm_tracking_source base.group_sale_salesman 1 0 0 0
9 access_crm_tracking_source_manager crm.tracking.source manager model_crm_tracking_source base.group_sale_manager 1 1 1 1
10 access_crm_case_categ crm.case.categ model_crm_case_categ base.group_sale_salesman 1 1 1 0
11 access_crm_lead_manager crm.lead.manager model_crm_lead base.group_sale_manager 1 1 1 1
12 access_crm_phonecall_manager crm.phonecall.manager model_crm_phonecall base.group_sale_manager 1 1 1 1
15 access_crm_phonecall crm.phonecall model_crm_phonecall base.group_sale_salesman 1 1 1 0
16 access_crm_case_stage crm.case.stage model_crm_case_stage 1 0 0 0
17 access_crm_case_stage_manager crm.case.stage model_crm_case_stage base.group_sale_manager 1 1 1 1
18 access_crm_case_resource_type_user access_crm_tracking_campaign_user crm_case_resource_type user crm_tracking_campaign user model_crm_case_resource_type model_crm_tracking_campaign base.group_sale_salesman 1 1 1 0
19 access_crm_case_resource_type_manager access_crm_tracking_campaign_manager crm_case_resource_type manager crm_tracking_campaign manager model_crm_case_resource_type model_crm_tracking_campaign base.group_sale_manager 1 1 1 1
20 access_crm_phonecall_report_user crm.phonecall.report.user model_crm_phonecall_report base.group_sale_salesman 1 0 0 0
21 access_crm_phonecall_report_manager crm.phonecall.report model_crm_phonecall_report base.group_sale_manager 1 1 1 1
22 access_res_partner_manager res.partner.crm.manager base.model_res_partner base.group_sale_manager 1 0 0 0
31 access_crm_lead_partner_manager crm.lead.partner.manager model_crm_lead base.group_partner_manager 1 0 0 0
32 access_crm_phonecall_partner_manager crm.phonecall.partner.manager model_crm_phonecall base.group_partner_manager 1 1 1 1
33 access_crm_payment_mode_user crm.payment.mode model_crm_payment_mode base.group_sale_salesman 1 0 0 0
34 access_crm_payment_mode crm.payment.mode model_crm_payment_mode base.group_sale_manager 1 1 1 1
Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

+2 -2
View File
@@ -28,12 +28,12 @@
Case Category2
-->
<record model="crm.case.resource.type" id="type_claim1">
<record model="crm.tracking.campaign" id="claim_source1">
<field name="name">Corrective</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
</record>
<record model="crm.case.resource.type" id="type_claim2">
<record model="crm.tracking.campaign" id="claim_source2">
<field name="name">Preventive</field>
<field name="section_id" ref="sales_team.section_sales_department"/>
</record>
+1 -1
View File
@@ -56,7 +56,7 @@ class crm_helpdesk(osv.osv):
'date': fields.datetime('Date'),
'ref': fields.reference('Reference', selection=openerp.addons.base.res.res_request.referencable_models),
'ref2': fields.reference('Reference 2', selection=openerp.addons.base.res.res_request.referencable_models),
'channel_id': fields.many2one('crm.case.channel', 'Channel', help="Communication channel."),
'channel_id': fields.many2one('crm.tracking.medium', 'Channel', help="Communication channel."),
'planned_revenue': fields.float('Planned Revenue'),
'planned_cost': fields.float('Planned Costs'),
'priority': fields.selection([('0','Low'), ('1','Normal'), ('2','High')], 'Priority'),
@@ -56,7 +56,7 @@ class crm_helpdesk_report(osv.osv):
'date_deadline': fields.date('Deadline', select=True),
'priority': fields.selection([('5', 'Lowest'), ('4', 'Low'), \
('3', 'Normal'), ('2', 'High'), ('1', 'Highest')], 'Priority'),
'channel_id': fields.many2one('crm.case.channel', 'Channel'),
'channel_id': fields.many2one('crm.tracking.medium', 'Channel'),
'categ_id': fields.many2one('crm.case.categ', 'Category', \
domain="[('section_id','=',section_id),\
('object_id.model', '=', 'crm.helpdesk')]"),
+22
View File
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2014-Today OpenERP SA (<http://www.openerp.com>).
#
# 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 mass_mailing
+18
View File
@@ -0,0 +1,18 @@
{
'name': 'Campaign in Mass Mailing',
'version': '1.0',
'summary': 'This module allow to specify a campaign, a source and a channel for a mass mailing campaign.',
'author': 'OpenERP SA',
'description': """
Mass Mailing with Crm Marketing
================================
Link module mass mailing with the marketing mixin from crm.
""",
'depends': ['crm', 'mass_mailing'],
'data': [
'mass_mailing.xml',
],
'installable': True,
'auto_install': True,
}
+6
View File
@@ -0,0 +1,6 @@
from openerp.osv import osv
class MassMailing(osv.Model):
_name = 'mail.mass_mailing'
_inherit = ['mail.mass_mailing', 'crm.tracking.mixin']
+23
View File
@@ -0,0 +1,23 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_tracking_mass_mailing_form">
<field name="name">mail.mass_mailing.inherit.form</field>
<field name="model">mail.mass_mailing</field>
<field name="inherit_id" ref="mass_mailing.view_mail_mass_mailing_form"/>
<field name="arch" type="xml">
<xpath expr="//notebook/page[@string='Options']" position="after">
<page string="Tracking">
<group>
<field name="campaign_id" />
<field name="medium_id" />
<field name="source_id" />
</group>
</page>
</xpath>
</field>
</record>
</data>
</openerp>
@@ -12,9 +12,7 @@
<field name="function">Reseller</field>
<field name="country_id" ref="base.uk"/>
<field name="city">Edinburgh</field>
<field name="type_id" ref="crm.type_lead8"/>
<field name="categ_ids" eval="[(6, 0, [ref('crm.categ_oppor1')])]"/>
<field name="channel_id" ref="crm.crm_case_channel_email"/>
<field name="priority">2</field>
<field name="section_id" ref="sales_team.crm_case_section_2"/>
<field name="user_id" ref=""/>
@@ -15,9 +15,9 @@
<field name="email_from"/>
<field name="phone"/>
<field name="stage_id" invisible="1"/>
<field name="type_id" invisible="1"/>
<field name="campaign_id" invisible="1"/>
<field name="referred" invisible="1"/>
<field name="channel_id" invisible="1"/>
<field name="medium_id" invisible="1"/>
<field name="section_id" invisible="context.get('invisible_section', True)" groups="base.group_multi_salesteams"/>
<button string="I'm interested" name="case_interested" icon="gtk-index" type="object"/>
@@ -80,8 +80,8 @@
<field name="country_id" invisible="context.get('invisible_country', True)" />
<field name="date_action"/>
<field name="title_action" />
<field name="channel_id" invisible="1"/>
<field name="type_id" invisible="1"/>
<field name="medium_id" invisible="1"/>
<field name="campaign_id" invisible="1"/>
<field name="planned_revenue" sum="Expected Revenues"/>
<field name="probability" widget="progressbar" avg="Avg. of Probability"/>
<field name="section_id" groups="base.group_multi_salesteams" invisible="context.get('invisible_section', True)" />
@@ -140,8 +140,8 @@
</group>
<group col="2">
<separator string="Categorization" colspan="2"/>
<field name="type_id" readonly="1"/>
<field name="channel_id" readonly="1"/>
<field name="campaign_id" readonly="1"/>
<field name="medium_id" readonly="1"/>
</group>
</group>
<separator string="Details" />
+3 -3
View File
@@ -222,9 +222,9 @@ class email_template(osv.osv):
help="Optional translation language (ISO code) to select when sending out an email. "
"If not set, the english version will be used. "
"This should usually be a placeholder expression "
"that provides the appropriate language code, e.g. "
"${object.partner_id.lang.code}.",
placeholder="${object.partner_id.lang.code}"),
"that provides the appropriate language, e.g. "
"${object.partner_id.lang}.",
placeholder="${object.partner_id.lang}"),
'user_signature': fields.boolean('Add Signature',
help="If checked, the user's signature will be appended to the text version "
"of the message"),
+1 -1
View File
@@ -55,7 +55,7 @@ class event_event(models.Model):
readonly=False, states={'done': [('readonly', True)]})
type = fields.Many2one('event.type', string='Type of Event',
readonly=False, states={'done': [('readonly', True)]})
seats_max = fields.Integer(string='Maximum Avalaible Seats', oldname='register_max',
seats_max = fields.Integer(string='Maximum Available Seats', oldname='register_max',
readonly=True, states={'draft': [('readonly', False)]},
help="You can for each event define a maximum registration level. If you have too much registrations you are not able to confirm your event. (put 0 to ignore this rule )")
seats_min = fields.Integer(string='Minimum Reserved Seats', oldname='register_min',
+1 -1
View File
@@ -186,7 +186,7 @@ class event_ticket(osv.osv):
'deadline': fields.date("Sales End"),
'is_expired': fields.function(_is_expired, type='boolean', string='Is Expired'),
'price': fields.float('Price'),
'seats_max': fields.integer('Maximum Avalaible Seats', oldname='register_max', help="You can for each event define a maximum registration level. If you have too much registrations you are not able to confirm your event. (put 0 to ignore this rule )"),
'seats_max': fields.integer('Maximum Available Seats', oldname='register_max', help="You can for each event define a maximum registration level. If you have too much registrations you are not able to confirm your event. (put 0 to ignore this rule )"),
'seats_reserved': fields.function(_get_seats, string='Reserved Seats', type='integer', multi='seats_reserved'),
'seats_available': fields.function(_get_seats, string='Available Seats', type='integer', multi='seats_reserved'),
'seats_unconfirmed': fields.function(_get_seats, string='Unconfirmed Seat Reservations', type='integer', multi='seats_reserved'),
+2 -1
View File
@@ -35,7 +35,7 @@ import base64
from openerp import addons
from openerp.osv import fields, osv
from openerp import tools
from openerp import tools, api
from openerp.tools.translate import _
_logger = logging.getLogger(__name__)
@@ -129,6 +129,7 @@ openerp_mailgate: "|/path/to/openerp-mailgate.py --host=localhost -u %(uid)d -p
self.write(cr, uid, ids , {'state':'draft'})
return True
@api.cr_uid_ids_context
def connect(self, cr, uid, server_id, context=None):
if isinstance(server_id, (list,tuple)):
server_id = server_id[0]
@@ -59,6 +59,14 @@ class hr_evaluation_report(osv.Model):
}
_order = 'create_date desc'
_depends = {
'hr.evaluation.interview': ['evaluation_id', 'id', 'request_id'],
'hr_evaluation.evaluation': [
'create_date', 'date', 'date_close', 'employee_id', 'plan_id',
'rating', 'state',
],
}
def init(self, cr):
tools.drop_view_if_exists(cr, 'hr_evaluation_report')
cr.execute("""
@@ -220,8 +220,7 @@ class report_custom(report_rml):
elif data['model']=='ir.ui.menu':
for dept in obj_dept.browse(cr, uid, data['form']['depts'], context=context):
cr.execute("SELECT id FROM hr_employee WHERE department_id = %s", (dept.id,))
emp_ids = [x[0] for x in cr.fetchall()]
emp_ids = obj_emp.search(cr, uid, [('department_id', '=', dept.id)], context=context)
if emp_ids==[]:
continue
dept_done=0
@@ -532,6 +532,11 @@ class hr_timesheet_sheet_sheet_day(osv.osv):
'total_attendance': fields.float('Attendance', readonly=True),
'total_difference': fields.float('Difference', readonly=True),
}
_depends = {
'account.analytic.line': ['date', 'unit_amount'],
'hr.analytic.timesheet': ['line_id', 'sheet_id'],
'hr.attendance': ['action', 'name', 'sheet_id'],
}
def init(self, cr):
cr.execute("""create or replace view hr_timesheet_sheet_sheet_day as
@@ -602,6 +607,12 @@ class hr_timesheet_sheet_sheet_account(osv.osv):
'invoice_rate': fields.many2one('hr_timesheet_invoice.factor', 'Invoice rate', readonly=True),
}
_depends = {
'account.analytic.line': ['account_id', 'date', 'to_invoice', 'unit_amount', 'user_id'],
'hr.analytic.timesheet': ['line_id'],
'hr_timesheet_sheet.sheet': ['date_from', 'date_to', 'user_id'],
}
def init(self, cr):
cr.execute("""create or replace view hr_timesheet_sheet_sheet_account as (
select
+22
View File
@@ -0,0 +1,22 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2014 Tech Receptives (<http://techreceptives.com>).
#
# 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/>.
#
##############################################################################
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+56
View File
@@ -0,0 +1,56 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2014 Tech Receptives (<http://techreceptives.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Singapore - Accounting',
'version': '1.0',
'author': 'Tech Receptives',
'website': 'http://www.techreceptives.com',
'category': 'Localization/Account Charts',
'description': """
Singapore accounting chart and localization.
=======================================================
After installing this module, the Configuration wizard for accounting is launched.
* The Chart of Accounts consists of the list of all the general ledger accounts
required to maintain the transactions of Singapore.
* On that particular wizard, you will be asked to pass the name of the company,
the chart template to follow, the no. of digits to generate, the code for your
account and bank account, currency to create journals.
* The Chart of Taxes would display the different types/groups of taxes such as
Standard Rates, Zeroed, Exempted, MES and Out of Scope.
* The tax codes are specified considering the Tax Group and for easy accessibility of
submission of GST Tax Report.
""",
'depends': ['base', 'account', 'account_chart'],
'demo': [ ],
'data': [
'l10n_sg_chart_tax_code.xml',
'l10n_sg_chart.xml',
'l10n_sg_chart_tax.xml',
'l10n_sg_wizard.xml',
],
'installable': True,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
File diff suppressed because it is too large Load Diff
+352
View File
@@ -0,0 +1,352 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<!-- Sales Tax -->
<record id="sg_sale_tax_es_0" model="account.tax.template">
<field name="name">Sales Tax 0% ES33</field>
<field name="description">0% ES33</field>
<field name="price_include" eval="0"/>
<field name="amount">0.0</field>
<field name="type">percent</field>
<field name="type_tax_use">sale</field>
<field name="ref_base_sign">-1</field>
<field name="ref_tax_sign">-1</field>
<field name="account_collected_id" ref="account_account_791"/>
<field name="account_paid_id" ref="account_account_791"/>
<field name="base_code_id" ref="sg_base_code_exempted_sale_ES33"/>
<field name="tax_code_id" ref="sg_tax_code_exempted_sale_ES33"/>
<field name="ref_base_code_id" ref="sg_base_code_exempted_sale_ES33"/>
<field name="ref_tax_code_id" ref="sg_tax_code_exempted_sale_ES33"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_sale_tax_ds_7" model="account.tax.template">
<field name="name">Sales Tax 7% DS</field>
<field name="description">7% DS</field>
<field name="price_include" eval="0"/>
<field name="amount">0.07</field>
<field name="type">percent</field>
<field name="type_tax_use">sale</field>
<field name="ref_base_sign">-1</field>
<field name="ref_tax_sign">-1</field>
<field name="account_collected_id" ref="account_account_792"/>
<field name="account_paid_id" ref="account_account_792"/>
<field name="base_code_id" ref="sg_base_code_standard_sale_7_DS"/>
<field name="tax_code_id" ref="sg_tax_code_tax_received_7_DS"/>
<field name="ref_base_code_id" ref="sg_base_code_standard_sale_7_DS"/>
<field name="ref_tax_code_id" ref="sg_tax_code_tax_received_7_DS"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_sale_tax_esn_0" model="account.tax.template">
<field name="name">Sales Tax 0% ESN33</field>
<field name="description">0% ESN33</field>
<field name="price_include" eval="0"/>
<field name="amount">0.0</field>
<field name="type">percent</field>
<field name="type_tax_use">sale</field>
<field name="ref_base_sign">-1</field>
<field name="ref_tax_sign">-1</field>
<field name="account_collected_id" ref="account_account_793"/>
<field name="account_paid_id" ref="account_account_793"/>
<field name="base_code_id" ref="sg_base_code_exempted_sale_ESN33"/>
<field name="tax_code_id" ref="sg_tax_code_exempted_sale_ESN33"/>
<field name="ref_base_code_id" ref="sg_base_code_exempted_sale_ESN33"/>
<field name="ref_tax_code_id" ref="sg_tax_code_exempted_sale_ESN33"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_sale_tax_os_0" model="account.tax.template">
<field name="name">Sales Tax 0% OS</field>
<field name="description">0% OS</field>
<field name="price_include" eval="0"/>
<field name="amount">0.0</field>
<field name="type">percent</field>
<field name="type_tax_use">sale</field>
<field name="ref_base_sign">-1</field>
<field name="ref_tax_sign">-1</field>
<field name="account_collected_id" ref="account_account_794"/>
<field name="account_paid_id" ref="account_account_794"/>
<field name="base_code_id" ref="sg_base_code_out_scope_sale"/>
<field name="tax_code_id" ref="sg_tax_code_out_scope_sale"/>
<field name="ref_base_code_id" ref="sg_base_code_out_scope_sale"/>
<field name="ref_tax_code_id" ref="sg_tax_code_out_scope_sale"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_sale_tax_zr_0" model="account.tax.template">
<field name="name">Sales Tax 0% ZR</field>
<field name="description">0% ZR</field>
<field name="price_include" eval="0"/>
<field name="amount">0.00</field>
<field name="type">percent</field>
<field name="type_tax_use">sale</field>
<field name="ref_base_sign">-1</field>
<field name="ref_tax_sign">-1</field>
<field name="account_collected_id" ref="account_account_795"/>
<field name="account_paid_id" ref="account_account_795"/>
<field name="base_code_id" ref="sg_base_code_standard_sale_0"/>
<field name="tax_code_id" ref="sg_tax_code_tax_received_0"/>
<field name="ref_base_code_id" ref="sg_base_code_standard_sale_0"/>
<field name="ref_tax_code_id" ref="sg_tax_code_tax_received_0"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_sale_tax_sr_7" model="account.tax.template">
<field name="name">Sales Tax 7% SR</field>
<field name="description">7% SR</field>
<field name="price_include" eval="0"/>
<field name="amount">0.07</field>
<field name="type">percent</field>
<field name="type_tax_use">sale</field>
<field name="ref_base_sign">-1</field>
<field name="ref_tax_sign">-1</field>
<field name="account_collected_id" ref="account_account_796"/>
<field name="account_paid_id" ref="account_account_796"/>
<field name="base_code_id" ref="sg_base_code_standard_sale_7_SR"/>
<field name="tax_code_id" ref="sg_tax_code_tax_received_7_SR"/>
<field name="ref_base_code_id" ref="sg_base_code_standard_sale_7_SR"/>
<field name="ref_tax_code_id" ref="sg_tax_code_tax_received_7_SR"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<!-- Purchases Tax -->
<record id="sg_purchase_tax_txn33_7" model="account.tax.template">
<field name="name">Purchase Tax 7% TX-N33</field>
<field name="description">7% TX-N33</field>
<field name="account_collected_id" ref="account_account_738"/>
<field name="account_paid_id" ref="account_account_738"/>
<field name="price_include" eval="0"/>
<field name="amount">0.07</field>
<field name="type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="base_sign">-1</field>
<field name="tax_sign">-1</field>
<field name="base_code_id" ref="sg_base_code_standard_purchase_7_TX-N33"/>
<field name="tax_code_id" ref="sg_tax_code_tax_paid_7_TX-N33"/>
<field name="ref_base_code_id" ref="sg_base_code_standard_purchase_7_TX-N33"/>
<field name="ref_tax_code_id" ref="sg_tax_code_tax_paid_7_TX-N33"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_purchase_tax_txe33_7" model="account.tax.template">
<field name="name">Purchase Tax 7% TX-E33</field>
<field name="description">7% TX-E33</field>
<field name="account_collected_id" ref="account_account_739"/>
<field name="account_paid_id" ref="account_account_739"/>
<field name="price_include" eval="0"/>
<field name="amount">0.07</field>
<field name="type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="base_sign">-1</field>
<field name="tax_sign">-1</field>
<field name="base_code_id" ref="sg_base_code_standard_purchase_7_TX-E33"/>
<field name="tax_code_id" ref="sg_tax_code_tax_paid_7_TX-E33"/>
<field name="ref_base_code_id" ref="sg_base_code_standard_purchase_7_TX-E33"/>
<field name="ref_tax_code_id" ref="sg_tax_code_tax_paid_7_TX-E33"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_purchase_tax_bl_7" model="account.tax.template">
<field name="name">Purchase Tax 7% BL</field>
<field name="description">7% BL</field>
<field name="account_collected_id" ref="account_account_740"/>
<field name="account_paid_id" ref="account_account_740"/>
<field name="price_include" eval="0"/>
<field name="amount">0.07</field>
<field name="type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="base_sign">-1</field>
<field name="tax_sign">-1</field>
<field name="base_code_id" ref="sg_base_code_standard_purchase_7_BL"/>
<field name="tax_code_id" ref="sg_tax_code_tax_paid_7_BL"/>
<field name="ref_base_code_id" ref="sg_base_code_standard_purchase_7_BL"/>
<field name="ref_tax_code_id" ref="sg_tax_code_tax_paid_7_BL"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_purchase_tax_im_7" model="account.tax.template">
<field name="name">Purchase Tax 7% IM</field>
<field name="description">7% IM</field>
<field name="account_collected_id" ref="account_account_741"/>
<field name="account_paid_id" ref="account_account_741"/>
<field name="price_include" eval="0"/>
<field name="amount">0.07</field>
<field name="type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="base_sign">-1</field>
<field name="tax_sign">-1</field>
<field name="base_code_id" ref="sg_base_code_standard_purchase_7_IM"/>
<field name="tax_code_id" ref="sg_tax_code_tax_paid_7_IM"/>
<field name="ref_base_code_id" ref="sg_base_code_standard_purchase_7_IM"/>
<field name="ref_tax_code_id" ref="sg_tax_code_tax_paid_7_IM"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_purchase_tax_txre_7" model="account.tax.template">
<field name="name">Purchase Tax 7% TX-RE</field>
<field name="description">7% TX-RE</field>
<field name="account_collected_id" ref="account_account_742"/>
<field name="account_paid_id" ref="account_account_742"/>
<field name="price_include" eval="0"/>
<field name="amount">0.07</field>
<field name="type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="base_sign">-1</field>
<field name="tax_sign">-1</field>
<field name="base_code_id" ref="sg_base_code_standard_purchase_7_TX-RE"/>
<field name="tax_code_id" ref="sg_tax_code_tax_paid_7_TX-RE"/>
<field name="ref_base_code_id" ref="sg_base_code_standard_purchase_7_TX-RE"/>
<field name="ref_tax_code_id" ref="sg_tax_code_tax_paid_7_TX-RE"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_purchase_tax_me_0" model="account.tax.template">
<field name="name">Purchase Tax 0% ME</field>
<field name="description">0% ME</field>
<field name="account_collected_id" ref="account_account_743"/>
<field name="account_paid_id" ref="account_account_743"/>
<field name="price_include" eval="0"/>
<field name="amount">0.0</field>
<field name="type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="base_sign">-1</field>
<field name="tax_sign">-1</field>
<field name="base_code_id" ref="sg_base_code_standard_purchase_0_ME"/>
<field name="tax_code_id" ref="sg_tax_code_tax_paid_0_ME"/>
<field name="ref_base_code_id" ref="sg_base_code_standard_purchase_0_ME"/>
<field name="ref_tax_code_id" ref="sg_tax_code_tax_paid_0_ME"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_purchase_tax_nr_0" model="account.tax.template">
<field name="name">Purchase Tax 0% NR</field>
<field name="description">0% NR</field>
<field name="account_collected_id" ref="account_account_744"/>
<field name="account_paid_id" ref="account_account_744"/>
<field name="price_include" eval="0"/>
<field name="amount">0.0</field>
<field name="type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="base_sign">-1</field>
<field name="tax_sign">-1</field>
<field name="base_code_id" ref="sg_base_code_standard_purchase_0_NR"/>
<field name="tax_code_id" ref="sg_tax_code_tax_paid_0_NR"/>
<field name="ref_base_code_id" ref="sg_base_code_standard_purchase_0_NR"/>
<field name="ref_tax_code_id" ref="sg_tax_code_tax_paid_0_NR"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_purchase_tax_zp_0" model="account.tax.template">
<field name="name">Purchase Tax 0% ZP</field>
<field name="description">0% ZP</field>
<field name="account_collected_id" ref="account_account_745"/>
<field name="account_paid_id" ref="account_account_745"/>
<field name="price_include" eval="0"/>
<field name="amount">0.0</field>
<field name="type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="base_sign">-1</field>
<field name="tax_sign">-1</field>
<field name="base_code_id" ref="sg_base_code_standard_purchase_0_ZP"/>
<field name="tax_code_id" ref="sg_tax_code_tax_paid_0_ZP"/>
<field name="ref_base_code_id" ref="sg_base_code_standard_purchase_0_ZP"/>
<field name="ref_tax_code_id" ref="sg_tax_code_tax_paid_0_ZP"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_purchase_tax_op_0" model="account.tax.template">
<field name="name">Purchase Tax 0% OP</field>
<field name="description">0% OP</field>
<field name="account_collected_id" ref="account_account_746"/>
<field name="account_paid_id" ref="account_account_746"/>
<field name="price_include" eval="0"/>
<field name="amount">0.0</field>
<field name="type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="base_sign">-1</field>
<field name="tax_sign">-1</field>
<field name="base_code_id" ref="sg_base_code_out_scope_purchase"/>
<field name="tax_code_id" ref="sg_tax_code_out_scope_purchase"/>
<field name="ref_base_code_id" ref="sg_base_code_out_scope_purchase"/>
<field name="ref_tax_code_id" ref="sg_tax_code_out_scope_purchase"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_purchase_tax_ep_0" model="account.tax.template">
<field name="name">Purchase Tax 0% EP</field>
<field name="description">0% EP</field>
<field name="account_collected_id" ref="account_account_747"/>
<field name="account_paid_id" ref="account_account_747"/>
<field name="price_include" eval="0"/>
<field name="amount">0.0</field>
<field name="type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="base_sign">-1</field>
<field name="tax_sign">-1</field>
<field name="base_code_id" ref="sg_base_code_exempted_purchase"/>
<field name="tax_code_id" ref="sg_tax_code_exempted_purchase"/>
<field name="ref_base_code_id" ref="sg_base_code_exempted_purchase"/>
<field name="ref_tax_code_id" ref="sg_tax_code_exempted_purchase"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_purchase_tax_mes_0" model="account.tax.template">
<field name="name">Purchase Tax MES</field>
<field name="description">0% MES</field>
<field name="account_collected_id" ref="account_account_748"/>
<field name="account_paid_id" ref="account_account_748"/>
<field name="price_include" eval="0"/>
<field name="amount">0.0</field>
<field name="type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="base_sign">-1</field>
<field name="tax_sign">-1</field>
<field name="base_code_id" ref="sg_base_code_mes_import_purchase"/>
<field name="tax_code_id" ref="sg_tax_code_mes_purchase"/>
<field name="ref_base_code_id" ref="sg_base_code_mes_import_purchase"/>
<field name="ref_tax_code_id" ref="sg_tax_code_mes_purchase"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
<record id="sg_purchase_tax_tx7_7" model="account.tax.template">
<field name="name">Purchase Tax 7% TX7</field>
<field name="description">7% TX7</field>
<field name="account_collected_id" ref="account_account_749"/>
<field name="account_paid_id" ref="account_account_749"/>
<field name="price_include" eval="0"/>
<field name="amount">0.07</field>
<field name="type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="base_sign">-1</field>
<field name="tax_sign">-1</field>
<field name="base_code_id" ref="sg_base_code_standard_purchase_7_TX7"/>
<field name="tax_code_id" ref="sg_tax_code_tax_paid_7_TX7"/>
<field name="ref_base_code_id" ref="sg_base_code_standard_purchase_7_TX7"/>
<field name="ref_tax_code_id" ref="sg_tax_code_tax_paid_7_TX7"/>
<field name="child_depend" eval="0"/>
<field name="chart_template_id" ref="sg_chart_template"/>
</record>
</data>
</openerp>
+262
View File
@@ -0,0 +1,262 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record model="account.tax.code.template" id="sg_tax_code_tax_root">
<field name="name">Chart of Singapore</field>
</record>
<record model="account.tax.code.template" id="sg_tax_code_tax_bases">
<field name="name">Tax Bases</field>
<field name="parent_id" ref="sg_tax_code_tax_root"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_tax_balance_pay">
<field name="name">Tax Balance To Pay</field>
<field name="code">[Box 8]</field>
<field name="parent_id" ref="sg_tax_code_tax_root"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_exempted">
<field name="name">Exempted Taxes</field>
<field name="parent_id" ref="sg_tax_code_tax_root"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_out_of_scope">
<field name="name">Out of Scope Taxes</field>
<field name="parent_id" ref="sg_tax_code_tax_root"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_mes_purchase">
<field name="name">MES Purchase Tax</field>
<field name="parent_id" ref="sg_tax_code_tax_root"/>
</record>
<!-- Base Codes -->
<record model="account.tax.code.template" id="sg_base_code_taxed_sale">
<field name="name">Base of Taxed Sales</field>
<field name="code">[Box 4]</field>
<field name="parent_id" ref="sg_tax_code_tax_bases"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_standard_sale_7">
<field name="name">Sales 7% Standard</field>
<field name="code">[Box 1]</field>
<field name="parent_id" ref="sg_base_code_taxed_sale"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_standard_sale_7_SR">
<field name="name">Sales 7% Standard SR</field>
<field name="code"></field>
<field name="parent_id" ref="sg_base_code_standard_sale_7"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_standard_sale_7_DS">
<field name="name">Sales 7% Standard DS</field>
<field name="code"></field>
<field name="parent_id" ref="sg_base_code_standard_sale_7"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_standard_sale_0">
<field name="name">Sales 0% Standard</field>
<field name="code">[Box 2]</field>
<field name="parent_id" ref="sg_base_code_taxed_sale"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_exempted_sale">
<field name="name">Sales Exempted</field>
<field name="code">[Box 3]</field>
<field name="parent_id" ref="sg_base_code_taxed_sale"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_exempted_sale_ES33">
<field name="name">Sales Exempted ES33</field>
<field name="code"></field>
<field name="parent_id" ref="sg_base_code_exempted_sale"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_exempted_sale_ESN33">
<field name="name">Sales Exempted ESN33</field>
<field name="code"></field>
<field name="parent_id" ref="sg_base_code_exempted_sale"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_taxed_purchase">
<field name="name">Base of Taxed Purchases</field>
<field name="code">[Box 5]</field>
<field name="parent_id" ref="sg_tax_code_tax_bases"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_standard_purchase_7_TX7">
<field name="name">Purchase 7% Standard TX7</field>
<field name="parent_id" ref="sg_base_code_taxed_purchase"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_standard_purchase_7_TX-N33">
<field name="name">Purchase 7% Standard TX-N33</field>
<field name="parent_id" ref="sg_base_code_taxed_purchase"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_standard_purchase_7_TX-E33">
<field name="name">Purchase 7% Standard TX-E33</field>
<field name="parent_id" ref="sg_base_code_taxed_purchase"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_standard_purchase_7_BL">
<field name="name">Purchase 7% Standard BL</field>
<field name="parent_id" ref="sg_base_code_taxed_purchase"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_standard_purchase_7_IM">
<field name="name">Purchase 7% Standard IM</field>
<field name="parent_id" ref="sg_base_code_taxed_purchase"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_standard_purchase_7_TX-RE">
<field name="name">Purchase 7% Standard TX-RE</field>
<field name="parent_id" ref="sg_base_code_taxed_purchase"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_standard_purchase_0_ME">
<field name="name">Purchase 0% Standard ME</field>
<field name="parent_id" ref="sg_base_code_taxed_purchase"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_standard_purchase_0_NR">
<field name="name">Purchase 0% Standard NR</field>
<field name="parent_id" ref="sg_base_code_taxed_purchase"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_standard_purchase_0_ZP">
<field name="name">Purchase 0% Standard ZP</field>
<field name="parent_id" ref="sg_base_code_taxed_purchase"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_mes_import_purchase">
<field name="name">Purchase Imports Under MES</field>
<field name="code">[Box 9]</field>
<field name="parent_id" ref="sg_tax_code_tax_bases"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_exempted_purchase">
<field name="name">Purchase Exempted</field>
<field name="parent_id" ref="sg_tax_code_tax_bases"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_out_scope_purchase">
<field name="name">Purchase Out Of Scope</field>
<field name="parent_id" ref="sg_tax_code_tax_bases"/>
</record>
<record model="account.tax.code.template" id="sg_base_code_out_scope_sale">
<field name="name">Sales Out Of Scope</field>
<field name="parent_id" ref="sg_tax_code_tax_bases"/>
</record>
<!-- Tax Codes -->
<record model="account.tax.code.template" id="sg_tax_code_tax_received">
<field name="name">Tax Received</field>
<field name="code">[Box 6]</field>
<field name="parent_id" ref="sg_tax_code_tax_balance_pay"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_tax_received_0">
<field name="name">Tax Received @ 0%</field>
<field name="parent_id" ref="sg_tax_code_tax_received"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_tax_received_7_SR">
<field name="name">Tax Received @ 7% SR</field>
<field name="parent_id" ref="sg_tax_code_tax_received"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_tax_received_7_DS">
<field name="name">Tax Received @ 7% DS</field>
<field name="parent_id" ref="sg_tax_code_tax_received"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_tax_paid">
<field name="name">Tax Paid</field>
<field name="code">[Box 7]</field>
<field name="parent_id" ref="sg_tax_code_tax_balance_pay"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_tax_paid_7_TX7">
<field name="name">Tax Paid @ 7% TX7</field>
<field name="parent_id" ref="sg_tax_code_tax_paid"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_tax_paid_7_TX-N33">
<field name="name">Tax Paid @ 7% TX-N33</field>
<field name="parent_id" ref="sg_tax_code_tax_paid"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_tax_paid_7_TX-E33">
<field name="name">Tax Paid @ 7% TX-E33</field>
<field name="parent_id" ref="sg_tax_code_tax_paid"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_tax_paid_7_BL">
<field name="name">Tax Paid @ 7% BL</field>
<field name="parent_id" ref="sg_tax_code_tax_paid"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_tax_paid_7_IM">
<field name="name">Tax Paid @ 7% IM</field>
<field name="parent_id" ref="sg_tax_code_tax_paid"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_tax_paid_7_TX-RE">
<field name="name">Tax Paid @ 7% TX-RE</field>
<field name="parent_id" ref="sg_tax_code_tax_paid"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_tax_paid_0_ME">
<field name="name">Tax Paid @ 0% ME</field>
<field name="parent_id" ref="sg_tax_code_tax_paid"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_tax_paid_0_NR">
<field name="name">Tax Paid @ 0% NR</field>
<field name="parent_id" ref="sg_tax_code_tax_paid"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_tax_paid_0_ZP">
<field name="name">Tax Paid @ 0% ZP</field>
<field name="parent_id" ref="sg_tax_code_tax_paid"/>
</record>
<!-- Exempted Tax Codes -->
<record model="account.tax.code.template" id="sg_tax_code_exempted_purchase">
<field name="name">Exempted Purchase Tax</field>
<field name="parent_id" ref="sg_tax_code_exempted"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_exempted_sale_ES33">
<field name="name">Exempted Sales Tax ES33</field>
<field name="parent_id" ref="sg_tax_code_exempted"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_exempted_sale_ESN33">
<field name="name">Exempted Sales Tax ESN33</field>
<field name="parent_id" ref="sg_tax_code_exempted"/>
</record>
<!-- Out of Scope Tax Codes -->
<record model="account.tax.code.template" id="sg_tax_code_out_scope_purchase">
<field name="name">Out of Scope Purchase Tax</field>
<field name="parent_id" ref="sg_tax_code_out_of_scope"/>
</record>
<record model="account.tax.code.template" id="sg_tax_code_out_scope_sale">
<field name="name">Out of Scope Sales Tax</field>
<field name="parent_id" ref="sg_tax_code_out_of_scope"/>
</record>
</data>
</openerp>
+9
View File
@@ -0,0 +1,9 @@
<openerp>
<data noupdate="1">
<record id="account.action_wizard_multi_chart_todo" model="ir.actions.todo">
<field name="state">open</field>
</record>
</data>
</openerp>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

+6 -4
View File
@@ -12,8 +12,9 @@
<attribute name="groups"></attribute>
</xpath>
<xpath expr="//field[@name='company_id']" position="after">
<field name="type_id"/>
<field name="channel_id" widget="selection"/>
<field name="campaign_id" />
<field name="medium_id"/>
<field name="source_id" />
</xpath>
</field>
</record>
@@ -25,8 +26,9 @@
<field name="arch" type="xml">
<xpath expr="//group[@name='mailings']" position="before">
<group string="Marketing">
<field name="type_id" />
<field name="channel_id" widget="selection"/>
<field name="campaign_id" />
<field name="medium_id" />
<field name="source_id" />
</group>
</xpath>
</field>
+5
View File
@@ -74,6 +74,11 @@ class MailMail(osv.Model):
""" Override to add the tracking URL to the body. """
body = super(MailMail, self).send_get_mail_body(cr, uid, mail, partner=partner, context=context)
# prepend <base> tag for images using absolute urls
domain = self.pool.get("ir.config_parameter").get_param(cr, uid, "web.base.url", context=context)
base = "<base href='%s'>" % domain
body = tools.append_content_to_html(base, body, plaintext=False, container_tag='div')
# generate tracking URL
if mail.statistics_ids:
tracking_url = self._get_tracking_url(cr, uid, mail, partner, context=context)
@@ -144,7 +144,6 @@ class MassMailingCampaign(osv.Model):
row['replied_ratio'] = 100.0 * row['replied'] / total
return results
_columns = {
'name': fields.char('Name', required=True),
'stage_id': fields.many2one('mail.mass_mailing.stage', 'Stage', required=True),
@@ -326,7 +325,6 @@ class MassMailing(osv.Model):
row['replied_ratio'] = 100.0 * row['replied'] / total
return results
def _get_mailing_model(self, cr, uid, context=None):
res = []
for model_name in self.pool:
+12 -6
View File
@@ -364,7 +364,7 @@ class product_attribute_value(osv.osv):
_columns = {
'sequence': fields.integer('Sequence', help="Determine the display order"),
'name': fields.char('Value', translate=True, required=True),
'attribute_id': fields.many2one('product.attribute', 'Attribute', required=True),
'attribute_id': fields.many2one('product.attribute', 'Attribute', required=True, ondelete='cascade'),
'product_ids': fields.many2many('product.product', id1='att_id', id2='prod_id', string='Variants', readonly=True),
'price_extra': fields.function(_get_price_extra, type='float', string='Attribute Price Extra',
fnct_inv=_set_price_extra,
@@ -378,20 +378,26 @@ class product_attribute_value(osv.osv):
_defaults = {
'price_extra': 0.0,
}
def unlink(self, cr, uid, ids, context=None):
ctx = dict(context or {}, active_test=False)
product_ids = self.pool['product.product'].search(cr, uid, [('attribute_value_ids', 'in', ids)], context=ctx)
if product_ids:
raise osv.except_osv(_('Integrity Error!'), _('The operation cannot be completed:\nYou trying to delete an attribute value with a reference on a product variant.'))
return super(product_attribute_value, self).unlink(cr, uid, ids, context=context)
class product_attribute_price(osv.osv):
_name = "product.attribute.price"
_columns = {
'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True),
'value_id': fields.many2one('product.attribute.value', 'Product Attribute Value', required=True),
'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True, ondelete='cascade'),
'value_id': fields.many2one('product.attribute.value', 'Product Attribute Value', required=True, ondelete='cascade'),
'price_extra': fields.float('Price Extra', digits_compute=dp.get_precision('Product Price')),
}
class product_attribute_line(osv.osv):
_name = "product.attribute.line"
_columns = {
'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True),
'attribute_id': fields.many2one('product.attribute', 'Attribute', required=True),
'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True, ondelete='cascade'),
'attribute_id': fields.many2one('product.attribute', 'Attribute', required=True, ondelete='restrict'),
'value_ids': fields.many2many('product.attribute.value', id1='line_id', id2='val_id', string='Product Attribute Value'),
}
@@ -898,7 +904,7 @@ class product_product(osv.osv):
'product.template': (_get_name_template_ids, ['name'], 10),
'product.product': (lambda self, cr, uid, ids, c=None: ids, [], 10),
}, select=True),
'attribute_value_ids': fields.many2many('product.attribute.value', id1='prod_id', id2='att_id', string='Attributes', readonly=True),
'attribute_value_ids': fields.many2many('product.attribute.value', id1='prod_id', id2='att_id', string='Attributes', readonly=True, ondelete='restrict'),
# image: all image fields are base64 encoded and PIL-supported
'image_variant': fields.binary("Variant Image",
+1 -1
View File
@@ -10,6 +10,6 @@
report_type="qweb-pdf"
name="product.report_pricelist"
file="product.report_pricelist"
/>
menu="False"/>
</data>
</openerp>
+54 -2
View File
@@ -69,7 +69,7 @@
<group>
<field name="type"/>
<field name="uom_id" on_change="onchange_uom(uom_id,uom_po_id)" groups="product.group_uom"/>
<field name="lst_price"/>
<field name="list_price"/>
</group>
<group>
<field name="active"/>
@@ -193,6 +193,7 @@
<record id="variants_template_tree_view" model="ir.ui.view">
<field name="name">variants.template.tree</field>
<field name="model">product.attribute.value</field>
<field name="priority" eval="2"/>
<field name="arch" type="xml">
<tree string="Variant Values" editable="top">
<field name="sequence" widget="handle"/>
@@ -214,7 +215,7 @@
<!-- product product -->
<menuitem id="prod_config_main" name="Product Variants" parent="base.menu_base_config" sequence="70" groups="base.group_no_one"/>
<menuitem id="prod_config_main" name="Product Categories &amp; Attributes" parent="base.menu_base_config" sequence="70" groups="base.group_no_one"/>
<record id="product_search_form_view" model="ir.ui.view">
<field name="name">product.product.search</field>
@@ -268,6 +269,9 @@
<form position="attributes">
<attribute name="string">Product Variant</attribute>
</form>
<field name="list_price" position="attributes">
<attribute name="name">lst_price</attribute>
</field>
<field name="name" position="replace">
<field name="name" attrs="{'invisible': [('id', '!=', False)]}"/>
<field name="product_tmpl_id" class="oe_inline" readonly="1" attrs="{'invisible': [('id', '=', False)], 'required': [('id', '!=', False)]}"/>
@@ -385,6 +389,54 @@
<!-- -->
<record id="attribute_tree_view" model="ir.ui.view">
<field name="name">product.attribute.tree</field>
<field name="model">product.attribute</field>
<field name="arch" type="xml">
<tree string="Variant Values" editable="top">
<field name="name"/>
</tree>
</field>
</record>
<record id="attribute_action" model="ir.actions.act_window">
<field name="name">Attributes</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">product.attribute</field>
<field name="view_mode">tree</field>
<field name="view_type">form</field>
</record>
<menuitem action="attribute_action"
id="menu_attribute_action"
parent="product.prod_config_main" sequence="9" />
<record id="variants_tree_view" model="ir.ui.view">
<field name="name">product.attribute.value.tree</field>
<field name="model">product.attribute.value</field>
<field name="arch" type="xml">
<tree string="Variant Values" editable="top">
<field name="sequence" widget="handle"/>
<field name="attribute_id"/>
<field name="name"/>
</tree>
</field>
</record>
<record id="variants_action" model="ir.actions.act_window">
<field name="name">Attribute Values</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">product.attribute.value</field>
<field name="view_mode">tree</field>
<field name="view_type">form</field>
</record>
<menuitem action="variants_action"
id="menu_variants_action"
parent="product.prod_config_main" sequence="10" />
<!-- -->
<record id="product_normal_action_sell" model="ir.actions.act_window">
<field name="name">Product Variants</field>
<field name="type">ir.actions.act_window</field>
+14 -13
View File
@@ -209,9 +209,9 @@ class purchase_order(osv.osv):
"It's mainly used to do the matching when you receive the "
"products as this reference is usually written on the "
"delivery order sent by your supplier."),
'date_order':fields.date('Order Date', required=True, states={'confirmed':[('readonly',True)],
'date_order':fields.datetime('Order Date', required=True, states={'confirmed':[('readonly',True)],
'approved':[('readonly',True)]},
select=True, help="Date on which this document has been created.",
select=True, help="Depicts the date where the Quotation should be validated and converted into a Purchase Order, by default it's the creation date.",
copy=False),
'date_approve':fields.date('Date Approved', readonly=1, select=True, copy=False,
help="Date on which purchase order has been approved"),
@@ -290,7 +290,7 @@ class purchase_order(osv.osv):
'invoice_count': fields.function(_count_all, type='integer', string='Invoices', multi=True)
}
_defaults = {
'date_order': fields.date.context_today,
'date_order': fields.datetime.now,
'state': 'draft',
'name': lambda obj, cr, uid, context: '/',
'shipped': 0,
@@ -710,7 +710,7 @@ class purchase_order(osv.osv):
'product_id': order_line.product_id.id,
'product_uom': order_line.product_uom.id,
'product_uos': order_line.product_uom.id,
'date': fields.date.date_to_datetime(self, cr, uid, order.date_order, context),
'date': order.date_order,
'date_expected': fields.date.date_to_datetime(self, cr, uid, order_line.date_planned, context),
'location_id': order.partner_id.property_stock_supplier.id,
'location_dest_id': order.location_id.id,
@@ -980,8 +980,8 @@ class purchase_order_line(osv.osv):
'order_line_id', 'invoice_id', 'Invoice Lines',
readonly=True, copy=False),
'invoiced': fields.boolean('Invoiced', readonly=True, copy=False),
'partner_id': fields.related('order_id','partner_id',string='Partner',readonly=True,type="many2one", relation="res.partner", store=True),
'date_order': fields.related('order_id','date_order',string='Order Date',readonly=True,type="date"),
'partner_id': fields.related('order_id', 'partner_id', string='Partner', readonly=True, type="many2one", relation="res.partner", store=True),
'date_order': fields.related('order_id', 'date_order', string='Order Date', readonly=True, type="datetime"),
'procurement_ids': fields.one2many('procurement.order', 'purchase_line_id', string='Associated procurements'),
}
_defaults = {
@@ -1026,13 +1026,13 @@ class purchase_order_line(osv.osv):
:param browse_record | False supplier_info: product.supplierinfo, used to
determine delivery delay (if False, default delay = 0)
:param str date_order_str: date of order, as a string in
DEFAULT_SERVER_DATE_FORMAT
:param str date_order_str: date of order field, as a string in
DEFAULT_SERVER_DATETIME_FORMAT
:rtype: datetime
:return: desired Schedule Date for the PO line
"""
supplier_delay = int(supplier_info.delay) if supplier_info else 0
return datetime.strptime(date_order_str, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(days=supplier_delay)
return datetime.strptime(date_order_str, DEFAULT_SERVER_DATETIME_FORMAT) + relativedelta(days=supplier_delay)
def action_cancel(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'state': 'cancel'}, context=context)
@@ -1101,7 +1101,7 @@ class purchase_order_line(osv.osv):
# - determine product_qty and date_planned based on seller info
if not date_order:
date_order = fields.date.context_today(self,cr,uid,context=context)
date_order = fields.datetime.now()
supplierinfo = False
@@ -1125,8 +1125,9 @@ class purchase_order_line(osv.osv):
if state not in ('sent','bid'):
# - determine price_unit and taxes_id
if pricelist_id:
date_order_str = datetime.strptime(date_order, DEFAULT_SERVER_DATETIME_FORMAT).strftime(DEFAULT_SERVER_DATE_FORMAT)
price = product_pricelist.price_get(cr, uid, [pricelist_id],
product.id, qty or 1.0, partner_id or False, {'uom': uom_id, 'date': date_order})[pricelist_id]
product.id, qty or 1.0, partner_id or False, {'uom': uom_id, 'date': date_order_str})[pricelist_id]
else:
price = product.standard_price
@@ -1320,8 +1321,8 @@ class procurement_order(osv.osv):
po_id = available_draft_po_ids[0]
po_rec = po_obj.browse(cr, uid, po_id, context=context)
#if the product has to be ordered earlier those in the existing PO, we replace the purchase date on the order to avoid ordering it too late
if datetime.strptime(po_rec.date_order, DEFAULT_SERVER_DATE_FORMAT) > purchase_date:
po_obj.write(cr, uid, [po_id], {'date_order': purchase_date}, context=context)
if datetime.strptime(po_rec.date_order, DEFAULT_SERVER_DATETIME_FORMAT) > purchase_date:
po_obj.write(cr, uid, [po_id], {'date_order': purchase_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}, context=context)
#look for any other PO line in the selected PO with same product and UoM to sum quantities instead of creating a new po line
available_po_line_ids = po_line_obj.search(cr, uid, [('order_id', '=', po_id), ('product_id', '=', line_vals['product_id']), ('product_uom', '=', line_vals['product_uom'])], context=context)
if available_po_line_ids:
@@ -53,7 +53,7 @@
"code": "EUR",
"symbol": "€",
},
"date_order": "2011-09-13",
"date_order": "2011-09-13 12:00:00",
"partner_id": ["sale:724f9v70-dv70-1v70-8v70-701a04e25v70.res_partner_test22", "Junjun wala"],
"partner_address": {
"__id": "base:724f9v70-dv70-1v70-8v70-701a04e25v70.res_partner_address_7wdsjasdjh",
@@ -154,7 +154,7 @@
"code": "EUR",
"symbol": "€",
},
"date_order": "2011-09-13",
"date_order": "2011-09-13 12:00:00",
"partner_id": ["sale:724f93ec-ddd0-11e0-88ec-701a04e25543.res_partner_test22", "Junjun wala"],
"partner_address": {
"__id": "base:724f93ec-ddd0-11e0-88ec-701a04e25543.res_partner_address_7wdsjasdjh",
@@ -234,4 +234,4 @@
assert purchase_line.price_unit == 20 , "unit price is not same, got %s, expected 20"%(purchase_line.price_unit,)
assert purchase_line.product_qty == 10 , "product qty is not same"
else:
raise AssertionError('unknown order line: %s' % purchase_line)
raise AssertionError('unknown order line: %s' % purchase_line)
@@ -20,8 +20,10 @@
#
##############################################################################
from datetime import datetime
from openerp.osv import fields, osv
from openerp.tools.translate import _
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
import openerp.addons.decimal_precision as dp
class purchase_requisition(osv.osv):
@@ -134,7 +136,7 @@ class purchase_requisition(osv.osv):
picking_type_in = self.pool.get("purchase.order")._get_picking_in(cr, uid, context=context)
return {
'origin': requisition.name,
'date_order': requisition.date_end or fields.date.context_today(self, cr, uid, context=context),
'date_order': requisition.date_end or fields.datetime.now(),
'partner_id': supplier.id,
'pricelist_id': supplier_pricelist,
'location_id': requisition.picking_type_id.default_location_dest_id.id,
@@ -146,11 +148,15 @@ class purchase_requisition(osv.osv):
}
def _prepare_purchase_order_line(self, cr, uid, requisition, requisition_line, purchase_id, supplier, context=None):
if context is None:
context = {}
po_line_obj = self.pool.get('purchase.order.line')
product_uom = self.pool.get('product.uom')
product = requisition_line.product_id
default_uom_po_id = product.uom_po_id.id
date_order = requisition.ordering_date or fields.date.context_today(self, cr, uid, context=context)
ctx = context.copy()
ctx['tz'] = requisition.user_id.tz
date_order = requisition.ordering_date and fields.date.date_to_datetime(self, cr, uid, requisition.ordering_date, context=ctx) or fields.datetime.now()
qty = product_uom._compute_qty(cr, uid, requisition_line.product_uom_id.id, requisition_line.product_qty, default_uom_po_id)
supplier_pricelist = supplier.property_product_pricelist_purchase and supplier.property_product_pricelist_purchase.id or False
vals = po_line_obj.onchange_product_id(
+3
View File
@@ -25,6 +25,9 @@ class account_invoice_report(osv.osv):
_columns = {
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
}
_depends = {
'account.invoice': ['section_id'],
}
def _select(self):
return super(account_invoice_report, self)._select() + ", sub.section_id as section_id"
+2 -1
View File
@@ -22,7 +22,8 @@
from openerp.osv import osv, fields
class sale_order(osv.osv):
_inherit = 'sale.order'
_name = "sale.order"
_inherit = ['sale.order', 'crm.tracking.mixin']
_columns = {
'categ_ids': fields.many2many('crm.case.categ', 'sale_order_category_rel', 'order_id', 'category_id', 'Tags', \
domain="['|', ('section_id', '=', section_id), ('section_id', '=', False), ('object_id.model', '=', 'crm.lead')]", context="{'object_name': 'crm.lead'}")
+6
View File
@@ -29,6 +29,12 @@
<field name="user_id" position="after">
<field name="categ_ids" widget="many2many_tags"/>
</field>
<field name="origin" position="after">
<field name="campaign_id" />
<field name="medium_id" />
<field name="source_id" />
</field>
</field>
</record>
</data>
+1 -1
View File
@@ -3,7 +3,7 @@ access_stock_incoterms_all,stock.incoterms all,model_stock_incoterms,,1,0,0,0
access_stock_incoterms_manager,stock.incoterms manager,model_stock_incoterms,stock.group_stock_manager,1,1,1,1
access_stock_warehouse_manager,stock.warehouse.manager,model_stock_warehouse,stock.group_stock_manager,1,1,1,1
access_stock_warehouse_user,stock.warehouse.user,model_stock_warehouse,base.group_user,1,0,0,0
access_stock_location__partner_manager,stock.location.partner.manager,model_stock_location,base.group_partner_manager,1,1,1,1
access_stock_location__partner_manager,stock.location.partner.manager,model_stock_location,base.group_partner_manager,1,0,0,0
access_stock_location_manager,stock.location.manager,model_stock_location,stock.group_stock_manager,1,1,1,1
access_stock_location_user,stock.location.user,model_stock_location,base.group_user,1,0,0,0
access_stock_picking_user,stock.picking user,model_stock_picking,stock.group_stock_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
3 access_stock_incoterms_manager stock.incoterms manager model_stock_incoterms stock.group_stock_manager 1 1 1 1
4 access_stock_warehouse_manager stock.warehouse.manager model_stock_warehouse stock.group_stock_manager 1 1 1 1
5 access_stock_warehouse_user stock.warehouse.user model_stock_warehouse base.group_user 1 0 0 0
6 access_stock_location__partner_manager stock.location.partner.manager model_stock_location base.group_partner_manager 1 1 0 1 0 1 0
7 access_stock_location_manager stock.location.manager model_stock_location stock.group_stock_manager 1 1 1 1
8 access_stock_location_user stock.location.user model_stock_location base.group_user 1 0 0 0
9 access_stock_picking_user stock.picking user model_stock_picking stock.group_stock_user 1 1 1 1
@@ -20,7 +20,8 @@
##############################################################################
from openerp.osv import fields, osv
from openerp.osv import fields, osv, orm
from openerp.tools.translate import _
class make_procurement(osv.osv_memory):
_name = 'make.procurement'
@@ -108,6 +109,13 @@ class make_procurement(osv.osv_memory):
context = {}
record_id = context.get('active_id')
if context.get('active_model') == 'product.template':
product_ids = self.pool.get('product.product').search(cr, uid, [('product_tmpl_id', '=', context.get('active_id'))], context=context)
if len(product_ids) == 1:
record_id = product_ids[0]
else:
raise orm.except_orm(_('Warning'), _('Please use the Product Variant vue to request a procurement.'))
res = super(make_procurement, self).default_get(cr, uid, fields, context=context)
if record_id and 'product_id' in fields:
@@ -50,6 +50,13 @@ class stock_change_product_qty(osv.osv_memory):
res = super(stock_change_product_qty, self).default_get(cr, uid, fields, context=context)
if context.get('active_model') == 'product.template':
product_ids = self.pool.get('product.product').search(cr, uid, [('product_tmpl_id', '=', context.get('active_id'))], context=context)
if len(product_ids) == 1:
res['product_id'] = product_ids[0]
else:
raise orm.except_orm(_('Warning'), _('Please use the Product Variant vue to update the product quantity.'))
if 'location_id' in fields:
location_id = res.get('location_id', False)
if not location_id:
@@ -77,12 +84,8 @@ class stock_change_product_qty(osv.osv_memory):
if context is None:
context = {}
rec_id = context and context.get('active_id', False)
assert rec_id, _('Active ID is not set in Context')
inventory_obj = self.pool.get('stock.inventory')
inventory_line_obj = self.pool.get('stock.inventory.line')
prod_obj_pool = self.pool.get('product.product')
for data in self.browse(cr, uid, ids, context=context):
if data.new_quantity < 0:
@@ -90,15 +93,18 @@ class stock_change_product_qty(osv.osv_memory):
ctx = context.copy()
ctx['location'] = data.location_id.id
ctx['lot_id'] = data.lot_id.id
res_original = prod_obj_pool.browse(cr, uid, rec_id, context=ctx)
inventory_id = inventory_obj.create(cr, uid, {'name': _('INV: %s') % tools.ustr(res_original.name), 'product_id': rec_id, 'location_id': data.location_id.id, 'lot_id': data.lot_id.id}, context=context)
th_qty = res_original.qty_available
inventory_id = inventory_obj.create(cr, uid, {
'name': _('INV: %s') % tools.ustr(data.product_id.name),
'product_id': data.product_id.id,
'location_id': data.location_id.id,
'lot_id': data.lot_id.id}, context=context)
th_qty = data.product_id.qty_available
line_data = {
'inventory_id': inventory_id,
'product_qty': data.new_quantity,
'location_id': data.location_id.id,
'product_id': rec_id,
'product_uom_id': res_original.uom_id.id,
'product_id': data.product_id.id,
'product_uom_id': data.product_id.uom_id.id,
'th_qty': th_qty,
'prod_lot_id': data.lot_id.id
}
+3 -6
View File
@@ -332,11 +332,8 @@ var Tour = {
+ (step ? '\n waitFor: ' + Boolean(!step.waitFor || $(step.waitFor).size()) : '' )
+ "\n localStorage: " + JSON.stringify(localStorage)
+ '\n\n' + $("body").html();
Tour.reset();
if (state.mode === "test") {
console.log(message);
Tour.endTour();
}
console.log(message);
Tour.endTour();
},
lists: function () {
var tour_ids = [];
@@ -473,7 +470,7 @@ var Tour = {
},
endTour: function () {
var state = Tour.getState();
var test = state.step.id >= state.tour.steps.length-1;
var test = state.step && state.step.id >= state.tour.steps.length-1;
Tour.reset();
if (test) {
console.log("Tour '"+state.id+"' finish: ok");
@@ -24,15 +24,6 @@ instance.web.DiagramView = instance.web.View.extend({
this.ids = this.dataset.ids;
this.on('pager_action_executed', self, self.pager_action_trigger);
},
start: function () {
return this._super().then(function () {
return $.when(
openerp.webclient.session.load_js(['/web/js/web_diagram.assets_raphael'])
);
}).fail(function () {
throw new Error("Could not load raphael.js");
});
},
view_loading: function(r) {
return this.load_diagram(r);
@@ -295,7 +295,7 @@
}
if (obj.config.relativeGaugeSize === true) {
obj.canvas.setViewBox(0, 0, 200, 150, true);
obj.canvas.setViewBox(0, 0, 200, 150, false);
}
// canvas dimensions
@@ -306,7 +306,7 @@
canvasW = obj.config.width;
canvasH = obj.config.height;
} else if (obj.config.parentNode !== null) {
obj.canvas.setViewBox(0, 0, 200, 150, true);
obj.canvas.setViewBox(0, 0, 200, 150, false);
canvasW = 200;
canvasH = 150;
} else {
+1 -2
View File
@@ -40,8 +40,7 @@ class Website(openerp.addons.web.controllers.main.Home):
if not (first_menu.url.startswith(('/page/', '/?', '/#')) or (first_menu.url=='/')):
return request.redirect(first_menu.url)
if first_menu.url.startswith('/page/'):
page = first_menu.url[6:]
return request.registry['ir.http'].reroute(first_menu.url)
return self.page(page)
@http.route(website=True, auth="public")
+1 -1
View File
@@ -76,7 +76,7 @@ class ir_http(orm.AbstractModel):
if self.geo_ip_resolver and request.httprequest.remote_addr:
record = self.geo_ip_resolver.record_by_addr(request.httprequest.remote_addr) or {}
request.session['geoip'] = record
if request.website_enabled:
if func:
self._authenticate(func.routing['auth'])
+13 -13
View File
@@ -94,6 +94,17 @@
<t t-call-assets="website.assets_frontend"/>
<t t-raw="head or ''" name='layout_head'/>
<t t-if="website and website.google_analytics_key">
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','_gaw');
_gaw('create',_.str.trim('<t t-esc="website.google_analytics_key"/>'));
_gaw('send','pageview');
</script>
</t>
</head>
<body>
<div id="wrapwrap">
@@ -150,17 +161,6 @@
</div>
</footer>
</div>
<t t-if="website and website.google_analytics_key">
<script>
(function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
e=o.createElement(i);r=o.getElementsByTagName(i)[0];
e.src='//www.google-analytics.com/analytics.js';
r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
ga('create',_.str.trim('<t t-esc="website.google_analytics_key"/>'));
ga('send','pageview');
</script>
</t>
</body>
</html>
</template>
@@ -696,13 +696,13 @@ Sitemap: <t t-esc="url_root"/>sitemap.xml
</template>
<template id="sitemap_xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<urlset t-attf-xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<t t-raw="content"/>
</urlset>
</template>
<template id="sitemap_index_xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemapindex t-attf-xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap t-foreach="pages" t-as="page">
<loc><t t-esc="url_root"/>sitemap-<t t-esc="page"/>.xml</loc>
</sitemap>
+3 -3
View File
@@ -39,7 +39,7 @@ class contactus(http.Controller):
post_file = [] # List of file to add to ir_attachment once we have the ID
post_description = [] # Info to add after the message
values = {'user_id': False}
values = {}
lead_model = request.registry['crm.lead']
@@ -62,7 +62,7 @@ class contactus(http.Controller):
return request.website.render("website.contactus", values)
try:
values['channel_id'] = request.registry['ir.model.data'].get_object_reference(request.cr, SUPERUSER_ID, 'crm', 'crm_case_channel_website')[1]
values['medium_id'] = request.registry['ir.model.data'].get_object_reference(request.cr, SUPERUSER_ID, 'crm', 'crm_tracking_medium_website')[1]
values['section_id'] = request.registry['ir.model.data'].xmlid_to_res_id(request.cr, SUPERUSER_ID, 'website.salesteam_website_sales')
except ValueError:
pass
@@ -80,7 +80,7 @@ class contactus(http.Controller):
post_description.append("%s: %s" % ("REFERER", environ.get("HTTP_REFERER")))
values['description'] += dict_to_str(_("Environ Fields: "), post_description)
lead_id = lead_model.create(request.cr, SUPERUSER_ID, values, request.context)
lead_id = lead_model.create(request.cr, SUPERUSER_ID, dict(values, user_id=False), request.context)
if lead_id:
for field_value in post_file:
attachment_value = {
@@ -109,7 +109,7 @@ class WebsiteCrmPartnerAssign(http.Controller):
context=request.context) # todo in trunk: order="grade_id DESC, implemented_count DESC", offset=pager['offset'], limit=self._references_per_page
partners = partner_obj.browse(request.cr, SUPERUSER_ID, partner_ids, request.context)
# remove me in trunk
partners = sorted(partners, key=lambda x: (-1 * (x.grade_id and x.grade_id.id or 0), len(x.implemented_partner_ids)), reverse=True)
partners = sorted(partners, key=lambda x: (x.grade_id.sequence if x.grade_id else 0, len([i for i in x.implemented_partner_ids if i.website_published])), reverse=True)
partners = partners[pager['offset']:pager['offset'] + self._references_per_page]
google_map_partner_ids = ','.join(map(str, [p.id for p in partners]))
+3 -2
View File
@@ -112,7 +112,7 @@ class Post(osv.Model):
_name = 'forum.post'
_description = 'Forum Post'
_inherit = ['mail.thread', 'website.seo.metadata']
_order = "is_correct DESC, vote_count DESC"
_order = "is_correct DESC, vote_count DESC, write_date DESC"
def _get_user_vote(self, cr, uid, ids, field_name, arg, context):
res = dict.fromkeys(ids, 0)
@@ -401,6 +401,7 @@ class Post(osv.Model):
Vote = self.pool['forum.post.vote']
vote_ids = Vote.search(cr, uid, [('post_id', 'in', ids), ('user_id', '=', uid)], limit=1, context=context)
new_vote = 0
if vote_ids:
for vote in Vote.browse(cr, uid, vote_ids, context=context):
if upvote:
@@ -412,7 +413,7 @@ class Post(osv.Model):
for post_id in ids:
new_vote = '1' if upvote else '-1'
Vote.create(cr, uid, {'post_id': post_id, 'vote': new_vote}, context=context)
return {'vote_count': self._get_vote_count(cr, uid, ids, None, None, context=context)[ids[0]]}
return {'vote_count': self._get_vote_count(cr, uid, ids, None, None, context=context)[ids[0]], 'user_vote': new_vote}
def convert_answer_to_comment(self, cr, uid, id, context=None):
""" Tools to convert an answer (forum.post) to a comment (mail.message).
@@ -38,11 +38,11 @@ $(document).ready(function () {
}
} else {
$link.parent().find("#vote_count").html(data['vote_count']);
if (data['vote_count'] == 0) {
if (data['user_vote'] == 0) {
$link.parent().find(".text-success").removeClass("text-success");
$link.parent().find(".text-warning").removeClass("text-warning");
} else {
if (data['vote_count'] == 1) {
if (data['user_vote'] == 1) {
$link.addClass("text-success");
} else {
$link.addClass("text-warning");
+1 -1
View File
@@ -428,7 +428,7 @@
t-attf-data-href="/forum/#{slug(post.forum_id)}/post/#{slug(post)}/upvote"/>
<span id="vote_count" t-esc="post.vote_count"/>
<a t-attf-class="vote_down fa fa-thumbs-down no-decoration #{post.user_vote == -1 and 'text-warning' or ''} #{((post.user_vote == -1 and not post.can_upvote) or not post.can_downvote) and 'karma_required' or ''}"
t-attf-data-karma="#{post.user_vote == -1 and post.karma_uovote or post.karma_downvote}"
t-attf-data-karma="#{post.user_vote == -1 and post.karma_upvote or post.karma_downvote}"
t-attf-data-href="/forum/#{slug(post.forum_id)}/post/#{slug(post)}/downvote"/>
<div t-if="vote_count &gt; 1" class="subtitle">
votes
+1 -1
View File
@@ -17,7 +17,7 @@ class WebsiteResPartner(osv.Model):
'Website Partner Full Description'
),
'website_short_description': fields.text(
'Website artner Short Description'
'Website Partner Short Description'
),
# hack to allow using plain browse record in qweb views
'self': fields.function(_get_ids, type='many2one', relation=_name),
+25
View File
@@ -820,5 +820,30 @@ class website_sale(http.Controller):
product = product_obj.browse(request.cr, request.uid, id, context=request.context)
return product.write({'website_size_x': x, 'website_size_y': y})
@http.route(['/shop/tracking_last_order'], type='json', auth="public")
def tracking_cart(self, **post):
""" return JS code for google analytics"""
cr, uid, context = request.cr, request.uid, request.context
ret = {}
sale_order_id = request.session.get('sale_last_order_id')
if sale_order_id:
order = request.registry['sale.order'].browse(cr, SUPERUSER_ID, sale_order_id, context=context)
ret['transaction'] = {
'id': sale_order_id,
'affiliation': order.company_id.name,
'revenue': order.amount_total,
'currency': order.currency_id.name
}
ret['lines'] = []
for line in order.order_line:
if not line.is_delivery:
ret['lines'].append({
'id': line.order_id and line.order_id.id,
'name': line.product_id.categ_id and line.product_id.categ_id.name or '-',
'sku': line.product_id.id,
'quantity': line.product_uom_qty,
'price': line.price_unit,
})
return ret
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -1,4 +1,3 @@
@charset "utf-8";
/* ---- Default Styles ---- */
.oe_product {
border: 1px solid rgba(100, 100, 100, 0.2);
@@ -53,7 +52,7 @@
right: 0;
bottom: 0;
overflow: hidden;
padding: 0 15px 24px 0;
padding: 0 15px 24px 10px;
min-height: 56px;
border-top: 1px solid rgba(255, 255, 255, 0.2);
background: rgba(255, 255, 255, 0.75);
@@ -333,6 +332,14 @@ label.css_attribute_color.css_not_available {
max-height: 500px;
}
.oe_default_price {
display: none;
}
.discount .oe_default_price {
display: block;
}
/* ---- Publish managment and options ---- */
#products_grid .css_options {
display: none;
@@ -47,7 +47,7 @@
right: 0
bottom: 0
overflow: hidden
padding: 0 15px 24px 0
padding: 0 15px 24px 10px
min-height: 56px
border-top: 1px solid rgba(255,255,255,0.2)
background: rgba(255, 255, 255, 0.75)
@@ -282,6 +282,11 @@ label.css_attribute_color.css_not_available
display: block
max-height: 500px
.oe_default_price
display: none
.discount .oe_default_price
display: block
/* ---- Publish managment and options ---- */
#products_grid .css_options
@@ -102,7 +102,11 @@ $('.oe_website_sale').each(function () {
if (_.isEqual(variant_ids[k][1], values)) {
$price.html(price_to_str(variant_ids[k][2]));
$default_price.html(price_to_str(variant_ids[k][3]));
$default_price.parent().toggle(variant_ids[k][3]-variant_ids[k][2]>0.2);
if (variant_ids[k][3]-variant_ids[k][2]>0.2) {
$default_price.closest('.oe_website_sale').addClass("discount");
} else {
$default_price.closest('.oe_website_sale').removeClass("discount");
}
product_id = variant_ids[k][0];
break;
}
@@ -0,0 +1,67 @@
$(document).ready(function () {
// Watching a product
if ($("#product_detail.oe_website_sale").length) {
prod_id = $("input[name='product_id']").attr('value');
vpv("/stats/ecom/product_view/" + prod_id);
}
// Add a product into the cart
$(".oe_website_sale form[action='/shop/cart/update'] a.a-submit").on('click', function(o) {
prod_id = $("input[name='product_id']").attr('value');
vpv("/stats/ecom/product_add_to_cart/" + prod_id);
});
// Start checkout
$(".oe_website_sale a[href='/shop/checkout']").on('click', function(o) {
vpv("/stats/ecom/customer_checkout");
});
$(".oe_website_sale div.oe_cart a[href^='/web?redirect'][href$='/shop/checkout']").on('click', function(o) {
vpv("/stats/ecom/customer_signin");
});
$(".oe_website_sale form[action='/shop/confirm_order'] a.a-submit").on('click', function(o) {
if ($("#top_menu > li > a[href='/web/login']").length){
vpv("/stats/ecom/customer_signup");
}
vpv("/stats/ecom/order_checkout");
});
$(".oe_website_sale form[target='_self'] button[type=submit]").on('click', function(o) {
var method = $("#payment_method input[name=acquirer]:checked").nextAll("span:first").text();
vpv("/stats/ecom/order_payment/" + method);
});
if ($(".oe_website_sale div.oe_cart div.oe_website_sale_tx_status").length) {
track_ga('require', 'ecommerce');
order_id = $(".oe_website_sale div.oe_cart div.oe_website_sale_tx_status").data("order-id");
vpv("/stats/ecom/order_confirmed/" + order_id);
openerp.jsonRpc("/shop/tracking_last_order/").then(function(o) {
track_ga('ecommerce:clear');
if (o.transaction && o.lines) {
track_ga('ecommerce:addTransaction', o.transaction);
_.forEach(o.lines, function(line) {
track_ga('ecommerce:addItem', line);
});
}
track_ga('ecommerce:send');
});
}
function vpv(page){ //virtual page view
track_ga('send', 'pageview', {
'page': page,
'title': document.title,
});
}
function track_ga() {
website_ga = this._gaw || function(){};
website_ga.apply(this, arguments);
}
});
+8 -3
View File
@@ -344,6 +344,7 @@
<template id="product" name="Product">
<t t-call="website.layout">
<script type="text/javascript" src="/website_sale/static/src/js/website_sale_tracking.js"></script>
<t t-set="additional_title" t-value="product.name"/>
<div itemscope="itemscope" itemtype="http://schema.org/Product" id="wrap" class="js_sale">
@@ -371,7 +372,7 @@
</div>
</section>
<section class="container oe_website_sale" id="product_detail">
<section t-attf-class="container oe_website_sale #{(compute_currency(product.lst_price) - product.price) &gt; 0.1 and 'discount'}" id="product_detail">
<div class="row">
<div class="col-sm-7 col-md-7 col-lg-7">
<span itemprop="image" t-field="product.image" t-field-options='{"widget": "image", "class": "product_detail_img"}'/>
@@ -435,13 +436,13 @@
<template id="product_price">
<div itemprop="offers" itemscope="itemscope" itemtype="http://schema.org/Offer" class="product_price mt16">
<h4 class="oe_price_h4 css_editable_mode_hidden">
<span class="text-danger oe_default_price" t-att-style="'' if (compute_currency(product.lst_price) - product.price) &gt; 0.1 else 'display: none;'" style="text-decoration: line-through; white-space: nowrap;"
<span class="text-danger oe_default_price" style="text-decoration: line-through; white-space: nowrap;"
t-field="product.lst_price"
t-field-options='{
"widget": "monetary",
"from_currency": "website.currency_id",
"display_currency": "user_id.partner_id.property_product_pricelist.currency_id"
}'/><br/>
}'/>
<b class="oe_price" style="white-space: nowrap;"
t-field="product.price"
t-field-options='{
@@ -649,6 +650,7 @@
<template id="cart" name="Shopping Cart">
<t t-call="website.layout">
<script type="text/javascript" src="/website_sale/static/src/js/website_sale_tracking.js"></script>
<div id="wrap">
<div class="container oe_website_sale">
@@ -836,6 +838,7 @@
<template id="checkout">
<t t-call="website.layout">
<script type="text/javascript" src="/website_sale/static/src/js/website_sale_tracking.js"></script>
<t t-set="additional_title">Shop - Checkout</t>
<div id="wrap">
<div class="container oe_website_sale">
@@ -998,6 +1001,7 @@
<template id="payment">
<t t-call="website.layout">
<script type="text/javascript" src="/website_sale/static/src/js/website_sale_tracking.js"></script>
<t t-set="additional_title">Shop - Select Payment Mode</t>
<div id="wrap">
<div class="container oe_website_sale">
@@ -1116,6 +1120,7 @@
<template id="confirmation">
<t t-call="website.layout">
<script type="text/javascript" src="/website_sale/static/src/js/website_sale_tracking.js"></script>
<t t-set="additional_title">Shop - Confirmed</t>
<div id="wrap">
<div class="container oe_website_sale">
+10
View File
@@ -45,6 +45,16 @@
</field>
</field>
</record>
<record id="variants_tree_view" model="ir.ui.view">
<field name="name">variants.template.tree</field>
<field name="model">product.attribute.value</field>
<field name="inherit_id" ref="product.variants_tree_view"/>
<field name="arch" type="xml">
<field name="name" position="after">
<field name="color"/>
</field>
</field>
</record>
<!-- Product Public Categories -->
<record id="product_public_category_form_view" model="ir.ui.view">
+11 -1
View File
@@ -145,7 +145,7 @@ class ir_model(osv.osv):
if result and result[0] == 'v':
cr.execute('DROP view %s' % (model_pool._table,))
elif result and result[0] == 'r':
cr.execute('DROP TABLE %s' % (model_pool._table,))
cr.execute('DROP TABLE %s CASCADE' % (model_pool._table,))
return True
def unlink(self, cr, user, ids, context=None):
@@ -200,6 +200,8 @@ class ir_model(osv.osv):
def instanciate(self, cr, user, model, context=None):
class x_custom_model(osv.osv):
_custom = True
if isinstance(model, unicode):
model = model.encode('utf-8')
x_custom_model._name = model
x_custom_model._module = False
a = x_custom_model._build_model(self.pool, cr)
@@ -307,6 +309,14 @@ class ir_model_fields(osv.osv):
if column_name and (result and result[0] == 'r'):
cr.execute('ALTER table "%s" DROP column "%s" cascade' % (model._table, field.name))
model._columns.pop(field.name, None)
# remove m2m relation table for custom fields
# we consider the m2m relation is only one way as it's not possible
# to specify the relation table in the interface for custom fields
# TODO master: maybe use ir.model.relations for custom fields
if field.state == 'manual' and field.ttype == 'many2many':
rel_name = self.pool[field.model]._all_columns[field.name].column._rel
cr.execute('DROP table "%s"' % (rel_name))
return True
def unlink(self, cr, user, ids, context=None):
+3 -3
View File
@@ -664,7 +664,7 @@ class DateTimeConverter(osv.AbstractModel):
if options and options.get('hide_seconds'):
pattern = pattern.replace(":ss", "").replace(":s", "")
return babel.dates.format_datetime(value, format=pattern, locale=locale)
class TextConverter(osv.AbstractModel):
@@ -779,7 +779,7 @@ class MonetaryConverter(osv.AbstractModel):
lang_code = context.get('lang') or 'en_US'
lang = self.pool['res.lang']
formatted_amount = lang.format(cr, uid, [lang_code],
formatted_amount = lang.format(cr, uid, [lang_code],
fmt, Currency.round(cr, uid, display_currency, from_amount),
grouping=True, monetary=True)
@@ -879,7 +879,7 @@ class Contact(orm.AbstractModel):
id = getattr(record, field_name).id
field_browse = self.pool[column._obj].browse(cr, openerp.SUPERUSER_ID, id, context={"show_address": True})
value = field_browse.display_name
value = field_browse.name_get()[0][1]
val = {
'name': value.split("\n")[0],
+7 -2
View File
@@ -177,8 +177,13 @@ class module(osv.osv):
element.set('src', "/%s/static/description/%s" % (module.name, element.get('src')))
res[module.id] = lxml.html.tostring(html)
else:
overrides = dict(embed_stylesheet=False, doctitle_xform=False, output_encoding='unicode')
output = publish_string(source=module.description, settings_overrides=overrides, writer=MyWriter())
overrides = {
'embed_stylesheet': False,
'doctitle_xform': False,
'output_encoding': 'unicode',
'xml_declaration': False,
}
output = publish_string(source=module.description or '', settings_overrides=overrides, writer=MyWriter())
res[module.id] = output
return res
+2 -2
View File
@@ -756,7 +756,7 @@ class Environment(object):
"""
if not spec:
return
for env in list(self.all):
for env in list(iter(self.all)):
c = env.cache
for field, ids in spec:
if ids is None:
@@ -769,7 +769,7 @@ class Environment(object):
def invalidate_all(self):
""" Clear the cache of all environments. """
for env in list(self.all):
for env in list(iter(self.all)):
env.cache.clear()
env.prefetch.clear()
env.computed.clear()
+20 -6
View File
@@ -366,9 +366,17 @@ class Field(object):
else:
self._setup_regular(env)
# put invalidation/recomputation triggers on dependencies
# put invalidation/recomputation triggers on field dependencies
model = env[self.model_name]
for path in self.depends:
self._setup_dependency([], env[self.model_name], path.split('.'))
self._setup_dependency([], model, path.split('.'))
# put invalidation triggers on model dependencies
for dep_model_name, field_names in model._depends.iteritems():
dep_model = env[dep_model_name]
for field_name in field_names:
field = dep_model._fields[field_name]
field._triggers.add((self, None))
#
# Setup of related fields
@@ -800,7 +808,7 @@ class Field(object):
# invalidate the fields that depend on self, and prepare recomputation
spec = [(self, records._ids)]
for field, path in self._triggers:
if field.store:
if path and field.store:
# don't move this line to function top, see log
env = records.env(user=SUPERUSER_ID, context={'active_test': False})
target = env[field.model_name].search([(path, 'in', records.ids)])
@@ -824,10 +832,13 @@ class Field(object):
computed = target.browse(env.computed[field])
if path == 'id':
target = records - computed
elif path:
target = (target.browse(env.cache[field]) - computed).filtered(
lambda rec: rec._mapped_cache(path) & records
)
else:
for record in target.browse(env.cache[field]) - computed:
if record._mapped_cache(path) & records:
target += record
target = target.browse(env.cache[field]) - computed
if target:
spec.append((field, target._ids))
@@ -1542,6 +1553,9 @@ class Id(Field):
store = True
readonly = True
def __init__(self, string=None, **kwargs):
super(Id, self).__init__(type='integer', string=string, **kwargs)
def to_column(self):
return fields.integer('ID')
+5 -2
View File
@@ -1145,11 +1145,14 @@ class Root(object):
"""Root WSGI application for the OpenERP Web Client.
"""
def __init__(self):
self._loaded = False
@lazy_property
def session_store(self):
# Setup http sessions
path = openerp.tools.config.session_dir
_logger.debug('HTTP sessions stored in: %s', path)
self.session_store = werkzeug.contrib.sessions.FilesystemSessionStore(path, session_class=OpenERPSession)
self._loaded = False
return werkzeug.contrib.sessions.FilesystemSessionStore(path, session_class=OpenERPSession)
@lazy_property
def nodb_routing_map(self):
+98 -81
View File
@@ -326,6 +326,10 @@ class BaseModel(object):
_log_create = False
_sql_constraints = []
# model dependencies, for models backed up by sql views:
# {model_name: field_names, ...}
_depends = {}
CONCURRENCY_CHECK_FIELD = '__last_update'
def log(self, cr, uid, id, message, secondary=False, context=None):
@@ -585,6 +589,10 @@ class BaseModel(object):
inherits = dict(parent_class._inherits)
inherits.update(cls._inherits)
depends = dict(parent_class._depends)
for m, fs in cls._depends.iteritems():
depends.setdefault(m, []).extend(fs)
old_constraints = parent_class._constraints
new_constraints = cls._constraints
# filter out from old_constraints the ones overridden by a
@@ -604,6 +612,7 @@ class BaseModel(object):
'_columns': columns,
'_defaults': defaults,
'_inherits': inherits,
'_depends': depends,
'_constraints': constraints,
'_sql_constraints': sql_constraints,
}
@@ -617,6 +626,7 @@ class BaseModel(object):
'_columns': dict(cls._columns),
'_defaults': dict(cls._defaults),
'_inherits': dict(cls._inherits),
'_depends': dict(cls._depends),
'_constraints': list(cls._constraints),
'_sql_constraints': list(cls._sql_constraints),
'_original_module': original_module,
@@ -629,76 +639,8 @@ class BaseModel(object):
if col._type == 'float':
cls._columns[key] = copy.copy(col)
# link the class to the registry, and update the registry
cls.pool = pool
# Note: we have to insert an instance into the registry now, because it
# can trigger some stuff on other models which expect this new instance
# (like method _inherits_reload_src())
# instantiate the model, and initialize it
model = object.__new__(cls)
cls._model = model # backward compatibility
pool.add(name, model)
# determine description, table, sequence and log_access
if not cls._description:
cls._description = cls._name
if not cls._table:
cls._table = cls._name.replace('.', '_')
if not cls._sequence:
cls._sequence = cls._table + '_id_seq'
if not hasattr(cls, '_log_access'):
# If _log_access is not specified, it is the same value as _auto.
cls._log_access = cls._auto
# Transience
if cls.is_transient():
cls._transient_check_count = 0
cls._transient_max_count = config.get('osv_memory_count_limit')
cls._transient_max_hours = config.get('osv_memory_age_limit')
assert cls._log_access, \
"TransientModels must have log_access turned on, " \
"in order to implement their access rights policy"
# retrieve new-style fields and duplicate them (to avoid clashes with
# inheritance between different models)
cls._fields = {}
for attr, field in getmembers(cls, Field.__instancecheck__):
if not field._origin:
cls._add_field(attr, field.copy())
# introduce magic fields
cls._add_magic_fields()
# register stuff about low-level function fields and custom fields
cls._init_function_fields(pool, cr)
cls._init_manual_fields(pool, cr)
# process _inherits
cls._inherits_check()
cls._inherits_reload()
# register constraints and onchange methods
cls._init_constraints_onchanges()
# check defaults
for k in cls._defaults:
assert k in cls._fields, \
"Model %s has a default for nonexiting field %s" % (cls._name, k)
# restart columns
for column in cls._columns.itervalues():
column.restart()
# validate rec_name
if cls._rec_name:
assert cls._rec_name in cls._fields, \
"Invalid rec_name %s for model %s" % (cls._rec_name, cls._name)
elif 'name' in cls._fields:
cls._rec_name = 'name'
# prepare ormcache, which must be shared by all instances of the model
cls._ormcache = {}
# complete the initialization of model
model.__init__(pool, cr)
return model
@@ -818,8 +760,81 @@ class BaseModel(object):
return None
def __init__(self, pool, cr):
# this method no longer does anything; kept for backward compatibility
pass
""" Initialize a model and make it part of the given registry.
- copy the stored fields' functions in the registry,
- retrieve custom fields and add them in the model,
- ensure there is a many2one for each _inherits'd parent,
- update the children's _columns,
- give a chance to each field to initialize itself.
"""
cls = type(self)
# link the class to the registry, and update the registry
cls.pool = pool
cls._model = self # backward compatibility
pool.add(cls._name, self)
# determine description, table, sequence and log_access
if not cls._description:
cls._description = cls._name
if not cls._table:
cls._table = cls._name.replace('.', '_')
if not cls._sequence:
cls._sequence = cls._table + '_id_seq'
if not hasattr(cls, '_log_access'):
# If _log_access is not specified, it is the same value as _auto.
cls._log_access = cls._auto
# Transience
if cls.is_transient():
cls._transient_check_count = 0
cls._transient_max_count = config.get('osv_memory_count_limit')
cls._transient_max_hours = config.get('osv_memory_age_limit')
assert cls._log_access, \
"TransientModels must have log_access turned on, " \
"in order to implement their access rights policy"
# retrieve new-style fields and duplicate them (to avoid clashes with
# inheritance between different models)
cls._fields = {}
for attr, field in getmembers(cls, Field.__instancecheck__):
if not field._origin:
cls._add_field(attr, field.copy())
# introduce magic fields
cls._add_magic_fields()
# register stuff about low-level function fields and custom fields
cls._init_function_fields(pool, cr)
cls._init_manual_fields(pool, cr)
# process _inherits
cls._inherits_check()
cls._inherits_reload()
# register constraints and onchange methods
cls._init_constraints_onchanges()
# check defaults
for k in cls._defaults:
assert k in cls._fields, \
"Model %s has a default for nonexiting field %s" % (cls._name, k)
# restart columns
for column in cls._columns.itervalues():
column.restart()
# validate rec_name
if cls._rec_name:
assert cls._rec_name in cls._fields, \
"Invalid rec_name %s for model %s" % (cls._rec_name, cls._name)
elif 'name' in cls._fields:
cls._rec_name = 'name'
# prepare ormcache, which must be shared by all instances of the model
cls._ormcache = {}
def __export_xml_id(self):
""" Return a valid xml_id for the record `self`. """
@@ -1640,7 +1655,7 @@ class BaseModel(object):
record.display_name = convert(record[name])
else:
for record in self:
record.display_name = "%s,%s" % (self._name, self.id)
record.display_name = "%s,%s" % (record._name, record.id)
def _inverse_display_name(self):
name = self._rec_name
@@ -2760,7 +2775,10 @@ class BaseModel(object):
def _m2m_raise_or_create_relation(self, cr, f):
m2m_tbl, col1, col2 = f._sql_names(self)
self._save_relation_table(cr, m2m_tbl)
# do not create relations for custom fields as they do not belong to a module
# they will be automatically removed when dropping the corresponding ir.model.field
if not f.string.startswith('x_'):
self._save_relation_table(cr, m2m_tbl)
cr.execute("SELECT relname FROM pg_class WHERE relkind IN ('r','v') AND relname=%s", (m2m_tbl,))
if not cr.dictfetchall():
if f._obj not in self.pool:
@@ -3013,7 +3031,7 @@ class BaseModel(object):
if not fields:
fields = filter(valid, self._fields)
else:
invalid_fields = list(set(filter(lambda name: not valid(name), fields)))
invalid_fields = set(filter(lambda name: not valid(name), fields))
if invalid_fields:
_logger.warning('Access Denied by ACLs for operation: %s, uid: %s, model: %s, fields: %s',
operation, user, self._name, ', '.join(invalid_fields))
@@ -3281,7 +3299,7 @@ class BaseModel(object):
self._cr.execute(query, (self._name, tuple(self.ids)))
res = self._cr.dictfetchall()
uids = list(set(r[k] for r in res for k in ['write_uid', 'create_uid'] if r.get(k)))
uids = set(r[k] for r in res for k in ['write_uid', 'create_uid'] if r.get(k))
names = dict(self.env['res.users'].browse(uids).name_get())
for r in res:
@@ -3504,7 +3522,7 @@ class BaseModel(object):
for order, obj_name, store_ids, fields in result_store:
if obj_name == self._name:
effective_store_ids = list(set(store_ids) - set(ids))
effective_store_ids = set(store_ids) - set(ids)
else:
effective_store_ids = store_ids
if effective_store_ids:
@@ -5402,7 +5420,7 @@ class BaseModel(object):
""" If `field` must be recomputed on some record in `self`, return the
corresponding records that must be recomputed.
"""
for env in [self.env] + list(self.env.all):
for env in [self.env] + list(iter(self.env.all)):
if env.todo.get(field) and env.todo[field] & self:
return env.todo[field]
@@ -5424,7 +5442,7 @@ class BaseModel(object):
""" Recompute stored function fields. The fields and records to
recompute have been determined by method :meth:`modified`.
"""
for env in list(self.env.all):
for env in list(iter(self.env.all)):
while env.todo:
field, recs = next(env.todo.iteritems())
# evaluate the fields to recompute, and save them to database
@@ -5642,7 +5660,7 @@ class RecordCache(MutableMapping):
if args and isinstance(args[0], SpecialValue):
values = dict.fromkeys(self._recs._ids, args[0])
for name, field in self._recs._fields.iteritems():
if name not in MAGIC_COLUMNS:
if name != 'id':
self._recs.env.cache[field].update(values)
else:
return super(RecordCache, self).update(*args, **kwargs)
@@ -5660,8 +5678,7 @@ class RecordCache(MutableMapping):
cache, id = self._recs.env.cache, self._recs.id
dummy = SpecialValue(None)
for name, field in self._recs._fields.iteritems():
if name not in MAGIC_COLUMNS and \
not isinstance(cache[field].get(id, dummy), SpecialValue):
if name != 'id' and not isinstance(cache[field].get(id, dummy), SpecialValue):
yield name
def __len__(self):
+5 -1
View File
@@ -43,7 +43,7 @@ MANIFEST = '__openerp__.py'
_logger = logging.getLogger(__name__)
# addons path as a list
ad_paths = [tools.config.addons_data_dir]
ad_paths = []
hooked = False
# Modules already loaded
@@ -89,6 +89,10 @@ def initialize_sys_path():
global ad_paths
global hooked
dd = tools.config.addons_data_dir
if dd not in ad_paths:
ad_paths.append(dd)
for ad in tools.config['addons_path'].split(','):
ad = os.path.abspath(tools.ustr(ad.strip()))
if ad not in ad_paths:
+5 -2
View File
@@ -61,7 +61,10 @@ def check_ssl():
DEFAULT_LOG_HANDLER = [':INFO']
def _get_default_datadir():
return appdirs.user_data_dir(appname='OpenERP', appauthor=release.author)
home = os.path.expanduser('~')
func = appdirs.user_data_dir if os.path.exists(home) else appdirs.site_data_dir
# No "version" kwarg as session and filestore paths are shared against series
return func(appname='Odoo', appauthor=release.author)
class configmanager(object):
def __init__(self, fname=None):
@@ -649,7 +652,7 @@ class configmanager(object):
@property
def session_dir(self):
d = os.path.join(self['data_dir'], 'sessions', release.series)
d = os.path.join(self['data_dir'], 'sessions')
if not os.path.exists(d):
os.makedirs(d, 0700)
else: