[MERGE] forward port of latest saas-2 until rev 9051 dle@openerp.com-20131217142126-1lbim47d2m2x4bb0

bzr revid: mat@openerp.com-20131218155715-khb909yy99cbmna8
This commit is contained in:
Martin Trigaux 2013-12-18 16:57:15 +01:00
commit 54be818a3b
32 changed files with 161 additions and 49 deletions

View File

@ -3,9 +3,15 @@
<data noupdate="1">
<record id="analytic_journal_sale" model="account.analytic.journal">
<field name="code">SAL</field>
<field name="name">Sales</field>
<field name="type">sale</field>
</record>
<record id="exp" model="account.analytic.journal">
<field name="code">PUR</field>
<field name="name">Purchases</field>
<field name="type">purchase</field>
</record>
<!--
Payment term

View File

@ -6,11 +6,6 @@
<field name="name">Sales</field>
<field name="type">sale</field>
</record>
<record id="exp" model="account.analytic.journal">
<field name="code">PUR</field>
<field name="name">Purchases</field>
<field name="type">purchase</field>
</record>
<record id="sit" model="account.analytic.journal">
<field name="code">START</field>
<field name="name">Miscellaneous Operation</field>

View File

@ -450,6 +450,7 @@ class account_analytic_account(osv.osv):
'is_overdue_quantity' : fields.function(_is_overdue_quantity, method=True, type='boolean', string='Overdue Quantity',
store={
'account.analytic.line' : (_get_analytic_account, None, 20),
'account.analytic.account': (lambda self, cr, uid, ids, c=None: ids, ['quantity_max'], 10),
}),
'ca_invoiced': fields.function(_ca_invoiced_calc, type='float', string='Invoiced Amount',
help="Total customer invoiced amount for this account.",

View File

@ -23,6 +23,7 @@ from datetime import datetime, timedelta
import time
import logging
import openerp
from openerp import SUPERUSER_ID
from openerp.osv import fields, osv
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
@ -222,6 +223,7 @@ class base_action_rule(osv.osv):
def create(self, cr, uid, vals, context=None):
res_id = super(base_action_rule, self).create(cr, uid, vals, context=context)
self._register_hook(cr, [res_id])
openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname)
return res_id
def write(self, cr, uid, ids, vals, context=None):
@ -229,6 +231,7 @@ class base_action_rule(osv.osv):
ids = [ids]
super(base_action_rule, self).write(cr, uid, ids, vals, context=context)
self._register_hook(cr, ids)
openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname)
return True
def onchange_model_id(self, cr, uid, ids, model_id, context=None):

View File

@ -411,7 +411,7 @@
on_change="on_change_partner_id(partner_id)"
string="Customer"
context="{'default_name': partner_name, 'default_email': email_from, 'default_phone': phone}"/>
<field name="email_from" string="Email"/>
<field name="email_from" string="Email" widget="email"/>
<field name="phone"/>
</group>

View File

@ -32,6 +32,7 @@ import psycopg2
import openerp
from openerp import tools
from openerp import SUPERUSER_ID
from openerp.osv import fields, osv
from openerp.osv.orm import except_orm
import openerp.report.interface
@ -322,7 +323,7 @@ class document_directory(osv.osv):
ressource_parent_type_id=vals.get('ressource_parent_type_id',False)
ressource_id=vals.get('ressource_id',0)
if op=='write':
for directory in self.browse(cr, uid, ids):
for directory in self.browse(cr, SUPERUSER_ID, ids):
if not name:
name=directory.name
if not parent_id:
@ -336,7 +337,7 @@ class document_directory(osv.osv):
if len(res):
return False
if op=='create':
res=self.search(cr,uid,[('name','=',name),('parent_id','=',parent_id),('ressource_parent_type_id','=',ressource_parent_type_id),('ressource_id','=',ressource_id)])
res = self.search(cr, SUPERUSER_ID, [('name','=',name),('parent_id','=',parent_id),('ressource_parent_type_id','=',ressource_parent_type_id),('ressource_id','=',ressource_id)])
if len(res):
return False
return True

View File

@ -58,6 +58,23 @@
!python {model: ir.attachment}: |
ids = self.search(cr, uid, [('res_model', '=', 'res.country'), ('res_id', '=', ref("base.za"))])
assert ids == [ ref("attach_3rd")], ids
-
I test that I can't create duplicate directories (even when duplicates are hidden by a record rule)
-
!python {model: document.directory}: |
duplicate_detected = False
from openerp.osv.osv import except_osv
try:
demo_uid = ref('base.user_demo')
dir_vals = {
'name': 'Testing (will be deleted!)',
'parent_id': ref('document.dir_root')
}
new_dir_id = self.create(cr, demo_uid, dir_vals, context=None)
self.unlink(cr, uid, [new_dir_id], context=None)
except except_osv, e:
duplicate_detected = e.value == u'Directory name must be unique!'
assert duplicate_detected is True, 'Failed to detect duplicate directory'
-
I delete the attachments
-

View File

@ -57,9 +57,10 @@ class res_users(osv.Model):
various mailboxes, we do not have access to the current partner_id. """
if kwargs.get('type') == 'email':
return super(res_users, self).message_post(cr, uid, thread_id, context=context, **kwargs)
res = None
employee_ids = self._message_post_get_eid(cr, uid, thread_id, context=context)
if not employee_ids:
pass # dpo something
if not employee_ids: # no employee: fall back on previous behavior
return super(res_users, self).message_post(cr, uid, thread_id, context=context, **kwargs)
for employee_id in employee_ids:
res = self.pool.get('hr.employee').message_post(cr, uid, employee_id, context=context, **kwargs)
return res

View File

@ -242,6 +242,10 @@ class hr_holidays(osv.osv):
result['value'] = {
'employee_id': ids_employee[0]
}
elif holiday_type != 'employee':
result['value'] = {
'employee_id': False
}
return result
def onchange_employee(self, cr, uid, ids, employee_id):

View File

@ -745,6 +745,8 @@
<field name="property_account_receivable" ref="pcg_3488"/>
<field name="property_account_payable" ref="pcg_4488"/>
<field name="currency_id" ref="base.MAD"/>
<field name="property_account_income_categ" ref="pcg_7111"/>
<field name="property_account_expense_categ" ref="pcg_1486"/>
</record>
<record model="account.tax.template" id="tva_exo">

View File

@ -119,3 +119,5 @@
"51100_general_product",51100,"Freight and Shipping Costs","other","l10n_us.user_type_cogs","cost_of_goods_sold","False","l10n_us.account_chart_template_general_product"
"52500_general_product",52500,"Purchase Discounts","other","l10n_us.user_type_cogs","cost_of_goods_sold","False","l10n_us.account_chart_template_general_product"
"52900_general_product",52900,"Purchases - Resale Items","other","l10n_us.user_type_cogs","cost_of_goods_sold","False","l10n_us.account_chart_template_general_product"
"base_miscincome","49000","Miscellaneous Income","other","l10n_us.user_type_income","income","False","l10n_us.account_chart_template_basic"
"base_miscexpense","69000","Miscellaneous Expense","other","l10n_us.user_type_expense","expense","False","l10n_us.account_chart_template_basic"
1 id code name type user_type:id parent_id:id reconcile chart_template_id:id
119 51100_general_product 51100 Freight and Shipping Costs other l10n_us.user_type_cogs cost_of_goods_sold False l10n_us.account_chart_template_general_product
120 52500_general_product 52500 Purchase Discounts other l10n_us.user_type_cogs cost_of_goods_sold False l10n_us.account_chart_template_general_product
121 52900_general_product 52900 Purchases - Resale Items other l10n_us.user_type_cogs cost_of_goods_sold False l10n_us.account_chart_template_general_product
122 base_miscincome 49000 Miscellaneous Income other l10n_us.user_type_income income False l10n_us.account_chart_template_basic
123 base_miscexpense 69000 Miscellaneous Expense other l10n_us.user_type_expense expense False l10n_us.account_chart_template_basic

View File

@ -9,6 +9,8 @@
<field name="property_account_receivable" ref="account_receivable"/>
<field name="property_account_payable" ref="account_payable"/>
<field name="currency_id" ref="base.USD"/>
<field name="property_account_income_categ" ref="base_miscincome"/>
<field name="property_account_expense_categ" ref="base_miscexpense"/>
</record>
<record id="account_chart_template_advertising" model="account.chart.template">
<field name="bank_account_view_id" ref="cash_expenditure"/>

View File

@ -81,16 +81,19 @@ Main Features
'css': [
'static/src/css/mail.css',
'static/src/css/mail_group.css',
'static/src/css/announcement.css',
],
'js': [
'static/src/js/mail.js',
'static/src/js/mail_followers.js',
'static/src/js/many2many_tags_email.js',
'static/src/js/announcement.js',
'static/src/js/suggestions.js',
],
'qweb': [
'static/src/xml/mail.xml',
'static/src/xml/mail_followers.xml',
'static/src/xml/announcement.xml',
'static/src/xml/suggestions.xml',
],
}

View File

@ -0,0 +1,3 @@
.openerp .annoucement_bar {
display: none;
}

View File

@ -0,0 +1,42 @@
openerp_announcement = function(instance) {
instance.web.WebClient.include({
show_application: function() {
return $.when(this._super.apply(this, arguments)).then(this.proxy('show_annoucement_bar'));
},
_ab_location: function(dbuuid) {
return _.str.sprintf('https://services.openerp.com/openerp-enterprise/ab/css/%s.css', dbuuid);
},
show_annoucement_bar: function() {
if (this.session.get_cookie('ab') === 'c') {
return;
}
var self = this;
var config_parameter = new instance.web.Model('ir.config_parameter');
var $bar = this.$el.find('.announcement_bar');
return config_parameter.call('get_param', ['database.uuid', false]).then(function(dbuuid) {
if (!dbuuid) {
return;
}
var $link = $bar.find('.url a');
$link.attr('href', _.str.sprintf('%s/%s', $link.attr('href'), dbuuid));
var $css = $('<link />').attr({
rel : 'stylesheet',
type: 'text/css',
media: 'screen',
href: self._ab_location(dbuuid)
});
$css.on('load', function() {
var close = function() {
var ttl = 7*24*60*60;
self.session.set_cookie('ab', 'c', ttl);
$bar.slideUp('slow');
};
$bar.find('.close').on('click', close);
self.trigger('ab_loaded', $bar);
});
$('head').append($css);
});
}
});
};

View File

@ -6,6 +6,7 @@ openerp.mail = function (session) {
openerp_mail_followers(session, mail); // import mail_followers.js
openerp_FieldMany2ManyTagsEmail(session); // import manyy2many_tags_email.js
openerp_announcement(session);
/**
* ------------------------------------------------------------

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-extend="WebClient">
<t t-jquery="table.oe_webclient" t-operation="prepend">
<td colspan="2" class="announcement_bar">
<span class="message"></span>
<span class="url"><a href="https://services.openerp.com/openerp-enterprise/ab/register" target="_blank"></a></span>
<span class="close"></span>
</td>
</t>
</t>
</templates>

View File

@ -38,9 +38,9 @@ professional emails and reuse templates in a few clicks.
],
'data': [
'mail_data.xml',
'mass_mailing_view.xml',
'wizard/mail_compose_message_view.xml',
'wizard/mail_mass_mailing_create_segment.xml',
'mass_mailing_view.xml',
'security/ir.model.access.csv',
],
'js': [

View File

@ -252,6 +252,9 @@
<t t-if="widget.view.is_action_enabled('edit')">
<li><a type="edit">Settings</a></li>
</t>
<t t-if="widget.view.is_action_enabled('edit')">
<li><a name="%(action_mail_mass_mailing_create)d" type="action">New Wave</a></li>
</t>
<t t-if="widget.view.is_action_enabled('delete')">
<li><a type="delete">Delete</a></li>
</t>

View File

@ -36,7 +36,7 @@ class MailMassMailingCreate(osv.TransientModel):
required=True,
),
'model_id': fields.many2one(
'ir.model', 'Document',
'ir.model', 'Document Type',
required=True,
help='Document on which the mass mailing will run. This must be a '
'valid OpenERP model.',
@ -116,6 +116,7 @@ class MailMassMailingCreate(osv.TransientModel):
'default_template_id': wizard.template_id.id,
'default_use_mass_mailing_campaign': True,
'default_use_active_domain': True,
'default_model': wizard.model_id.model,
'default_active_domain': wizard.domain,
'default_mass_mailing_campaign_id': wizard.mass_mailing_campaign_id.id,
'default_mass_mailing_id': wizard.mass_mailing_id.id,

View File

@ -42,7 +42,7 @@
</p>
</div>
<label for="model_id"/>
<label for="template_id"/>
<div>
<field name="template_id"/>
<p class="oe_grey"
@ -55,8 +55,7 @@
<label for="name"/>
<div>
<field name="name"/>
<p class="oe_grey"
attrs="{'invisible': [('name', '!=', False)]}">
<p class="oe_grey">
Please choose the name of the mailing.
</p>
</div>

View File

@ -70,6 +70,8 @@ class report_custom(report_rml):
main_strd_price = str(std_price) + '\r\n'
sum_strd = prod_qtty*std_price
for seller_id in prod.seller_ids:
if seller_id.name.id == prod.seller_id.id:
continue
sellers += '- <i>'+ to_xml(seller_id.name.name) +'</i>\r\n'
pricelist = seller_id.name.property_product_pricelist_purchase
price = pricelist_pool.price_get(cr,uid,[pricelist.id],

View File

@ -714,13 +714,14 @@ class pos_order(osv.osv):
}, context=context)
self.write(cr, uid, [order.id], {'picking_id': picking_id}, context=context)
location_id = order.warehouse_id.lot_stock_id.id
output_id = order.warehouse_id.lot_output_id.id
if order.partner_id:
destination_id = order.partner_id.property_stock_customer.id
else:
destination_id = partner_obj.default_get(cr, uid, ['property_stock_customer'], context=context)['property_stock_customer']
for line in order.lines:
if line.product_id and line.product_id.type == 'service':
continue
if line.qty < 0:
location_id, output_id = output_id, location_id
move_obj.create(cr, uid, {
'name': line.name,
@ -732,11 +733,9 @@ class pos_order(osv.osv):
'product_qty': abs(line.qty),
'tracking_id': False,
'state': 'draft',
'location_id': location_id,
'location_dest_id': output_id,
'location_id': location_id if line.qty >= 0 else destination_id,
'location_dest_id': destination_id if line.qty >= 0 else location_id,
}, context=context)
if line.qty < 0:
location_id, output_id = output_id, location_id
picking_obj.signal_button_confirm(cr, uid, [picking_id])
picking_obj.force_assign(cr, uid, [picking_id], context)

View File

@ -560,6 +560,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
this.handler = function(e){
if(e.which === 13){ //ignore returns
e.preventDefault();
return;
}

View File

@ -46,12 +46,15 @@
Process Transition
-->
<!-- This "foreign" process node is duplicated here from the corresponding sale_stock node because
<!-- This process node is duplicated here from the corresponding sale_stock node because
`project_mrp` implements a basic procurement system for services without actually using the
full-fledged procurement process from sale_stock, and without the dependency. So it stil
represents a "procurement system".
full-fledged procurement process from sale_stock, and without the dependency. So it still
represents a "procurement system". Sharing the external ID causes other problems, so
we duplicate it instead.
TODO: To cleanup this duplicate node, it should probably be moved to the
`sale` module directly, and removed from both `sale_stock` and `project_mrp`.
-->
<record id="procurement.process_node_saleprocurement0" model="process.node">
<record id="process_node_saleprocurement0" model="process.node">
<field name="menu_id" ref="procurement.menu_stock_procurement_action"/>
<field name="model_id" ref="procurement.model_procurement_order"/>
<field name="kind">subflow</field>
@ -66,7 +69,7 @@
<field eval="&quot;&quot;&quot;Procurement Task&quot;&quot;&quot;" name="name"/>
<field eval="&quot;&quot;&quot;if product type is 'service' then it creates the task.&quot;&quot;&quot;" name="note"/>
<field name="target_node_id" ref="process_node_procuretasktask0"/>
<field name="source_node_id" ref="procurement.process_node_saleprocurement0"/>
<field name="source_node_id" ref="process_node_saleprocurement0"/>
</record>
<record id="process_transition_createtask0" model="process.transition">

View File

@ -140,6 +140,6 @@ class stock_picking_in(osv.osv):
_columns = {
'purchase_id': fields.many2one('purchase.order', 'Purchase Order',
ondelete='set null', select=True),
'warehouse_id': fields.related('purchase_id', 'warehouse_id', type='many2one', relation='stock.warehouse', string='Destination Warehouse'),
'warehouse_id': fields.related('purchase_id', 'warehouse_id', type='many2one', relation='stock.warehouse', string='Destination Warehouse', readonly=True),
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -997,9 +997,9 @@ class mail_compose_message(osv.Model):
def send_mail(self, cr, uid, ids, context=None):
context = context or {}
if context.get('active_model') == 'sale.order' and context.get('active_ids') and context.get('mark_so_as_sent'):
if context.get('default_model') == 'sale.order' and context.get('default_res_id') and context.get('mark_so_as_sent'):
context = dict(context, mail_post_autofollow=True)
self.pool.get('sale.order').signal_quotation_sent(cr, uid, context['active_ids'])
self.pool.get('sale.order').signal_quotation_sent(cr, uid, [context['default_res_id']])
return super(mail_compose_message, self).send_mail(cr, uid, ids, context=context)

View File

@ -26,6 +26,18 @@ from dateutil import relativedelta
from openerp import tools
from openerp.osv import osv, fields
class res_users(osv.Model):
_inherit = 'res.users'
_columns = {
'default_section_id': fields.many2one('crm.case.section', 'Default Sales Team'),
}
def __init__(self, pool, cr):
init_res = super(res_users, self).__init__(pool, cr)
# duplicate list to avoid modifying the original reference
self.SELF_WRITEABLE_FIELDS = list(self.SELF_WRITEABLE_FIELDS)
self.SELF_WRITEABLE_FIELDS.extend(['default_section_id'])
return init_res
class sale_order(osv.osv):
_inherit = 'sale.order'
@ -35,6 +47,17 @@ class sale_order(osv.osv):
domain="['|',('section_id','=',section_id),('section_id','=',False), ('object_id.model', '=', 'crm.lead')]", context="{'object_name': 'crm.lead'}")
}
def _get_default_section_id(self, cr, uid, context=None):
""" Gives default section by checking if present in the context """
section_id = self.pool.get('crm.lead')._resolve_section_id_from_context(cr, uid, context=context) or False
if not section_id:
section_id = self.pool.get('res.users').browse(cr, uid, uid, context).default_section_id.id or False
return section_id
_defaults = {
'section_id': lambda s, cr, uid, c: s._get_default_section_id(cr, uid, c),
}
def _prepare_invoice(self, cr, uid, order, lines, context=None):
invoice_vals = super(sale_order, self)._prepare_invoice(cr, uid, order, lines, context=context)
if order.section_id and order.section_id.id:
@ -92,21 +115,6 @@ class crm_case_section(osv.osv):
def action_forecast(self, cr, uid, id, value, context=None):
return self.write(cr, uid, [id], {'invoiced_forecast': round(float(value))}, context=context)
class res_users(osv.Model):
_inherit = 'res.users'
_columns = {
'default_section_id': fields.many2one('crm.case.section', 'Default Sales Team'),
}
def __init__(self, pool, cr):
init_res = super(res_users, self).__init__(pool, cr)
# duplicate list to avoid modifying the original reference
self.SELF_WRITEABLE_FIELDS = list(self.SELF_WRITEABLE_FIELDS)
self.SELF_WRITEABLE_FIELDS.extend(['default_section_id'])
return init_res
class sale_crm_lead(osv.Model):
_inherit = 'crm.lead'

View File

@ -2106,7 +2106,7 @@ class stock_move(osv.osv):
})
new_moves.append(self.browse(cr, uid, [new_id])[0])
if pickid:
self.signal_button_confirm(cr, uid, [pickid])
self.pool.get('stock.picking').signal_button_confirm(cr, uid, [pickid])
if new_moves:
new_moves += self.create_chained_picking(cr, uid, new_moves, context)
return new_moves

View File

@ -1044,7 +1044,7 @@
<button name="action_process" states="assigned" string="Receive" type="object" class="oe_highlight"/>
</xpath>
<xpath expr="//field[@name='partner_id']" position="replace">
<field name="partner_id" on_change="onchange_partner_in(partner_id)" string="Supplier" domain="[('supplier','=',True)]" />
<field name="partner_id" on_change="onchange_partner_in(partner_id)" string="Supplier" domain="[('supplier','=',True)]" context="{'default_supplier':1,'default_customer':0}"/>
</xpath>
<xpath expr="//field[@name='move_lines']" position="replace">
<field name="move_lines" context="{'address_in_id': partner_id, 'picking_type': 'in', 'form_view_ref':'view_move_picking_form', 'tree_view_ref':'view_move_picking_tree'}" options='{"reload_on_button": true}'/>

View File

@ -10,7 +10,7 @@ OpenERP Web LinkedIn module.
This module provides the Integration of the LinkedIn with OpenERP.
""",
'data': ['web_linkedin_view.xml'],
'depends' : ['crm'],
'depends' : ['web','crm'],
'js': ['static/src/js/*.js'],
'css': ['static/src/css/*.css'],
'qweb': ['static/src/xml/*.xml'],

View File

@ -24,6 +24,7 @@ import urllib2
from urlparse import urlparse, urlunparse
import openerp
import openerp.addons.web
from openerp.osv import fields, osv
class Binary(openerp.http.Controller):
@ -88,4 +89,4 @@ class web_linkedin_fields(osv.Model):
'linkedin_url': fields.char(string="LinkedIn url", size=100, store=True),
'linkedin_public_url': fields.function(_get_url, type='text', string="LinkedIn url",
help="This url is set automatically when you join the partner with a LinkedIn account."),
}
}