[MERGE] forward port of branch 8.0 up to c0496ed
This commit is contained in:
@@ -1347,7 +1347,7 @@ class account_invoice_line(models.Model):
|
||||
if type in ('in_invoice', 'in_refund'):
|
||||
values['price_unit'] = price_unit or product.standard_price
|
||||
else:
|
||||
values['price_unit'] = product.list_price
|
||||
values['price_unit'] = product.lst_price
|
||||
|
||||
values['uos_id'] = uom_id or product.uom_id.id
|
||||
domain = {'uos_id': [('category_id', '=', product.uom_id.category_id.id)]}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
|
||||
|
||||
import datetime
|
||||
|
||||
from openerp import tools
|
||||
from openerp.tests.common import TransactionCase
|
||||
from openerp.osv import fields
|
||||
|
||||
class TestAccountFollowup(TransactionCase):
|
||||
def setUp(self):
|
||||
@@ -45,14 +44,15 @@ class TestAccountFollowup(TransactionCase):
|
||||
self.registry('account.invoice').signal_workflow(cr, uid, [self.invoice_id], 'invoice_open')
|
||||
|
||||
self.voucher = self.registry("account.voucher")
|
||||
|
||||
self.current_date = datetime.datetime.strptime(fields.date.context_today(self.user, cr, uid, context={}), tools.DEFAULT_SERVER_DATE_FORMAT)
|
||||
|
||||
|
||||
def test_00_send_followup_after_3_days(self):
|
||||
""" Send follow up after 3 days and check nothing is done (as first follow-up level is only after 15 days)"""
|
||||
cr, uid = self.cr, self.uid
|
||||
current_date = datetime.datetime.utcnow()
|
||||
delta = datetime.timedelta(days=3)
|
||||
result = current_date + delta
|
||||
result = self.current_date + delta
|
||||
self.wizard_id = self.wizard.create(cr, uid, {'date':result.strftime(tools.DEFAULT_SERVER_DATE_FORMAT),
|
||||
'followup_id': self.followup_id
|
||||
}, context={"followup_id": self.followup_id})
|
||||
@@ -61,33 +61,32 @@ class TestAccountFollowup(TransactionCase):
|
||||
|
||||
def run_wizard_three_times(self):
|
||||
cr, uid = self.cr, self.uid
|
||||
current_date = datetime.datetime.utcnow()
|
||||
delta = datetime.timedelta(days=40)
|
||||
result = current_date + delta
|
||||
result = self.current_date + delta
|
||||
result = self.current_date + delta
|
||||
self.wizard_id = self.wizard.create(cr, uid, {'date':result.strftime(tools.DEFAULT_SERVER_DATE_FORMAT),
|
||||
'followup_id': self.followup_id
|
||||
}, context={"followup_id": self.followup_id})
|
||||
self.wizard.do_process(cr, uid, [self.wizard_id], context={"followup_id": self.followup_id, 'tz':'UTC'})
|
||||
self.wizard.do_process(cr, uid, [self.wizard_id], context={"followup_id": self.followup_id})
|
||||
self.wizard_id = self.wizard.create(cr, uid, {'date':result.strftime(tools.DEFAULT_SERVER_DATE_FORMAT),
|
||||
'followup_id': self.followup_id
|
||||
}, context={"followup_id": self.followup_id})
|
||||
self.wizard.do_process(cr, uid, [self.wizard_id], context={"followup_id": self.followup_id, 'tz':'UTC'})
|
||||
self.wizard.do_process(cr, uid, [self.wizard_id], context={"followup_id": self.followup_id})
|
||||
self.wizard_id = self.wizard.create(cr, uid, {'date':result.strftime(tools.DEFAULT_SERVER_DATE_FORMAT),
|
||||
'followup_id': self.followup_id,
|
||||
}, context={"followup_id": self.followup_id})
|
||||
self.wizard.do_process(cr, uid, [self.wizard_id], context={"followup_id": self.followup_id, 'tz':'UTC'})
|
||||
self.wizard.do_process(cr, uid, [self.wizard_id], context={"followup_id": self.followup_id})
|
||||
|
||||
def test_01_send_followup_later_for_upgrade(self):
|
||||
""" Send one follow-up after 15 days to check it upgrades to level 1"""
|
||||
cr, uid = self.cr, self.uid
|
||||
current_date = datetime.datetime.utcnow()
|
||||
delta = datetime.timedelta(days=15)
|
||||
result = current_date + delta
|
||||
result = self.current_date + delta
|
||||
self.wizard_id = self.wizard.create(cr, uid, {
|
||||
'date':result.strftime(tools.DEFAULT_SERVER_DATE_FORMAT),
|
||||
'followup_id': self.followup_id
|
||||
}, context={"followup_id": self.followup_id})
|
||||
self.wizard.do_process(cr, uid, [self.wizard_id], context={"followup_id": self.followup_id, 'tz':'UTC'})
|
||||
self.wizard.do_process(cr, uid, [self.wizard_id], context={"followup_id": self.followup_id})
|
||||
self.assertEqual(self.partner.browse(cr, uid, self.partner_id).latest_followup_level_id.id, self.first_followup_line_id,
|
||||
"Not updated to the correct follow-up level")
|
||||
|
||||
@@ -98,7 +97,7 @@ class TestAccountFollowup(TransactionCase):
|
||||
self.assertEqual(self.partner.browse(cr, uid, self.partner_id).payment_next_action,
|
||||
"Call the customer on the phone! ", "Manual action not set")
|
||||
self.assertEqual(self.partner.browse(cr, uid, self.partner_id).payment_next_action_date,
|
||||
datetime.datetime.utcnow().strftime(tools.DEFAULT_SERVER_DATE_FORMAT))
|
||||
self.current_date.strftime(tools.DEFAULT_SERVER_DATE_FORMAT))
|
||||
|
||||
def test_03_filter_on_credit(self):
|
||||
""" Check the partners can be filtered on having credits """
|
||||
@@ -134,9 +133,8 @@ class TestAccountFollowup(TransactionCase):
|
||||
"""Run wizard until manual action, pay the invoice and check that partner has no follow-up level anymore and after running the wizard the action is empty"""
|
||||
cr, uid = self.cr, self.uid
|
||||
self.test_02_check_manual_action()
|
||||
current_date = datetime.datetime.utcnow()
|
||||
delta = datetime.timedelta(days=1)
|
||||
result = current_date + delta
|
||||
result = self.current_date + delta
|
||||
self.invoice.pay_and_reconcile(cr, uid, [self.invoice_id], 1000.0, self.pay_account_id,
|
||||
self.period_id, self.journal_id, self.pay_account_id,
|
||||
self.period_id, self.journal_id,
|
||||
|
||||
@@ -19,13 +19,48 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import osv
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
from openerp.exceptions import UserError
|
||||
from operator import itemgetter
|
||||
|
||||
class account_move_line(osv.osv):
|
||||
_inherit = "account.move.line"
|
||||
|
||||
def _amount_residual(self, cr, uid, ids, field_names, args, context=None):
|
||||
return self._amount_residual(self, cr, uid, ids, field_names, args, context=context)
|
||||
|
||||
def _to_pay_search(self, cr, uid, obj, name, args, context=None):
|
||||
if not args:
|
||||
return []
|
||||
line_obj = self.pool.get('account.move.line')
|
||||
query = line_obj._query_get(cr, uid, context={})
|
||||
where = ' and '.join(map(lambda x: '''(SELECT
|
||||
CASE WHEN l.amount_currency < 0
|
||||
THEN - l.amount_currency
|
||||
ELSE l.credit
|
||||
END - coalesce(sum(pl.amount_currency), 0)
|
||||
FROM payment_line pl
|
||||
INNER JOIN payment_order po ON (pl.order_id = po.id)
|
||||
WHERE move_line_id = l.id
|
||||
AND po.state != 'cancel'
|
||||
) %(operator)s %%s ''' % {'operator': x[1]}, args))
|
||||
sql_args = tuple(map(itemgetter(2), args))
|
||||
|
||||
cr.execute(('''SELECT id
|
||||
FROM account_move_line l
|
||||
WHERE account_id IN (select id
|
||||
FROM account_account
|
||||
WHERE type=%s AND active)
|
||||
AND reconcile_id IS null
|
||||
AND credit > 0
|
||||
AND ''' + where + ' and ' + query), ('payable',)+sql_args )
|
||||
|
||||
res = cr.fetchall()
|
||||
if not res:
|
||||
return [('id', '=', '0')]
|
||||
return [('id', 'in', map(lambda x:x[0], res))]
|
||||
|
||||
def line2bank(self, cr, uid, ids, payment_type=None, context=None):
|
||||
"""
|
||||
Try to return for each Ledger Posting line a corresponding bank
|
||||
@@ -57,3 +92,8 @@ class account_move_line(osv.osv):
|
||||
else:
|
||||
raise UserError(_('There is no partner defined on the entry line.'))
|
||||
return line2bank
|
||||
|
||||
_columns = {
|
||||
'amount_to_pay': fields.function(_amount_residual,
|
||||
type='float', string='Amount to pay', fnct_search=_to_pay_search),
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
<notebook>
|
||||
<page string="Payment">
|
||||
<group col="4">
|
||||
<field name="move_line_id" on_change="onchange_move_line(move_line_id,parent.mode,parent.date_prefered,parent.date_scheduled,currency,company_currency)" domain="[('reconcile_id','=', False), ('credit', '>',0), ('account_id.reconcile', '=', True)] "/>
|
||||
<field name="move_line_id" on_change="onchange_move_line(move_line_id,parent.mode,parent.date_prefered,parent.date_scheduled,currency,company_currency)" domain="[('reconcile_id','=', False), ('credit', '>',0), ('account_id.reconcile', '=', True),('amount_to_pay','>', 0)] "/>
|
||||
<separator colspan="4" string="Transaction Information"/>
|
||||
<field name="date"/>
|
||||
<label for="amount_currency" string="Amount"/>
|
||||
|
||||
@@ -46,24 +46,15 @@ class hr_timesheet_report(osv.osv):
|
||||
htss.date_from,
|
||||
htss.date_to,
|
||||
count(*) as nbr,
|
||||
(SELECT sum(day.total_difference)
|
||||
FROM hr_timesheet_sheet_sheet AS sheet
|
||||
LEFT JOIN hr_timesheet_sheet_sheet_day AS day
|
||||
ON (sheet.id = day.sheet_id) where sheet.id=htss.id) as total_diff,
|
||||
(SELECT sum(day.total_timesheet)
|
||||
FROM hr_timesheet_sheet_sheet AS sheet
|
||||
LEFT JOIN hr_timesheet_sheet_sheet_day AS day
|
||||
ON (sheet.id = day.sheet_id) where sheet.id=htss.id) as total_timesheet,
|
||||
(SELECT sum(day.total_attendance)
|
||||
FROM hr_timesheet_sheet_sheet AS sheet
|
||||
LEFT JOIN hr_timesheet_sheet_sheet_day AS day
|
||||
ON (sheet.id = day.sheet_id) where sheet.id=htss.id) as total_attendance,
|
||||
sum(day.total_difference) as total_diff,
|
||||
sum(day.total_timesheet) as total_timesheet,
|
||||
sum(day.total_attendance) as total_attendance,
|
||||
aal.to_invoice,
|
||||
htss.department_id,
|
||||
htss.state"""
|
||||
|
||||
def _from(self):
|
||||
return super(hr_timesheet_report, self)._from() + "left join hr_timesheet_sheet_sheet as htss ON (hat.sheet_id=htss.id)"
|
||||
return super(hr_timesheet_report, self)._from() + "left join hr_timesheet_sheet_sheet as htss ON (hat.sheet_id=htss.id) left join hr_timesheet_sheet_sheet_day AS day ON (htss.id = day.sheet_id)"
|
||||
|
||||
def _group_by(self):
|
||||
return super(hr_timesheet_report, self)._group_by() + """,
|
||||
|
||||
@@ -800,7 +800,8 @@ openerp.mail = function (session) {
|
||||
|
||||
_.each(messages, function (thread) {
|
||||
if (thread.author_id && !thread.author_id[0] &&
|
||||
!_.find(self.recipients, function (recipient) {return recipient.email_address == thread.author_id[3];})) {
|
||||
!_.find(self.recipients, function (recipient) {return recipient.email_address == thread.author_id[3];}) &&
|
||||
_.some([thread.author_id[1], thread.author_id[2], thread.author_id[3]])) {
|
||||
self.recipients.push({ 'full_name': thread.author_id[1],
|
||||
'name': thread.author_id[2],
|
||||
'email_address': thread.author_id[3],
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
I check Timesheet line for employee in current Timesheet
|
||||
-
|
||||
!python {model: hr.analytic.timesheet}: |
|
||||
import datetime
|
||||
start = (datetime.date.today().strftime('%Y-%m-%d'))
|
||||
from openerp.osv import fields
|
||||
start = fields.date.context_today(self, cr, uid, context=context)
|
||||
task_work = self.search(cr, uid, [("name","=","Social network integration: Test Timesheet records")],context)[0]
|
||||
task_ids = self.browse(cr, uid, task_work, context)
|
||||
assert task_ids.user_id.id == ref("base.user_demo"), 'Error, The User in Timesheet is not Correct'
|
||||
|
||||
@@ -149,19 +149,6 @@ class purchase_order(osv.osv):
|
||||
limit=1)
|
||||
return res and res[0] or False
|
||||
|
||||
def _has_non_stockable_item(self, cr, uid, ids, *args):
|
||||
res = dict.fromkeys(ids, False)
|
||||
for order in self.browse(cr, uid, ids):
|
||||
for order_line in order.order_line:
|
||||
if (
|
||||
not order_line.product_id
|
||||
or
|
||||
order_line.product_id
|
||||
and order_line.product_id.type not in ('product', 'consu')
|
||||
):
|
||||
res[order.id] = True
|
||||
return res
|
||||
|
||||
def _get_picking_in(self, cr, uid, context=None):
|
||||
obj_data = self.pool.get('ir.model.data')
|
||||
type_obj = self.pool.get('stock.picking.type')
|
||||
@@ -311,7 +298,6 @@ class purchase_order(osv.osv):
|
||||
'create_uid': fields.many2one('res.users', 'Responsible'),
|
||||
'company_id': fields.many2one('res.company', 'Company', required=True, select=1, states={'confirmed': [('readonly', True)], 'approved': [('readonly', True)]}),
|
||||
'journal_id': fields.many2one('account.journal', 'Journal'),
|
||||
'has_non_stockable_item': fields.function(_has_non_stockable_item, method=True, type='boolean', string='Contains a non-stockable item'),
|
||||
'bid_date': fields.date('Bid Received On', readonly=True, help="Date on which the bid was received"),
|
||||
'bid_validity': fields.date('Bid Valid Until', help="Date on which the bid expired"),
|
||||
'picking_type_id': fields.many2one('stock.picking.type', 'Deliver To', help="This will determine picking type of incoming shipment", required=True,
|
||||
@@ -554,10 +540,10 @@ class purchase_order(osv.osv):
|
||||
for po in self.browse(cr, uid, ids, context=context):
|
||||
if not po.order_line:
|
||||
raise UserError(_('You cannot confirm a purchase order without any purchase order line.'))
|
||||
if po.invoice_method == 'picking' and po.has_non_stockable_item is True:
|
||||
if po.invoice_method == 'picking' and not any([l.product_id and l.product_id.type in ('product', 'consu') for l in po.order_line]):
|
||||
raise osv.except_osv(
|
||||
_('Error!'),
|
||||
_("You cannot confirm a purchase order with Invoice Control Method 'Based on incoming shipments' that contains non-stockable items."))
|
||||
_("You cannot confirm a purchase order with Invoice Control Method 'Based on incoming shipments' that doesn't contain any stockable item."))
|
||||
for line in po.order_line:
|
||||
if line.state=='draft':
|
||||
todo.append(line.id)
|
||||
|
||||
@@ -2153,12 +2153,20 @@ instance.web.search.AutoComplete = instance.web.Widget.extend({
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!self.searching) {
|
||||
self.searching = true;
|
||||
return;
|
||||
var search_string = self.get_search_string();
|
||||
if (self.search_string !== search_string) {
|
||||
if (search_string.length) {
|
||||
self.search_string = search_string;
|
||||
setTimeout(function () { self.initiate_search(search_string);}, self.delay);
|
||||
} else {
|
||||
self.close();
|
||||
}
|
||||
}
|
||||
self.search_string = self.get_search_string();
|
||||
});
|
||||
this.$input.on('keypress', function (ev) {
|
||||
self.search_string = self.get_search_string() + String.fromCharCode(ev.which);
|
||||
if (self.search_string.length) {
|
||||
self.searching = true;
|
||||
var search_string = self.search_string;
|
||||
setTimeout(function () { self.initiate_search(search_string);}, self.delay);
|
||||
} else {
|
||||
|
||||
@@ -4393,8 +4393,8 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({
|
||||
|
||||
this.records
|
||||
.bind('add', this.proxy("changed_records"))
|
||||
.bind('edit', this.proxy("changed_records"))
|
||||
.bind('remove', this.proxy("changed_records"));
|
||||
this.on('save:after', this, this.proxy("changed_records"));
|
||||
},
|
||||
start: function () {
|
||||
var ret = this._super();
|
||||
@@ -4411,7 +4411,6 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({
|
||||
if (!this.fields_view || !this.editable()){
|
||||
return true;
|
||||
}
|
||||
var r;
|
||||
if (_.isEmpty(this.records.records)){
|
||||
return true;
|
||||
}
|
||||
@@ -4422,9 +4421,8 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({
|
||||
current_values[field.name] = field.get('value');
|
||||
});
|
||||
var valid = _.every(this.records.records, function(record){
|
||||
r = record;
|
||||
_.each(self.editor.form.fields, function(field){
|
||||
field.set_value(r.attributes[field.name]);
|
||||
field.set_value(record.attributes[field.name]);
|
||||
});
|
||||
return _.every(self.editor.form.fields, function(field){
|
||||
field.process_modifiers();
|
||||
|
||||
@@ -350,6 +350,7 @@ instance.web.ActionManager = instance.web.Widget.extend({
|
||||
search_disable_custom_filters: action.context && action.context.search_disable_custom_filters
|
||||
});
|
||||
action.menu_id = options.action_menu_id;
|
||||
action.context.params = _.extend({ 'action' : action.id }, action.context.params);
|
||||
if (!(type in this)) {
|
||||
console.error("Action manager can't handle action of type " + action.type, action);
|
||||
return $.Deferred().reject();
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
<h1 class="page-header hidden-print">History</h1>
|
||||
<ul class="media-list hidden-print" id="comments-list">
|
||||
<t t-foreach="quotation.message_ids" t-as="message">
|
||||
<li class="media" t-if="message.type <> 'comment' or message.subtype_id">
|
||||
<li class="media" t-if="message.type not in ['comment', 'notification'] or message.subtype_id">
|
||||
<div class="media-body">
|
||||
<img class="media-object pull-left" t-att-src="website.image_url(message.author_id, 'image_small')" style="width: 50px; margin-right: 10px;"/>
|
||||
<div class="media-body">
|
||||
|
||||
Reference in New Issue
Block a user