[MERGE] forward port branch saas-14 up to c9a01ab30a

This commit is contained in:
Christophe Simonis
2018-06-26 13:13:05 +02:00
15 changed files with 99 additions and 21 deletions
@@ -194,7 +194,7 @@ class ReportAgedPartnerBalance(models.AbstractModel):
values['name'] = _('Unknown Partner')
values['trust'] = False
if at_least_one_amount or self._context.get('include_nullified_amount'):
if at_least_one_amount or (self._context.get('include_nullified_amount') and lines[partner['partner_id']]):
res.append(values)
return res, total, lines
@@ -753,3 +753,61 @@ class TestReconciliation(AccountingTestCase):
self.assertEqual(reversed_bank_line.full_reconcile_id.id, bank_line.full_reconcile_id.id)
self.assertEqual(reversed_customer_line.full_reconcile_id.id, customer_line.full_reconcile_id.id)
def create_invoice_partner(self, type='out_invoice', invoice_amount=50, currency_id=None, partner_id=False):
#we create an invoice in given currency
invoice = self.account_invoice_model.create({'partner_id': partner_id,
'reference_type': 'none',
'currency_id': currency_id,
'name': type == 'out_invoice' and 'invoice to client' or 'invoice to vendor',
'account_id': self.account_rcv.id,
'type': type,
'date_invoice': time.strftime('%Y') + '-07-01',
})
self.account_invoice_line_model.create({'product_id': self.product.id,
'quantity': 1,
'price_unit': invoice_amount,
'invoice_id': invoice.id,
'name': 'product that cost ' + str(invoice_amount),
'account_id': self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_revenue').id)], limit=1).id,
})
#validate invoice
invoice.action_invoice_open()
return invoice
def test_aged_report(self):
AgedReport = self.env['report.account.report_agedpartnerbalance'].with_context(include_nullified_amount=True)
account_type = ['receivable']
report_date_to = time.strftime('%Y') + '-07-15'
partner = self.env['res.partner'].create({'name': 'AgedPartner'})
currency = self.env.user.company_id.currency_id
invoice = self.create_invoice_partner(currency_id=currency.id, partner_id=partner.id)
# Don't forward port in >= 11.0
journal = self.env['account.journal'].create({'name': 'Bank', 'type': 'bank', 'code': 'THE'})
statement = self.make_payment(invoice, journal, 50)
# Case 1: The invoice and payment are reconciled: Nothing should appear
report_lines, total, amls = AgedReport._get_partner_move_lines(account_type, report_date_to, 'posted', 30)
partner_lines = [line for line in report_lines if line['partner_id'] == partner.id]
self.assertEqual(partner_lines, [], 'The aged receivable shouldn\'t have lines at this point')
self.assertFalse(partner.id in amls, 'The aged receivable should not have amls either')
# Case 2: The invoice and payment are not reconciled: we should have one line on the report
# and 2 amls
invoice.move_id.line_ids.with_context(invoice_id=invoice.id).remove_move_reconcile()
report_lines, total, amls = AgedReport._get_partner_move_lines(account_type, report_date_to, 'posted', 30)
partner_lines = [line for line in report_lines if line['partner_id'] == partner.id]
self.assertEqual(partner_lines, [{'trust': 'normal', '1': 0.0, '0': 0.0, 'direction': 0.0, 'partner_id': partner.id, '3': 0.0, 'total': 0.0, 'name': 'AgedPartner', '4': 0.0, '2': 0.0}],
'We should have a line in the report for the partner')
self.assertEqual(len(amls[partner.id]), 2, 'We should have 2 account move lines for the partner')
positive_line = [line for line in amls[partner.id] if line['line'].balance > 0]
negative_line = [line for line in amls[partner.id] if line['line'].balance < 0]
self.assertEqual(positive_line[0]['amount'], 50.0, 'The amount of the amls should be 50')
self.assertEqual(negative_line[0]['amount'], -50.0, 'The amount of the amls should be -50')
+6
View File
@@ -69,3 +69,9 @@ class AccountAnalyticAccount(models.Model):
_inherit = 'account.analytic.account'
name = fields.Char(translate=True)
class ResCountryState(models.Model):
_inherit = 'res.country.state'
name = fields.Char(translate=True)
+3 -2
View File
@@ -206,10 +206,11 @@ class PosConfig(models.Model):
def name_get(self):
result = []
for config in self:
if (not config.session_ids) or (config.session_ids[0].state == 'closed'):
last_session = self.env['pos.session'].search([('config_id', '=', config.id)], limit=1)
if (not last_session) or (last_session.state == 'closed'):
result.append((config.id, config.name + ' (' + _('not used') + ')'))
continue
result.append((config.id, config.name + ' (' + config.session_ids[0].user_id.name + ')'))
result.append((config.id, config.name + ' (' + last_session.user_id.name + ')'))
return result
@api.model
@@ -29,8 +29,10 @@ var Printer = core.Class.extend(mixins.PropertiesMixin,{
self.connection.rpc('/hw_proxy/print_xml_receipt',{receipt: r},{timeout: 5000})
.then(function(){
send_printing_job();
},function(){
},function(error, event){
self.receipt_queue.unshift(r);
console.log('There was an error while trying to print the order:');
console.log(error);
});
}
}
@@ -54,7 +56,7 @@ models.load_models({
for(var i = 0; i < printers.length; i++){
if(active_printers[printers[i].id]){
var url = printers[i].proxy_ip;
var url = printers[i].proxy_ip || '';
if(url.indexOf('//') < 0){
url = 'http://'+url;
}
+2 -2
View File
@@ -1065,7 +1065,7 @@ class ProcurementOrder(models.Model):
if not po:
vals = procurement._prepare_purchase_order(partner)
po = self.env['purchase.order'].create(vals)
name = (procurement.group_id and (procurement.group_id.name + ":") or "") + (procurement.name != "/" and procurement.name or procurement.move_dest_id.raw_material_production_id and procurement.move_dest_id.raw_material_production_id.name or "")
name = (procurement.group_id and (procurement.group_id.name + ":") or "") + (procurement.name != "/" and procurement.name or "")
message = _("This purchase order has been created from: <a href=# data-oe-model=procurement.order data-oe-id=%d>%s</a>") % (procurement.id, name)
po.message_post(body=message)
cache[domain] = po
@@ -1078,7 +1078,7 @@ class ProcurementOrder(models.Model):
po.write({'origin': po.origin})
else:
po.write({'origin': procurement.origin})
name = (self.group_id and (self.group_id.name + ":") or "") + (self.name != "/" and self.name or self.move_dest_id.raw_material_production_id and self.move_dest_id.raw_material_production_id.name or "")
name = (self.group_id and (self.group_id.name + ":") or "") + (self.name != "/" and self.name or "")
message = _("This purchase order has been modified from: <a href=# data-oe-model=procurement.order data-oe-id=%d>%s</a>") % (procurement.id, name)
po.message_post(body=message)
if po:
+5 -1
View File
@@ -50,7 +50,11 @@ tour.register('sale_tour', {
in_modal: false,
run: function (actions) {
actions.auto();
actions.auto(".modal-footer .btn-primary");
// There might be a modal because of the view:
// sale.order.form.editable.list, enabled by some groups
if ($(".modal-footer .btn-primary").length) {
actions.auto(".modal-footer .btn-primary");
}
},
id: "quotation_product_selected",
}, {
+1 -4
View File
@@ -81,10 +81,7 @@ class AccountInvoiceLine(models.Model):
qty_done = sum([x.uom_id._compute_quantity(x.quantity, x.product_id.uom_id) for x in s_line.invoice_lines if x.invoice_id.state in ('open', 'paid')])
quantity = self.uom_id._compute_quantity(self.quantity, self.product_id.uom_id)
# Put moves in fixed order by date executed
moves = self.env['stock.move']
for procurement in s_line.procurement_ids:
moves |= procurement.move_ids
moves.sorted(lambda x: x.date)
moves = s_line.mapped('procurement_ids.move_ids').sorted(lambda x: x.date)
# Go through all the moves and do nothing until you get to qty_done
# Beyond qty_done we need to calculate the average of the price_unit
# on the moves we encounter.
+1 -4
View File
@@ -25,10 +25,7 @@ class AccountInvoiceLine(models.Model):
qty_done = sum([x.uom_id._compute_quantity(x.quantity, x.product_id.uom_id) for x in s_line.invoice_lines if x.invoice_id.state in ('open', 'paid')])
quantity = self.uom_id._compute_quantity(self.quantity, self.product_id.uom_id)
# Put moves in fixed order by date executed
moves = self.env['stock.move']
for procurement in s_line.procurement_ids:
moves |= procurement.move_ids
moves.sorted(lambda x: x.date)
moves = s_line.mapped('procurement_ids.move_ids').sorted(lambda x: x.date)
# Go through all the moves and do nothing until you get to qty_done
# Beyond qty_done we need to calculate the average of the price_unit
# on the moves we encounter.
+1 -1
View File
@@ -529,7 +529,7 @@ class StockMove(models.Model):
'name': self.rule_id and self.rule_id.name or "/",
'origin': origin,
'company_id': self.company_id.id,
'date_planned': self.date,
'date_planned': self.date_expected,
'product_id': self.product_id.id,
'product_qty': self.product_uom_qty,
'product_uom': self.product_uom.id,
+2
View File
@@ -128,11 +128,13 @@ class ProductProduct(models.Model):
'account_id': debit_account_id,
'debit': abs(diff * qty_available),
'credit': 0,
'product_id': product.id,
}), (0, 0, {
'name': _('Standard Price changed'),
'account_id': credit_account_id,
'debit': 0,
'credit': abs(diff * qty_available),
'product_id': product.id,
})],
}
move = AccountMove.create(move_vals)
@@ -33,7 +33,7 @@ function get_fc_defaultOptions() {
// adapt format for fullcalendar v1.
// see http://fullcalendar.io/docs1/utilities/formatDate/
var conversions = [['YYYY', 'yyyy'], ['YY', 'y'], ['DDDD', 'dddd'], ['DD', 'dd']];
var conversions = [['YYYY', 'yyyy'], ['YY', 'yy'], ['DDDD', 'dddd'], ['DD', 'dd']];
_.each(conversions, function(conv) {
dateFormat = dateFormat.replace(conv[0], conv[1]);
});
+11
View File
@@ -64,6 +64,17 @@ class SaleOrder(models.Model):
else:
return 0
@api.model_cr_context
def _init_column(self, column_name):
if column_name != 'access_token':
super(SaleOrder, self)._init_column(column_name)
else:
query = """UPDATE %(table_name)s
SET %(column_name)s = md5(random()::text || clock_timestamp()::text)::uuid
WHERE %(column_name)s IS NULL
""" % {'table_name': self._table, 'column_name': column_name}
self.env.cr.execute(query)
access_token = fields.Char(
'Security Token', copy=False, default=lambda self: str(uuid.uuid4()),
required=True)
@@ -9,7 +9,7 @@ require('website_sale.website_sale');
$('.oe_website_sale #add_to_cart, .oe_website_sale #products_grid .a-submit')
.off('click')
.removeClass('a-submit')
.click(function (event) {
.click(_.debounce(function (event) {
var $form = $(this).closest('form');
var quantity = parseFloat($form.find('input[name="add_qty"]').val() || 1);
var product_id = parseInt($form.find('input[type="hidden"][name="product_id"], input[type="radio"][name="product_id"]:checked').first().val(),10);
@@ -95,6 +95,6 @@ $('.oe_website_sale #add_to_cart, .oe_website_sale #products_grid .a-submit')
});
});
return false;
});
}, 200, true));
});
+1 -1
View File
@@ -188,7 +188,7 @@ class Property(models.Model):
if not values:
return
if not default_value:
if default_value is None:
domain = self._get_domain(name, model)
if domain is None:
raise Exception()