[MERGE] forward port of branch 7.0 up to d0a0b7d

This commit is contained in:
Christophe Simonis 2014-08-20 17:45:05 +02:00
commit 8f13e8320e
15 changed files with 75 additions and 26 deletions

View File

@ -1681,7 +1681,8 @@ class account_move_reconcile(osv.osv):
if not total: if not total:
self.pool.get('account.move.line').write(cr, uid, self.pool.get('account.move.line').write(cr, uid,
map(lambda x: x.id, rec.line_partial_ids), map(lambda x: x.id, rec.line_partial_ids),
{'reconcile_id': rec.id } {'reconcile_id': rec.id },
context=context
) )
return True return True

View File

@ -802,11 +802,14 @@ class account_move_line(osv.osv):
if self.pool.get('res.currency').is_zero(cr, uid, currency_id, total): if self.pool.get('res.currency').is_zero(cr, uid, currency_id, total):
res = self.reconcile(cr, uid, merges+unmerge, context=context, writeoff_acc_id=writeoff_acc_id, writeoff_period_id=writeoff_period_id, writeoff_journal_id=writeoff_journal_id) res = self.reconcile(cr, uid, merges+unmerge, context=context, writeoff_acc_id=writeoff_acc_id, writeoff_period_id=writeoff_period_id, writeoff_journal_id=writeoff_journal_id)
return res return res
# marking the lines as reconciled does not change their validity, so there is no need
# to revalidate their moves completely.
reconcile_context = dict(context, novalidate=True)
r_id = move_rec_obj.create(cr, uid, { r_id = move_rec_obj.create(cr, uid, {
'type': type, 'type': type,
'line_partial_ids': map(lambda x: (4,x,False), merges+unmerge) 'line_partial_ids': map(lambda x: (4,x,False), merges+unmerge)
}, context=context) }, context=reconcile_context)
move_rec_obj.reconcile_partial_check(cr, uid, [r_id] + merges_rec, context=context) move_rec_obj.reconcile_partial_check(cr, uid, [r_id] + merges_rec, context=reconcile_context)
return True return True
def reconcile(self, cr, uid, ids, type='auto', writeoff_acc_id=False, writeoff_period_id=False, writeoff_journal_id=False, context=None): def reconcile(self, cr, uid, ids, type='auto', writeoff_acc_id=False, writeoff_period_id=False, writeoff_journal_id=False, context=None):
@ -931,11 +934,14 @@ class account_move_line(osv.osv):
writeoff_line_ids = [writeoff_line_ids[1]] writeoff_line_ids = [writeoff_line_ids[1]]
ids += writeoff_line_ids ids += writeoff_line_ids
# marking the lines as reconciled does not change their validity, so there is no need
# to revalidate their moves completely.
reconcile_context = dict(context, novalidate=True)
r_id = move_rec_obj.create(cr, uid, { r_id = move_rec_obj.create(cr, uid, {
'type': type, 'type': type,
'line_id': map(lambda x: (4, x, False), ids), 'line_id': map(lambda x: (4, x, False), ids),
'line_partial_ids': map(lambda x: (3, x, False), ids) 'line_partial_ids': map(lambda x: (3, x, False), ids)
}) }, context=reconcile_context)
# the id of the move.reconcile is written in the move.line (self) by the create method above # the id of the move.reconcile is written in the move.line (self) by the create method above
# because of the way the line_id are defined: (4, x, False) # because of the way the line_id are defined: (4, x, False)
for id in ids: for id in ids:

View File

@ -358,7 +358,7 @@ class account_voucher(osv.osv):
\n* The \'Posted\' status is used when user create voucher,a voucher number is generated and voucher entries are created in account \ \n* The \'Posted\' status is used when user create voucher,a voucher number is generated and voucher entries are created in account \
\n* The \'Cancelled\' status is used when user cancel voucher.'), \n* The \'Cancelled\' status is used when user cancel voucher.'),
'amount': fields.float('Total', digits_compute=dp.get_precision('Account'), required=True, readonly=True, states={'draft':[('readonly',False)]}), 'amount': fields.float('Total', digits_compute=dp.get_precision('Account'), required=True, readonly=True, states={'draft':[('readonly',False)]}),
'tax_amount':fields.float('Tax Amount', digits_compute=dp.get_precision('Account'), readonly=True, states={'draft':[('readonly',False)]}), 'tax_amount':fields.float('Tax Amount', digits_compute=dp.get_precision('Account'), readonly=True),
'reference': fields.char('Ref #', size=64, readonly=True, states={'draft':[('readonly',False)]}, help="Transaction reference number."), 'reference': fields.char('Ref #', size=64, readonly=True, states={'draft':[('readonly',False)]}, help="Transaction reference number."),
'number': fields.char('Number', size=32, readonly=True,), 'number': fields.char('Number', size=32, readonly=True,),
'move_id':fields.many2one('account.move', 'Account Entry'), 'move_id':fields.many2one('account.move', 'Account Entry'),
@ -1323,10 +1323,14 @@ class account_voucher(osv.osv):
if voucher.payment_option == 'with_writeoff': if voucher.payment_option == 'with_writeoff':
account_id = voucher.writeoff_acc_id.id account_id = voucher.writeoff_acc_id.id
write_off_name = voucher.comment write_off_name = voucher.comment
elif voucher.type in ('sale', 'receipt'): elif voucher.partner_id:
account_id = voucher.partner_id.property_account_receivable.id if voucher.type in ('sale', 'receipt'):
account_id = voucher.partner_id.property_account_receivable.id
else:
account_id = voucher.partner_id.property_account_payable.id
else: else:
account_id = voucher.partner_id.property_account_payable.id # fallback on account of voucher
account_id = voucher.account_id.id
sign = voucher.type == 'payment' and -1 or 1 sign = voucher.type == 'payment' and -1 or 1
move_line = { move_line = {
'name': write_off_name or name, 'name': write_off_name or name,

View File

@ -159,7 +159,7 @@
<field name="res_model">account.voucher</field> <field name="res_model">account.voucher</field>
<field name="view_type">form</field> <field name="view_type">form</field>
<field name="view_mode">tree,form,graph</field> <field name="view_mode">tree,form,graph</field>
<field name="context">{'type':'general'}</field> <field name="context">{}</field>
<field name="view_id" eval="view_voucher_tree"/> <field name="view_id" eval="view_voucher_tree"/>
<field name="search_view_id" ref="view_voucher_filter"/> <field name="search_view_id" ref="view_voucher_filter"/>
</record> </record>

View File

@ -21,4 +21,5 @@ class auth_oauth_provider(osv.osv):
} }
_defaults = { _defaults = {
'enabled' : False, 'enabled' : False,
'css_class' : "zocial",
} }

View File

@ -27,7 +27,7 @@ class pos_order_report(osv.osv):
_description = "Point of Sale Orders Statistics" _description = "Point of Sale Orders Statistics"
_auto = False _auto = False
_columns = { _columns = {
'date': fields.date('Date Order', readonly=True), 'date': fields.datetime('Date Order', readonly=True),
'partner_id':fields.many2one('res.partner', 'Partner', readonly=True), 'partner_id':fields.many2one('res.partner', 'Partner', readonly=True),
'product_id':fields.many2one('product.product', 'Product', readonly=True), 'product_id':fields.many2one('product.product', 'Product', readonly=True),
'state': fields.selection([('draft', 'New'), ('paid', 'Closed'), ('done', 'Synchronized'), ('invoiced', 'Invoiced'), ('cancel', 'Cancelled')], 'state': fields.selection([('draft', 'New'), ('paid', 'Closed'), ('done', 'Synchronized'), ('invoiced', 'Invoiced'), ('cancel', 'Cancelled')],

View File

@ -684,6 +684,9 @@ class product_product(osv.osv):
unlink_ids = [] unlink_ids = []
unlink_product_tmpl_ids = [] unlink_product_tmpl_ids = []
for product in self.browse(cr, uid, ids, context=context): for product in self.browse(cr, uid, ids, context=context):
# Check if product still exists, in case it has been unlinked by unlinking its template
if not product.exists():
continue
tmpl_id = product.product_tmpl_id.id tmpl_id = product.product_tmpl_id.id
# Check if the product is last product of this template # Check if the product is last product of this template
other_product_ids = self.search(cr, uid, [('product_tmpl_id', '=', tmpl_id), ('id', '!=', product.id)], context=context) other_product_ids = self.search(cr, uid, [('product_tmpl_id', '=', tmpl_id), ('id', '!=', product.id)], context=context)

View File

@ -126,7 +126,7 @@ class stock_partial_picking(osv.osv_memory):
# Overridden to inject the purchase price as true 'cost price' when processing # Overridden to inject the purchase price as true 'cost price' when processing
# incoming pickings. # incoming pickings.
def _product_cost_for_average_update(self, cr, uid, move): def _product_cost_for_average_update(self, cr, uid, move):
if move.picking_id.purchase_id: if move.picking_id.purchase_id and move.purchase_line_id:
return {'cost': move.purchase_line_id.price_unit, return {'cost': move.purchase_line_id.price_unit,
'currency': move.picking_id.purchase_id.currency_id.id} 'currency': move.picking_id.purchase_id.currency_id.id}
return super(stock_partial_picking, self)._product_cost_for_average_update(cr, uid, move) return super(stock_partial_picking, self)._product_cost_for_average_update(cr, uid, move)

View File

@ -277,6 +277,8 @@ class product_product(osv.osv):
if prodlot_id: if prodlot_id:
prodlot_clause = ' and prodlot_id = %s ' prodlot_clause = ' and prodlot_id = %s '
where += [prodlot_id] where += [prodlot_id]
elif 'prodlot_id' in context and not prodlot_id:
prodlot_clause = ' and prodlot_id is null '
# TODO: perhaps merge in one query. # TODO: perhaps merge in one query.
if 'in' in what: if 'in' in what:

View File

@ -37,6 +37,36 @@
!python {model: product.product}: | !python {model: product.product}: |
product = self.browse(cr, uid, ref('product_product_6'), context=context) product = self.browse(cr, uid, ref('product_product_6'), context=context)
assert product.qty_available == 10, "Stock is not updated." assert product.qty_available == 10, "Stock is not updated."
-
I update the current stock of the Ice-cream with 10 kgm without Production Lot.
-
!record {model: stock.change.product.qty, id: change_qty_nolot}:
location_id: location_monitor_small
new_quantity: 10
product_id: product_product_6
-
!python {model: stock.change.product.qty}: |
self.change_product_qty(cr, uid, [ref('change_qty_nolot')], context=dict(context, active_id=ref('product_product_6')))
-
I check available stock of Ice-cream after update stock.
-
!python {model: product.product}: |
product = self.browse(cr, uid, ref('product_product_6'), context=context)
assert product.qty_available == 20, "Real stock is not updated."
-
I revert 10kgm updated stock again with no production lot in order to level the stock
-
!record {model: stock.change.product.qty, id: change_qty_nolot_1}:
location_id: location_monitor_small
new_quantity: 0
product_id: product_product_6
-
!python {model: stock.change.product.qty}: |
self.change_product_qty(cr, uid, [ref('change_qty_nolot_1')], context=dict(context, active_id=ref('product_product_6')))
-
!python {model: product.product}: |
product = self.browse(cr, uid, ref('product_product_6'), context=context)
assert product.qty_available == 10, "Real stock is not updated."
- -
Stock user can merge inventory, so let's check data with giving the access rights of user. Stock user can merge inventory, so let's check data with giving the access rights of user.
- -

View File

@ -258,7 +258,7 @@
if (!focus_field){ if (!focus_field){
focus_field = _.find(self.editor.form.fields_order, function(field){ return fields[field] && fields[field].$el.is(':visible:has(input)'); }); focus_field = _.find(self.editor.form.fields_order, function(field){ return fields[field] && fields[field].$el.is(':visible:has(input)'); });
} }
if (focus_field) fields[focus_field].$el.find('input').select(); if (focus_field && fields[focus_field]) fields[focus_field].$el.find('input').select();
return record.attributes; return record.attributes;
}); });
}).fail(function () { }).fail(function () {

View File

@ -1214,16 +1214,18 @@
</t> </t>
<t t-name="FieldBinaryImage"> <t t-name="FieldBinaryImage">
<span class="oe_form_field oe_form_field_image" t-att-style="widget.node.attrs.style"> <span class="oe_form_field oe_form_field_image" t-att-style="widget.node.attrs.style">
<div class="oe_form_field_image_controls oe_edit_only"> <t t-if="!widget.get('effective_readonly')">
<t t-call="HiddenInputFile"> <div class="oe_form_field_image_controls oe_edit_only">
<t t-set="fileupload_id" t-value="widget.fileupload_id"/> <t t-call="HiddenInputFile">
Edit <t t-set="fileupload_id" t-value="widget.fileupload_id"/>
</t> Edit
<div class="oe_form_binary_progress" style="display: none"> </t>
<img t-att-src='_s + "/web/static/src/img/throbber.gif"' width="16" height="16"/> <div class="oe_form_binary_progress" style="display: none">
<b>Uploading ...</b> <img t-att-src='_s + "/web/static/src/img/throbber.gif"' width="16" height="16"/>
<b>Uploading ...</b>
</div>
</div> </div>
</div> </t>
</span> </span>
</t> </t>
<t t-name="FieldBinaryImage-img"> <t t-name="FieldBinaryImage-img">

View File

@ -183,7 +183,7 @@
<field name="fax"/> <field name="fax"/>
<field name="user_ids" invisible="1"/> <field name="user_ids" invisible="1"/>
<field name="email" widget="email" attrs="{'required': [('user_ids','!=', [])]}"/> <field name="email" widget="email" attrs="{'required': [('user_ids','!=', [])]}"/>
<field name="title" domain="[('domain', '=', 'contact')]" options='{"no_open": True}'/> <field name="title" options='{"no_open": True}'/>
</group> </group>
</group> </group>

View File

@ -1222,9 +1222,9 @@ class function(_column):
# if we already have a value, don't recompute it. # if we already have a value, don't recompute it.
# This happen if case of stored many2one fields # This happen if case of stored many2one fields
if values and not multi and name in values[0]: if values and not multi and name in values[0]:
result = {v['id']: v[name] for v in values} result = dict((v['id'], v[name]) for v in values)
elif values and multi and all(n in values[0] for n in name): elif values and multi and all(n in values[0] for n in name):
result = {v['id']: dict((n, v[n]) for n in name) for v in values} result = dict((v['id'], dict((n, v[n]) for n in name)) for v in values)
else: else:
result = self._fnct(obj, cr, uid, ids, name, self._arg, context) result = self._fnct(obj, cr, uid, ids, name, self._arg, context)
for id in ids: for id in ids:

View File

@ -788,7 +788,7 @@ def trans_generate(lang, modules, cr):
def get_module_paths(): def get_module_paths():
# default addons path (base) # default addons path (base)
def_path = os.path.abspath(os.path.join(config.config['root_path'], 'addons')) def_path = os.path.abspath(os.path.join(config.config['root_path'], 'addons'))
mod_paths = { def_path } mod_paths = set([ def_path ])
ad_paths = map(lambda m: os.path.abspath(m.strip()),config.config['addons_path'].split(',')) ad_paths = map(lambda m: os.path.abspath(m.strip()),config.config['addons_path'].split(','))
for adp in ad_paths: for adp in ad_paths:
mod_paths.add(adp) mod_paths.add(adp)
@ -796,7 +796,7 @@ def trans_generate(lang, modules, cr):
mod_paths.add(adp) mod_paths.add(adp)
elif adp != def_path and adp.startswith(def_path): elif adp != def_path and adp.startswith(def_path):
mod_paths.add(adp[len(def_path)+1:]) mod_paths.add(adp[len(def_path)+1:])
return mod_paths return list(mod_paths)
def get_module_from_path(path, mod_paths): def get_module_from_path(path, mod_paths):
for mp in mod_paths: for mp in mod_paths: