[MERGE] forward port branch saas-11.3 up to e033114879

This commit is contained in:
Christophe Simonis
2019-01-11 18:56:24 +01:00
12 changed files with 111 additions and 22 deletions
+3 -1
View File
@@ -992,6 +992,7 @@ class AccountInvoice(models.Model):
@api.multi
def get_taxes_values(self):
tax_grouped = {}
round_curr = self.currency_id.round
for line in self.invoice_line_ids:
if not line.account_id:
continue
@@ -1003,9 +1004,10 @@ class AccountInvoice(models.Model):
if key not in tax_grouped:
tax_grouped[key] = val
tax_grouped[key]['base'] = round_curr(val['base'])
else:
tax_grouped[key]['amount'] += val['amount']
tax_grouped[key]['base'] += val['base']
tax_grouped[key]['base'] += round_curr(val['base'])
return tax_grouped
@api.multi
@@ -103,3 +103,66 @@ class TestAccountCustomerInvoice(AccountTestUsers):
# I clicked on Add Credit Note button.
self.account_invoice_refund_0.invoice_refund()
def test_customer_invoice_tax(self):
self.env.user.company_id.tax_calculation_rounding_method = 'round_globally'
payment_term = self.env.ref('account.account_payment_term_advance')
journalrec = self.env['account.journal'].search([('type', '=', 'sale')])[0]
partner3 = self.env.ref('base.res_partner_3')
account_id = self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_revenue').id)], limit=1).id
tax = self.env['account.tax'].create({
'name': 'Tax 15.0',
'amount': 15.0,
'amount_type': 'percent',
'type_tax_use': 'sale',
})
invoice_line_data = [
(0, 0,
{
'product_id': self.env.ref('product.product_product_1').id,
'quantity': 40.0,
'account_id': account_id,
'name': 'product test 1',
'discount' : 10.00,
'price_unit': 2.27,
'invoice_line_tax_ids': [(6, 0, [tax.id])],
}
),
(0, 0,
{
'product_id': self.env.ref('product.product_product_2').id,
'quantity': 21.0,
'account_id': self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_revenue').id)], limit=1).id,
'name': 'product test 2',
'discount' : 10.00,
'price_unit': 2.77,
'invoice_line_tax_ids': [(6, 0, [tax.id])],
}
),
(0, 0,
{
'product_id': self.env.ref('product.product_product_3').id,
'quantity': 21.0,
'account_id': self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_revenue').id)], limit=1).id,
'name': 'product test 3',
'discount' : 10.00,
'price_unit': 2.77,
'invoice_line_tax_ids': [(6, 0, [tax.id])],
}
)
]
invoice = self.env['account.invoice'].create(dict(
name="Test Customer Invoice",
reference_type="none",
payment_term_id=payment_term.id,
journal_id=journalrec.id,
partner_id=partner3.id,
invoice_line_ids=invoice_line_data
))
self.assertEquals(invoice.amount_untaxed, sum([x.base for x in invoice.tax_line_ids]))
@@ -149,7 +149,7 @@ class AuthorizeAPI():
root = self._base_tree('createCustomerProfileRequest')
profile = etree.SubElement(root, "profile")
etree.SubElement(profile, "merchantCustomerId").text = 'ODOO-%s-%s' % (partner.id, uuid4().hex[:8])
etree.SubElement(profile, "email").text = partner.email
etree.SubElement(profile, "email").text = partner.email or ''
payment_profile = etree.SubElement(profile, "paymentProfiles")
etree.SubElement(payment_profile, "customerType").text = 'business' if partner.is_company else 'individual'
billTo = etree.SubElement(payment_profile, "billTo")
+6 -9
View File
@@ -839,21 +839,18 @@ class PosOrder(models.Model):
lots_necessary = True
if picking_type:
lots_necessary = picking_type and picking_type.use_existing_lots
qty = 0
qty_done = 0
pack_lots = []
pos_pack_lots = PosPackOperationLot.search([('order_id', '=', order.id), ('product_id', '=', move.product_id.id)])
pack_lot_names = [pos_pack.lot_name for pos_pack in pos_pack_lots]
if pack_lot_names and lots_necessary:
for lot_name in list(set(pack_lot_names)):
stock_production_lot = StockProductionLot.search([('name', '=', lot_name), ('product_id', '=', move.product_id.id)])
if pos_pack_lots and lots_necessary:
for pos_pack_lot in pos_pack_lots:
stock_production_lot = StockProductionLot.search([('name', '=', pos_pack_lot.lot_name), ('product_id', '=', move.product_id.id)])
if stock_production_lot:
# a serialnumber always has a quantity of 1 product, a lot number takes the full quantity of the order line
qty = 1.0
if stock_production_lot.product_id.tracking == 'lot':
# if a lot nr is set through the frontend it will refer to the full quantity
qty = move.product_uom_qty
else: # serial numbers
qty = 1.0
qty = pos_pack_lot.pos_order_line_id.qty
qty_done += qty
pack_lots.append({'lot_id': stock_production_lot.id, 'qty': qty})
else:
@@ -1970,16 +1970,11 @@ var PaymentScreenWidget = ScreenWidget.extend({
$('body').keypress(this.keyboard_handler);
// that one comes from the pos, but we prefer to cover all the basis
$('body').keydown(this.keyboard_keydown_handler);
// legacy vanilla JS listeners
window.document.body.addEventListener('keypress',this.keyboard_handler);
window.document.body.addEventListener('keydown',this.keyboard_keydown_handler);
this._super();
},
hide: function(){
$('body').off('keypress', this.keyboard_handler);
$('body').off('keydown', this.keyboard_keydown_handler);
window.document.body.removeEventListener('keypress',this.keyboard_handler);
window.document.body.removeEventListener('keydown',this.keyboard_keydown_handler);
this._super();
},
// sets up listeners to watch for order changes
@@ -107,7 +107,13 @@ var ProjectPlan = AbstractAction.extend(ControlPanelMixin, {
* @param {string|html} dom
*/
_refreshPlan: function (dom) {
this.$el.html(dom);
// TODO: Not forward port this fix on master
var $dom = $(dom);
$dom.find('div.o_timesheet_plan_sale_timesheet_dashboard > table.table, ' +
'div.o_timesheet_plan_sale_timesheet_people_time > table.table, ' +
'div.o_project_plan_project_timesheet_forecast > table.table')
.wrap('<div class="table-responsive"></div>');
this.$el.html($dom);
},
/**
@@ -48,7 +48,7 @@ QUnit.module('Timesheet Plan', {
mockRPC: function (route) {
assert.step(route);
if (route === '/timesheet/plan') {
return $.when({html_content: 'Banach-Tarski'});
return $.when({html_content: '<p>Banach-Tarski</p>'});
}
return this._super.apply(this, arguments);
},
@@ -81,7 +81,7 @@ QUnit.module('Timesheet Plan', {
action: {name: 'Fibonacci'},
mockRPC: function (route) {
if (route === '/timesheet/plan') {
return $.when({html_content: 'Banach-Tarski'});
return $.when({html_content: '<p>Banach-Tarski</p>'});
}
return this._super.apply(this, arguments);
},
+4
View File
@@ -533,6 +533,10 @@ class Picking(models.Model):
def action_assign_owner(self):
self.move_line_ids.write({'owner_id': self.owner_id.id})
def action_assign_partner(self):
for picking in self:
picking.move_lines.write({'partner_id': picking.partner_id.id})
@api.multi
def do_print_picking(self):
self.write({'printed': True})
@@ -247,6 +247,9 @@
<group>
<group>
<field name="partner_id"/>
<button name="action_assign_partner" string="Assign Partner" type="object" help="Assign the partner to the Operations. Use only if the partner is manually changed!"
attrs="{'invisible': ['|', '|', ('move_line_exist', '=', False), ('state', 'not in', ('draft', 'assigned', 'confirmed')), ('picking_type_code', '=', 'internal')]}"
class="oe_link oe_edit_only"/>
<field name="picking_type_id" attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="location_id" groups="stock.group_stock_multi_locations" attrs="{'invisible': [('picking_type_code', '=', 'incoming')]}"/>
<field name="location_dest_id" groups="stock.group_stock_multi_locations" attrs="{'invisible': [('picking_type_code', '=', 'outgoing')]}"/>
@@ -736,6 +736,7 @@ var IconWidget = MediaWidget.extend({
this.$('div.font-icons-icons').html(
QWeb.render('web_editor.dialog.font-icons.icons', {iconsParser: iconsParser})
);
return $.when();
},
//--------------------------------------------------------------------------
@@ -690,7 +690,7 @@ a.no-decoration {
.o_website_sale_animate {
opacity: 0.7;
position: absolute;
position: absolute !important;
height: 150px;
width: 150px;
z-index: 1020;
+20 -2
View File
@@ -868,8 +868,26 @@ class GroupsImplied(models.Model):
if values.get('users') or values.get('implied_ids'):
# add all implied groups (to all users of each group)
for group in self:
vals = {'users': list(pycompat.izip(repeat(4), group.with_context(active_test=False).users.ids))}
super(GroupsImplied, group.trans_implied_ids).write(vals)
self._cr.execute("""
WITH RECURSIVE group_imply(gid, hid) AS (
SELECT gid, hid
FROM res_groups_implied_rel
UNION
SELECT i.gid, r.hid
FROM res_groups_implied_rel r
JOIN group_imply i ON (i.hid = r.gid)
)
INSERT INTO res_groups_users_rel (gid, uid)
SELECT i.hid, r.uid
FROM group_imply i, res_groups_users_rel r
WHERE r.gid = i.gid
AND i.gid = %(gid)s
EXCEPT
SELECT r.gid, r.uid
FROM res_groups_users_rel r
JOIN group_imply i ON (r.gid = i.hid)
WHERE i.gid = %(gid)s
""", dict(gid=group.id))
return res
class UsersImplied(models.Model):