[MERGE] Forward-port of latest saas-2 (incl. 7.0) bugfixes, up to rev. 9127 odo@openerp.com-20140212122042-3m2tysmr31mtecnc

bzr revid: odo@openerp.com-20140212175141-i9yz8zlseglrk8sb
This commit is contained in:
Olivier Dony 2014-02-12 18:51:41 +01:00
commit bbd813e76e
25 changed files with 135 additions and 109 deletions

View File

@ -114,7 +114,7 @@ class account_invoice(osv.osv):
#we check if the invoice is partially reconciled and if there are other invoices
#involved in this partial reconciliation (and we sum these invoices)
for line in aml.reconcile_partial_id.line_partial_ids:
if line.invoice:
if line.invoice and invoice.type == line.invoice.type:
nb_inv_in_partial_rec += 1
#store the max invoice id as for this invoice we will make a balance instead of a simple division
max_invoice_id = max(max_invoice_id, line.invoice.id)

View File

@ -1453,7 +1453,7 @@
<act_window
id="act_account_move_to_account_move_line_open"
name="Journal Items"
context="{'search_default_journal_id': active_id, 'default_journal_id': active_id}"
context="{'search_default_move_id': active_id, 'default_move_id': active_id}"
res_model="account.move.line"
src_model="account.move"/>

View File

@ -664,13 +664,20 @@ class account_analytic_account(osv.osv):
partner_payment_term = contract.partner_id.property_payment_term and contract.partner_id.property_payment_term.id or False
currency_id = False
if contract.pricelist_id:
currency_id = contract.pricelist_id.currency_id.id
elif contract.partner_id.property_product_pricelist:
currency_id = contract.partner_id.property_product_pricelist.currency_id.id
elif contract.company_id:
currency_id = contract.company_id.currency_id.id
inv_data = {
'reference': contract.code or False,
'account_id': contract.partner_id.property_account_receivable.id,
'type': 'out_invoice',
'partner_id': contract.partner_id.id,
'currency_id': contract.partner_id.property_product_pricelist.id or False,
'currency_id': currency_id,
'journal_id': len(journal_ids) and journal_ids[0] or False,
'date_invoice': contract.recurring_next_date,
'origin': contract.name,

View File

@ -1366,6 +1366,7 @@ class account_voucher(osv.osv):
move_pool = self.pool.get('account.move')
move_line_pool = self.pool.get('account.move.line')
for voucher in self.browse(cr, uid, ids, context=context):
local_context = dict(context, force_company=voucher.journal_id.company_id.id)
if voucher.move_id:
continue
company_currency = self._get_company_currency(cr, uid, voucher.id, context)
@ -1380,7 +1381,7 @@ class account_voucher(osv.osv):
# Get the name of the account_move just created
name = move_pool.browse(cr, uid, move_id, context=context).name
# Create the first line of the voucher
move_line_id = move_line_pool.create(cr, uid, self.first_move_line_get(cr,uid,voucher.id, move_id, company_currency, current_currency, context), context)
move_line_id = move_line_pool.create(cr, uid, self.first_move_line_get(cr,uid,voucher.id, move_id, company_currency, current_currency, local_context), local_context)
move_line_brw = move_line_pool.browse(cr, uid, move_line_id, context=context)
line_total = move_line_brw.debit - move_line_brw.credit
rec_list_ids = []
@ -1392,9 +1393,9 @@ class account_voucher(osv.osv):
line_total, rec_list_ids = self.voucher_move_line_create(cr, uid, voucher.id, line_total, move_id, company_currency, current_currency, context)
# Create the writeoff line if needed
ml_writeoff = self.writeoff_move_line_get(cr, uid, voucher.id, line_total, move_id, name, company_currency, current_currency, context)
ml_writeoff = self.writeoff_move_line_get(cr, uid, voucher.id, line_total, move_id, name, company_currency, current_currency, local_context)
if ml_writeoff:
move_line_pool.create(cr, uid, ml_writeoff, context)
move_line_pool.create(cr, uid, ml_writeoff, local_context)
# We post the voucher.
self.write(cr, uid, [voucher.id], {
'move_id': move_id,
@ -1605,7 +1606,11 @@ class account_bank_statement(osv.osv):
bank_st_line_obj = self.pool.get('account.bank.statement.line')
st_line = bank_st_line_obj.browse(cr, uid, st_line_id, context=context)
if st_line.voucher_id:
voucher_obj.write(cr, uid, [st_line.voucher_id.id], {'number': next_number}, context=context)
voucher_obj.write(cr, uid, [st_line.voucher_id.id],
{'number': next_number,
'date': st_line.date,
'period_id': st_line.statement_id.period_id.id},
context=context)
if st_line.voucher_id.state == 'cancel':
voucher_obj.action_cancel_draft(cr, uid, [st_line.voucher_id.id], context=context)
voucher_obj.signal_proforma_voucher(cr, uid, [st_line.voucher_id.id])

View File

@ -94,7 +94,7 @@ class account_statement_from_invoice_lines(osv.osv_memory):
'account_id': result['value'].get('account_id', statement.journal_id.default_credit_account_id.id),
'company_id': statement.company_id.id,
'currency_id': statement.currency.id,
'date': line.date,
'date': statement.date,
'amount': sign*amount,
'payment_rate': result['value']['payment_rate'],
'payment_rate_currency_id': result['value']['payment_rate_currency_id'],
@ -119,7 +119,7 @@ class account_statement_from_invoice_lines(osv.osv_memory):
'statement_id': statement_id,
'ref': line.ref,
'voucher_id': voucher_id,
'date': time.strftime('%Y-%m-%d'),
'date': statement.date,
}, context=context)
return {'type': 'ir.actions.act_window_close'}

View File

@ -268,10 +268,14 @@ def log_fct(cr, uid_orig, model, method, fct_src, *args, **kw):
new_values = get_data(cr, uid_orig, pool, res_ids, model, method)
elif method == 'read':
res = fct_src(cr, uid_orig, model.model, method, *args, **kw)
if isinstance(res, dict):
records = [res]
else:
records = res
# build the res_ids and the old_values dict. Here we don't use get_data() to
# avoid performing an additional read()
res_ids = []
for record in res:
for record in records:
res_ids.append(record['id'])
old_values[(model.id, record['id'])] = {'value': record, 'text': record}
# log only the fields read
@ -279,7 +283,9 @@ def log_fct(cr, uid_orig, model, method, fct_src, *args, **kw):
elif method == 'unlink':
res_ids = args[0]
old_values = get_data(cr, uid_orig, pool, res_ids, model, method)
res = fct_src(cr, uid_orig, model.model, method, *args, **kw)
# process_data first as fct_src will unlink the record
self.process_data(cr, uid_orig, pool, res_ids, model, method, old_values, new_values, field_list)
return fct_src(cr, uid_orig, model.model, method, *args, **kw)
else: # method is write, action or workflow action
res_ids = []
if args:
@ -322,7 +328,7 @@ def get_data(cr, uid, pool, res_ids, model, method):
data = {}
resource_pool = pool[model.model]
# read all the fields of the given resources in super admin mode
for resource in resource_pool.read(cr, SUPERUSER_ID, res_ids):
for resource in resource_pool.read(cr, SUPERUSER_ID, res_ids, resource_pool._all_columns):
values = {}
values_text = {}
resource_id = resource['id']
@ -456,7 +462,9 @@ def process_data(cr, uid, pool, res_ids, model, method, old_values=None, new_val
# if at least one modification has been found
for model_id, resource_id in lines:
name = pool[model.model].name_get(cr, uid, [resource_id])[0][1]
line_model = pool.get('ir.model').browse(cr, SUPERUSER_ID, model_id).model
name = pool.get(line_model).name_get(cr, uid, [resource_id])[0][1]
vals = {
'method': method,
'object_id': model_id,

View File

@ -275,6 +275,13 @@ class base_action_rule(osv.osv):
if action.filter_id:
domain = eval(action.filter_id.domain)
ctx.update(eval(action.filter_id.context))
if 'lang' not in ctx:
# Filters might be language-sensitive, attempt to reuse creator lang
# as we are usually running this as super-user in background
[filter_meta] = action.filter_id.perm_read()
user_id = filter_meta['write_uid'] and filter_meta['write_uid'][0] or \
filter_meta['create_uid'][0]
ctx['lang'] = self.pool['res.users'].browse(cr, uid, user_id).lang
record_ids = model.search(cr, uid, domain, context=ctx)
# determine when action should occur for the records

View File

@ -60,7 +60,7 @@
<h3>Body</h3>
<field name="body_html" width="250" height="450"
placeholder="Rich-text/HTML content of the message (placeholders may be used here)"/>
<field name="attachment_ids" nolabel="1" widget="many2many_binary"/>
<field name="attachment_ids" widget="many2many_binary"/>
</page>
<page string="Advanced Settings">
<group>

View File

@ -369,10 +369,11 @@ class mail_thread(osv.AbstractModel):
track_ctx = dict(context)
if 'lang' not in track_ctx:
track_ctx['lang'] = self.pool.get('res.users').browse(cr, uid, uid, context=context).lang
tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=track_ctx)
if tracked_fields:
initial_values = {thread_id: dict((item, False) for item in tracked_fields)}
self.message_track(cr, uid, [thread_id], tracked_fields, initial_values, context=track_ctx)
if not context.get('mail_notrack'):
tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=track_ctx)
if tracked_fields:
initial_values = {thread_id: dict((item, False) for item in tracked_fields)}
self.message_track(cr, uid, [thread_id], tracked_fields, initial_values, context=track_ctx)
return thread_id
def write(self, cr, uid, ids, values, context=None):
@ -393,7 +394,11 @@ class mail_thread(osv.AbstractModel):
result = super(mail_thread, self).write(cr, uid, ids, values, context=context)
self.message_auto_subscribe(cr, uid, ids, values.keys(), context=context, values=values)
# Perform the tracking
if not context.get('mail_notrack'):
# Perform the tracking
tracked_fields = self._get_tracked_fields(cr, uid, values.keys(), context=context)
else:
tracked_fields = None
if tracked_fields:
self.message_track(cr, uid, ids, tracked_fields, initial_values, context=track_ctx)
return result
@ -414,6 +419,9 @@ class mail_thread(osv.AbstractModel):
return res
def copy(self, cr, uid, id, default=None, context=None):
# avoid tracking multiple temporary changes during copy
context = dict(context or {}, mail_notrack=True)
default = default or {}
default['message_ids'] = []
default['message_follower_ids'] = []
@ -1549,18 +1557,23 @@ class mail_thread(osv.AbstractModel):
""" Add partners to the records followers. """
if context is None:
context = {}
# not necessary for computation, but saves an access right check
if not partner_ids:
return True
mail_followers_obj = self.pool.get('mail.followers')
subtype_obj = self.pool.get('mail.message.subtype')
user_pid = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
if set(partner_ids) == set([user_pid]):
if context.get('operation', '') != 'create':
try:
self.check_access_rights(cr, uid, 'read')
try:
self.check_access_rights(cr, uid, 'read')
if context.get('operation', '') == 'create':
self.check_access_rule(cr, uid, ids, 'create')
else:
self.check_access_rule(cr, uid, ids, 'read')
except (osv.except_osv, orm.except_orm):
return False
except (osv.except_osv, orm.except_orm):
return False
else:
self.check_access_rights(cr, uid, 'write')
self.check_access_rule(cr, uid, ids, 'write')
@ -1605,6 +1618,9 @@ class mail_thread(osv.AbstractModel):
def message_unsubscribe(self, cr, uid, ids, partner_ids, context=None):
""" Remove partners from the records followers. """
# not necessary for computation, but saves an access right check
if not partner_ids:
return True
user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
if set(partner_ids) == set([user_pid]):
self.check_access_rights(cr, uid, 'read')

View File

@ -197,6 +197,7 @@ openerp_mail_followers = function(session, mail) {
// clean and display title
var node_user_list = this.$('.oe_follower_list').empty();
this.$('.oe_follower_title').html(this._format_followers(this.followers.length));
self.message_is_follower = _.indexOf(this.followers.map(function (rec) { return rec[2]['is_uid']}), true) != -1;
// truncate number of displayed followers
var truncated = this.followers.slice(0, this.displayed_nb);
_(truncated).each(function (record) {
@ -207,9 +208,6 @@ openerp_mail_followers = function(session, mail) {
'is_editable': record[2]['is_editable'],
'avatar_url': mail.ChatterUtils.get_image(self.session, 'res.partner', 'image_small', record[0]),
}
if (partner.is_uid) {
self.message_is_follower = partner.is_uid;
}
$(session.web.qweb.render('mail.followers.partner', {'record': partner, 'widget': self})).appendTo(node_user_list);
// On mouse-enter it will show the edit_subtype pencil.
if (partner.is_editable) {

View File

@ -135,14 +135,14 @@
<t t-if="widget.is_private or (widget.user_pid != partner[0])">
<t t-if="!widget.is_private and inc==0"> and </t>
<span t-attf-class="oe_partner_follower #{inc>=3?'oe_hidden':''}"><t t-if="inc" t-raw="', '"/>
<a t-if="widget.options.show_link" t-attf-href="#model=res.partner&amp;id=#{partner[0]}"><t t-raw="partner[1]"/></a>
<t t-if="!widget.options.show_link" t-raw="partner[1]"/>
<a t-if="widget.options.show_link" t-attf-href="#model=res.partner&amp;id=#{partner[0]}"><t t-esc="partner[1]"/></a>
<t t-if="!widget.options.show_link" t-esc="partner[1]"/>
</span>
<t t-set="inc" t-value="inc+1"/>
</t>
</t>
<t t-if="widget.partner_ids.length > 3">
<span class="oe_more">, <a><t t-raw="widget.partner_ids.length - 3"/> others...</a></span>
<span class="oe_more">, <a><t t-esc="widget.partner_ids.length - 3"/> others...</a></span>
<a class="oe_more_hidden">&lt;&lt;&lt;</a>
</t>
</div>
@ -150,8 +150,8 @@
<t t-foreach='widget.recipients' t-as='recipient'>
<label t-attf-title="Add as recipient and follower (reason: #{recipient.reason})">
<input type="checkbox" t-att-checked="recipient.checked ? 'checked' : undefined" t-att-data="recipient.full_name"/>
<t t-raw="recipient.name"/>
<t t-if="recipient.email_address">(<t t-raw="recipient.email_address"/>)</t>
<t t-esc="recipient.name"/>
<t t-if="recipient.email_address">(<t t-esc="recipient.email_address"/>)</t>
<t t-if="!recipient.email_address">(no email address)</t>
</label>
</t>
@ -177,7 +177,7 @@
<td colspan="2">
<h2 class="oe_view_title">
<span class="oe_view_title_text">
<t t-raw="widget.action.name"/>
<t t-esc="widget.action.name"/>
</span>
</h2>
<t t-if="widget.action.params.header_description">
@ -263,11 +263,11 @@
<div class="oe_msg_content">
<h1 t-if="(widget.show_record_name or widget.subject) and !widget.thread_level" class="oe_msg_title">
<a t-if="widget.options.show_link and widget.show_record_name" class="oe_mail_action_model" t-attf-href="#model=#{widget.model}&amp;id=#{widget.res_id}">
<t t-raw="widget.record_name"/>
<t t-esc="widget.record_name"/>
</a>
<span t-if="!widget.options.show_link and widget.show_record_name"><t t-raw="widget.record_name"/></span>
<span t-if="!widget.options.show_link and widget.show_record_name"><t t-esc="widget.record_name"/></span>
<t t-if="widget.show_record_name and widget.subject">: </t>
<t t-if="widget.subject" t-raw="widget.subject"/>
<t t-if="widget.subject" t-esc="widget.subject"/>
</h1>
<div class="oe_msg_body">
<t t-if="widget.body_short">
@ -283,8 +283,8 @@
<t t-if="widget.attachment_ids.length > 0">
<div class="oe_msg_attachment_list"></div>
</t>
<a t-if="widget.author_id and widget.options.show_link and widget.author_id[0]" t-attf-href="#model=res.partner&amp;id=#{widget.author_id[0]}"><t t-raw="widget.author_id[2]"/></a>
<span t-if="widget.author_id and (!widget.options.show_link or !widget.author_id[0])"><t t-raw="widget.author_id[2]"/></span>
<a t-if="widget.author_id and widget.options.show_link and widget.author_id[0]" t-attf-href="#model=res.partner&amp;id=#{widget.author_id[0]}"><t t-esc="widget.author_id[2]"/></a>
<span t-if="widget.author_id and (!widget.options.show_link or !widget.author_id[0])"><t t-esc="widget.author_id[2]"/></span>
<t t-if="widget.type == 'notification'">
updated document
<t t-if="widget.partner_ids.length > 0">
@ -303,20 +303,20 @@
<t t-if="widget.type == 'notification' or ( (widget.type == 'email' or widget.type == 'comment') and (widget.subtype or widget.partner_ids.length > 0))"
t-foreach="widget.partner_ids.slice(0, 3)" t-as="partner">
<span t-attf-class="oe_partner_follower">
<a t-if="widget.options.show_link" t-attf-href="#model=res.partner&amp;id=#{partner[0]}"><t t-raw="partner[1]"/></a>
<t t-if="!widget.options.show_link" t-raw="partner[1]"/>
<a t-if="widget.options.show_link" t-attf-href="#model=res.partner&amp;id=#{partner[0]}"><t t-esc="partner[1]"/></a>
<t t-if="!widget.options.show_link" t-esc="partner[1]"/>
</span>
<t t-if="!partner_last">,</t>
</t>
<t t-if="widget.partner_ids.length > 3">
<span t-att-title="widget.extra_partners_str">and <t t-raw="widget.extra_partners_nbr"/> more</span>
<span t-att-title="widget.extra_partners_str">and <t t-esc="widget.extra_partners_nbr"/> more</span>
</t>
<t t-if="widget.type == 'notification' and widget.partner_ids.length > 0">
notified
</t>
<span class='oe_subtle'></span>
<span t-att-title="widget.date">
<t t-if="widget.timerelative" t-raw="widget.timerelative"/>
<t t-if="widget.timerelative" t-esc="widget.timerelative"/>
<t t-if="!widget.timerelative" t-raw="widget.display_date"/>
</span>
<span t-if="!widget.options.readonly" class='oe_subtle'></span>
@ -333,7 +333,7 @@
<div class='oe_separator'></div>
<a t-if="widget.nb_messages &lt;= 0" class="oe_msg_fetch_more">show more message</a>
<a t-if="widget.nb_messages === 1" class="oe_msg_fetch_more">show one more message</a>
<a t-if="widget.nb_messages &gt; 1" class="oe_msg_fetch_more">show <t t-raw="widget.nb_messages" /> more messages</a>
<a t-if="widget.nb_messages &gt; 1" class="oe_msg_fetch_more">show <t t-esc="widget.nb_messages" /> more messages</a>
</div>
</div>
</t>
@ -353,7 +353,7 @@
-->
<span t-name="mail.thread.message.vote">
<span class="oe_mail_vote_count" t-if='widget.vote_nb > 0'>
<t t-raw='widget.vote_nb' />
<t t-esc='widget.vote_nb' />
<span class='oe_e'>8</span>
</span>
<a href='#' class="oe_msg_vote">

View File

@ -43,13 +43,13 @@
<table class='oe_subtype'>
<tr>
<td width="10%"><input type="checkbox" t-att-checked="record.followed" t-att-id="'input_mail_followers_subtype_'+record.id" t-att-data-id="record.id" t-att-name="record.name" class="oe_msg_subtype_check"/></td>
<td><label t-att-for="'input_mail_followers_subtype_'+record.id"><t t-raw="record.name"/></label></td>
<td><label t-att-for="'input_mail_followers_subtype_'+record.id"><t t-esc="record.name"/></label></td>
</tr>
</table>
</t>
<t t-name="mail.followers.show_more">
<div class="oe_partner oe_show_more">And <t t-raw="number"/> more.</div>
<div class="oe_partner oe_show_more">And <t t-esc="number"/> more.</div>
</t>
</template>

View File

@ -130,7 +130,7 @@ class mail_compose_message(osv.TransientModel):
'wizard_id', 'attachment_id', 'Attachments'),
'filter_id': fields.many2one('ir.filters', 'Filters'),
}
#TODO change same_thread to False in trunk (Require view update)
_defaults = {
'composition_mode': 'comment',
'body': lambda self, cr, uid, ctx={}: '',
@ -268,6 +268,8 @@ class mail_compose_message(osv.TransientModel):
'mail.message', 0,
context=context)
mail_values['attachment_ids'] = m2m_attachment_ids
if not mail_values.get('reply_to'):
mail_values['reply_to'] = mail_values['email_from']
self.pool.get('mail.mail').create(cr, uid, mail_values, context=context)
else:
subtype = 'mail.mt_comment'
@ -321,10 +323,10 @@ class mail_compose_message(osv.TransientModel):
if email_dict.get('email_from'):
mail_values['email_from'] = email_dict.pop('email_from')
# replies redirection: mass mailing only
if not wizard.same_thread:
mail_values['reply_to'] = email_dict.pop('reply_to', None)
else:
if wizard.same_thread and wizard.post:
email_dict.pop('reply_to', None)
else:
mail_values['reply_to'] = email_dict.pop('reply_to', None)
mail_values.update(email_dict)
# mass mailing without post: mail_mail values
if mass_mail_mode and not wizard.post:

View File

@ -47,10 +47,10 @@
<field name="notify"
attrs="{'invisible':['|', ('post', '!=', True), ('composition_mode', '!=', 'mass_mail')]}"/>
<field name="same_thread"
attrs="{'invisible':[('composition_mode', '!=', 'mass_mail')]}"/>
attrs="{'invisible':['|', ('composition_mode', '!=', 'mass_mail'), ('post', '=', False)]}"/>
<field name="reply_to" placeholder="Email address te redirect replies..."
attrs="{'invisible':['|', ('same_thread', '=', True), ('composition_mode', '!=', 'mass_mail')],
'required':[('same_thread', '!=', True)]}"/>
attrs="{'invisible':['|', '&amp;', ('same_thread', '=', True), ('post', '=', True), ('composition_mode', '!=', 'mass_mail')],
'required':['&amp;', '|', ('post', '=', False), ('same_thread', '=', False), ('composition_mode', '=', 'mass_mail')]}"/>
</group>
<field name="body"/>
<field name="attachment_ids" widget="many2many_binary" string="Attach a file"/>

View File

@ -48,6 +48,7 @@ class MailThread(osv.Model):
if bounce_alias in email_to:
bounce_match = tools.bounce_re.search(email_to)
if bounce_match:
bounced_model, bounced_thread_id = None, False
bounced_mail_id = bounce_match.group(1)
stat_ids = self.pool['mail.mail.statistics'].set_bounced(cr, uid, mail_mail_ids=[bounced_mail_id], context=context)
for stat in self.pool['mail.mail.statistics'].browse(cr, uid, stat_ids, context=context):
@ -55,7 +56,7 @@ class MailThread(osv.Model):
bounced_thread_id = stat.res_id
_logger.info('Routing mail from %s to %s with Message-Id %s: bounced mail from mail %s, model: %s, thread_id: %s',
email_from, email_to, message_id, bounced_mail_id, bounced_model, bounced_thread_id)
if bounced_model and bounced_model in self.pool and hasattr(self.pool[bounced_model], 'message_receive_bounce'):
if bounced_model and bounced_model in self.pool and hasattr(self.pool[bounced_model], 'message_receive_bounce') and bounced_thread_id:
self.pool[bounced_model].message_receive_bounce(cr, uid, [bounced_thread_id], mail_id=bounced_mail_id, context=context)
return False

View File

@ -111,9 +111,6 @@ class procurement_order(osv.osv):
bom_result = production_obj.action_compute(cr, uid,
[produce_id], properties=[x.id for x in procurement.property_ids])
production_obj.signal_button_confirm(cr, uid, [produce_id])
if res_id:
move_obj.write(cr, uid, [res_id],
{'location_id': procurement.location_id.id})
self.production_order_create_note(cr, uid, ids, context=context)
return res

View File

@ -474,11 +474,12 @@ class pos_session(osv.osv):
account_move_obj = self.pool.get('account.move')
pos_order_obj = self.pool.get('pos.order')
for session in self.browse(cr, uid, ids, context=context):
local_context = dict(context or {}, force_company=session.config_id.journal_id.company_id.id)
order_ids = [order.id for order in session.order_ids if order.state == 'paid']
move_id = account_move_obj.create(cr, uid, {'ref' : session.name, 'journal_id' : session.config_id.journal_id.id, }, context=context)
move_id = account_move_obj.create(cr, uid, {'ref' : session.name, 'journal_id' : session.config_id.journal_id.id, }, context=local_context)
pos_order_obj._create_account_move_line(cr, uid, order_ids, session, move_id, context=context)
pos_order_obj._create_account_move_line(cr, uid, order_ids, session, move_id, context=local_context)
for order in session.order_ids:
if order.state not in ('paid', 'invoiced'):
@ -948,22 +949,16 @@ class pos_order(osv.osv):
# Tricky, via the workflow, we only have one id in the ids variable
"""Create a account move line of order grouped by products or not."""
account_move_obj = self.pool.get('account.move')
account_move_line_obj = self.pool.get('account.move.line')
account_period_obj = self.pool.get('account.period')
account_tax_obj = self.pool.get('account.tax')
user_proxy = self.pool.get('res.users')
property_obj = self.pool.get('ir.property')
cur_obj = self.pool.get('res.currency')
period = account_period_obj.find(cr, uid, context=context)[0]
#session_ids = set(order.session_id for order in self.browse(cr, uid, ids, context=context))
if session and not all(session.id == order.session_id.id for order in self.browse(cr, uid, ids, context=context)):
raise osv.except_osv(_('Error!'), _('Selected orders do not have the same session!'))
current_company = user_proxy.browse(cr, uid, uid, context=context).company_id
grouped_data = {}
have_to_group_by = session and session.config_id.group_by or False
@ -983,7 +978,7 @@ class pos_order(osv.osv):
if order.state != 'paid':
continue
user_company = user_proxy.browse(cr, order.user_id.id, order.user_id.id).company_id
current_company = order.sale_journal.company_id
group_tax = {}
account_def = property_obj.get(cr, uid, 'property_account_receivable', 'res.partner', context=context)
@ -1004,6 +999,7 @@ class pos_order(osv.osv):
# if have_to_group_by:
sale_journal_id = order.sale_journal.id
period = account_period_obj.find(cr, uid, context=dict(context or {}, company_id=current_company.id))[0]
# 'quantity': line.qty,
# 'product_id': line.product_id.id,
@ -1013,7 +1009,7 @@ class pos_order(osv.osv):
'journal_id' : sale_journal_id,
'period_id' : period,
'move_id' : move_id,
'company_id': user_company and user_company.id or False,
'company_id': current_company.id,
})
if data_type == 'product':
@ -1054,7 +1050,10 @@ class pos_order(osv.osv):
cur = order.pricelist_id.currency_id
for line in order.lines:
tax_amount = 0
taxes = [t for t in line.product_id.taxes_id]
taxes = []
for t in line.product_id.taxes_id:
if t.company_id.id == current_company.id:
taxes.append(t)
computed_taxes = account_tax_obj.compute_all(cr, uid, taxes, line.price_unit * (100.0-line.discount) / 100.0, line.qty)['taxes']
for tax in computed_taxes:

View File

@ -99,13 +99,10 @@ class pos_details_summary(report_sxw.rml_parse):
def _get_tax_amount(self, objects):
res = {}
list_ids = []
for order in objects:
for line in order.lines:
if len(line.product_id.taxes_id):
tax = line.product_id.taxes_id[0]
res[tax.name] = (line.price_unit * line.qty * (1-(line.discount or 0.0) / 100.0)) + (tax.id in list_ids and res[tax.name] or 0)
list_ids.append(tax.id)
for tax in line.product_id.taxes_id:
res[tax.name] = res.setdefault(tax.name, 0.0) + (line.price_subtotal_incl - line.price_subtotal)
return res
def _get_sales_total(self, objects):

View File

@ -232,7 +232,7 @@
<blockTable colWidths="255.0,255.0" style="Table11">
<tr>
<td>
<para style="P2">[[ t[0] ]]</para>
<para style="P2">[[ t[0].name ]]</para>
</td>
<td>
<para style="terp_default_Right_9_Bold">[[ formatLang(t[1], currency_obj=company.currency_id) ]]</para>

View File

@ -244,13 +244,15 @@ class product_pricelist(osv.osv):
for seller in product.seller_ids:
if (not partner) or (seller.name.id<>partner):
continue
product_default_uom = product.uom_id.id
qty_in_seller_uom = qty
from_uom = context.get('uom') or product.uom_id.id
seller_uom = seller.product_uom and seller.product_uom.id or False
if seller_uom and product_default_uom and product_default_uom != seller_uom:
if seller_uom and from_uom and from_uom != seller_uom:
qty_in_seller_uom = product_uom_obj._compute_qty(cr, uid, from_uom, qty, to_uom_id=seller_uom)
else:
uom_price_already_computed = True
qty = product_uom_obj._compute_qty(cr, uid, product_default_uom, qty, to_uom_id=seller_uom)
for line in seller.pricelist_ids:
if line.min_quantity <= qty:
if line.min_quantity <= qty_in_seller_uom:
price = line.price
else:

View File

@ -358,6 +358,11 @@ class project(osv.osv):
default['state'] = 'open'
default['line_ids'] = []
default['tasks'] = []
# Don't prepare (expensive) data to copy children (analytic accounts),
# they are discarded in analytic.copy(), and handled in duplicate_template()
default['child_ids'] = []
proj = self.browse(cr, uid, id, context=context)
if not default.get('name', False):
default.update(name=_("%s (copy)") % (proj.name))
@ -690,23 +695,13 @@ class task(osv.osv):
return {'value': vals}
def duplicate_task(self, cr, uid, map_ids, context=None):
for new in map_ids.values():
task = self.browse(cr, uid, new, context)
child_ids = [ ch.id for ch in task.child_ids]
if task.child_ids:
for child in task.child_ids:
if child.id in map_ids.keys():
child_ids.remove(child.id)
child_ids.append(map_ids[child.id])
parent_ids = [ ch.id for ch in task.parent_ids]
if task.parent_ids:
for parent in task.parent_ids:
if parent.id in map_ids.keys():
parent_ids.remove(parent.id)
parent_ids.append(map_ids[parent.id])
#FIXME why there is already the copy and the old one
self.write(cr, uid, new, {'parent_ids':[(6,0,set(parent_ids))], 'child_ids':[(6,0, set(child_ids))]})
mapper = lambda t: map_ids.get(t.id, t.id)
for task in self.browse(cr, uid, map_ids.values(), context):
new_child_ids = set(map(mapper, task.child_ids))
new_parent_ids = set(map(mapper, task.parent_ids))
if new_child_ids or new_parent_ids:
task.write({'parent_ids': [(6,0,list(new_parent_ids))],
'child_ids': [(6,0,list(new_child_ids))]})
def copy_data(self, cr, uid, id, default=None, context=None):
if default is None:

View File

@ -176,7 +176,7 @@
<button name="invoice_ok" states="except_invoice" string="Manually Corrected"/>
<button name="purchase_approve" states="confirmed" string="Approve Order" class="oe_highlight" groups="purchase.group_purchase_manager"/>
<button name="view_picking" string="Receive Products" type="object" attrs="{'invisible': ['|', ('shipped','=',True), ('state','!=', 'approved')]}" class="oe_highlight"/>
<button name="view_invoice" string="Receive Invoice" type="object" attrs="{'invisible': ['|', ('invoice_method','=','picking'), '|', ('state','!=', 'approved'), ('invoiced','=',True) ]}" class="oe_highlight"/>
<button name="view_invoice" string="Receive Invoice" type="object" attrs="{'invisible': ['|', ('invoice_method','in', ['picking', 'manual']), '|', ('state','!=', 'approved'), ('invoiced','=',True) ]}" class="oe_highlight"/>
<button name="action_cancel_draft" states="cancel,confirmed" string="Set to Draft" type="object" />
<button name="purchase_cancel" states="draft,confirmed,sent" string="Cancel"/>
<field name="state" widget="statusbar" statusbar_visible="draft,sent,approved,done" statusbar_colors='{"except_picking":"red","except_invoice":"red","confirmed":"blue"}' readonly="1"/>

View File

@ -77,9 +77,9 @@
<button name="invoice_recreate" states="invoice_except" string="Recreate Invoice" groups="base.group_user"/>
<button name="invoice_corrected" states="invoice_except" string="Ignore Exception" groups="base.group_user"/>
<button name="action_quotation_send" string="Send by Email" type="object" states="draft" class="oe_highlight" groups="base.group_user"/>
<button name="action_quotation_send" string="Send by Email" type="object" states="sent" groups="base.group_user"/>
<button name="action_quotation_send" string="Send by Email" type="object" states="sent,progress,manual" groups="base.group_user"/>
<button name="print_quotation" string="Print" type="object" states="draft" class="oe_highlight" groups="base.group_user"/>
<button name="print_quotation" string="Print" type="object" states="sent" groups="base.group_user"/>
<button name="print_quotation" string="Print" type="object" states="sent,progress,manual" groups="base.group_user"/>
<button name="action_button_confirm" states="draft" string="Confirm Sale" type="object" groups="base.group_user"/>
<button name="action_button_confirm" states="sent" string="Confirm Sale" class="oe_highlight" type="object" groups="base.group_user"/>
<button name="action_view_invoice" string="View Invoice" type="object" class="oe_highlight"
@ -90,7 +90,7 @@
<button name="cancel" states="draft,sent" string="Cancel Quotation" groups="base.group_user"/>
<button name="action_cancel" states="manual,progress" string="Cancel Order" type="object" groups="base.group_user"/>
<button name="invoice_cancel" states="invoice_except" string="Cancel Order" groups="base.group_user"/>
<field name="state" widget="statusbar" statusbar_visible="draft,sent,invoiced,done" statusbar_colors='{"invoice_except":"red","waiting_date":"blue"}'/>
<field name="state" widget="statusbar" statusbar_visible="draft,sent,progress,done" statusbar_colors='{"invoice_except":"red","waiting_date":"blue"}'/>
</header>
<sheet>
<h1>

View File

@ -20,8 +20,8 @@
<xpath expr="//button[@name='action_cancel']" position="after">
<button name="ship_cancel" states="shipping_except" string="Cancel Order"/>
</xpath>
<field name="state" position="replace">
<field name="state" widget="statusbar" statusbar_visible="draft,sent,progress,invoiced,done" statusbar_colors='{"shipping_except":"red","invoice_except":"red","waiting_date":"blue"}'/>
<field name="state" position="attributes">
<attribute name="statusbar_colors">{"shipping_except":"red","invoice_except":"red","waiting_date":"blue"}</attribute>
</field>
<field name="company_id" position="replace">
<field name="company_id" readonly="True"/>

View File

@ -379,8 +379,6 @@ class product_product(osv.osv):
"In a context with a single Warehouse, this includes "
"goods stored in the Stock Location of this Warehouse, or any "
"of its children.\n"
"stored in the Stock Location of the Warehouse of this Shop, "
"or any of its children.\n"
"Otherwise, this includes goods stored in any Stock Location "
"with 'internal' type."),
'incoming_qty': fields.function(_product_available, multi='qty_available',
@ -392,9 +390,6 @@ class product_product(osv.osv):
"In a context with a single Warehouse, this includes "
"goods arriving to the Stock Location of this Warehouse, or "
"any of its children.\n"
"In a context with a single Shop, this includes goods "
"arriving to the Stock Location of the Warehouse of this "
"Shop, or any of its children.\n"
"Otherwise, this includes goods arriving to any Stock "
"Location with 'internal' type."),
'outgoing_qty': fields.function(_product_available, multi='qty_available',
@ -406,9 +401,6 @@ class product_product(osv.osv):
"In a context with a single Warehouse, this includes "
"goods leaving the Stock Location of this Warehouse, or "
"any of its children.\n"
"In a context with a single Shop, this includes goods "
"leaving the Stock Location of the Warehouse of this "
"Shop, or any of its children.\n"
"Otherwise, this includes goods leaving any Stock "
"Location with 'internal' type."),
'track_production': fields.boolean('Track Manufacturing Lots', help="Forces to specify a Serial Number for all moves containing this product and generated by a Manufacturing Order"),