Skip to content
Permalink
Browse files

[MERGE] forward port branch 12.0 up to 11b1e12

  • Loading branch information...
KangOl committed Mar 25, 2019
2 parents 28a1371 + 11b1e12 commit f00c490be8688d80f211f6755b5ada541eefd602
Showing with 568 additions and 198 deletions.
  1. +1 −2 addons/account/models/account.py
  2. +6 −6 addons/account/models/account_invoice.py
  3. +2 −1 addons/account/report/account_invoice_report.py
  4. +1 −1 addons/auth_signup/data/auth_signup_data.xml
  5. +10 −2 addons/base_iban/models/res_partner_bank.py
  6. +7 −0 addons/crm/models/crm_lead.py
  7. +9 −4 addons/crm/models/crm_team.py
  8. +1 −1 addons/fleet/models/fleet_vehicle_cost.py
  9. +1 −0 addons/hr_holidays/__manifest__.py
  10. +6 −0 addons/hr_holidays/static/scss/hr_leave_mobile.scss
  11. +8 −0 addons/hr_holidays/views/hr_leave_template.xml
  12. +1 −1 addons/hr_holidays/views/hr_leave_views.xml
  13. +1 −1 addons/hr_timesheet/models/hr_timesheet.py
  14. +32 −0 addons/hr_timesheet/tests/test_timesheet.py
  15. +3 −2 addons/l10n_tr/__manifest__.py
  16. +82 −0 addons/l10n_tr/data/res.country.state.csv
  17. +7 −4 addons/mail/models/mail_activity.py
  18. +38 −2 addons/payment_adyen/models/payment.py
  19. +5 −1 addons/payment_stripe/static/src/js/stripe.js
  20. +6 −1 addons/payment_stripe/views/payment_stripe_templates.xml
  21. +3 −3 addons/point_of_sale/views/pos_config_view.xml
  22. +0 −1 addons/product/views/product_template_views.xml
  23. +1 −1 addons/purchase_requisition/models/purchase.py
  24. +2 −1 addons/sale/models/account_invoice.py
  25. +30 −5 addons/sale/models/sale.py
  26. +3 −3 addons/sale/report/sale_report_templates.xml
  27. +1 −1 addons/sale/views/sale_portal_templates.xml
  28. +1 −1 addons/stock/static/src/js/stock_traceability_report_widgets.js
  29. +1 −1 addons/stock/views/stock_picking_views.xml
  30. +1 −1 addons/stock_dropshipping/models/sale.py
  31. +4 −0 addons/stock_picking_batch/report/report_picking_batch.xml
  32. +4 −4 addons/test_mail/tests/test_mail_gateway.py
  33. +10 −10 addons/test_mail/tests/test_mail_message.py
  34. +5 −1 addons/web/static/src/js/views/calendar/calendar_controller.js
  35. +3 −1 addons/web/static/src/js/views/calendar/calendar_renderer.js
  36. +1 −1 addons/web/static/src/xml/base.xml
  37. +13 −1 addons/web_editor/static/src/js/editor/snippets.editor.js
  38. +1 −1 addons/web_editor/static/src/js/editor/transcoder.js
  39. +1 −1 addons/web_editor/static/src/scss/web_editor.common.scss
  40. +1 −4 addons/website_event/controllers/main.py
  41. +4 −0 addons/website_event_sale/controllers/main.py
  42. +4 −0 addons/website_forum/static/src/scss/website_forum.scss
  43. +1 −0 doc/cla/corporate/inspur.md
  44. +11 −0 doc/cla/individual/iledarn.md
  45. +82 −96 doc/webservices/upgrade.rst
  46. +22 −3 odoo/addons/base/models/ir_logging.py
  47. +22 −0 odoo/addons/base/models/res_partner.py
  48. +13 −0 odoo/addons/base/tests/test_translate.py
  49. +95 −27 odoo/service/server.py
  50. +1 −1 odoo/tools/translate.py
@@ -580,8 +580,7 @@ def _get_alias_values(self, alias_name=None):
if self.company_id != self.env.ref('base.main_company'):
alias_name += '-' + str(self.company_id.name)
return {
'alias_defaults': {'type': 'in_invoice'},
'alias_user_id': self.env.user.id,
'alias_defaults': {'type': 'in_invoice', 'company_id': self.company_id.id},
'alias_parent_thread_id': self.id,
'alias_name': re.sub(r'[^\w]+', '-', alias_name)
}
@@ -1889,12 +1889,12 @@ def _prepare_invoice_line(self):
}
return data

@api.model
def create(self, vals):
if vals.get('display_type', self.default_get(['display_type'])['display_type']):
vals.update(price_unit=0, account_id=False, quantity=0)

return super(AccountInvoiceLine, self).create(vals)
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
if vals.get('display_type', self.default_get(['display_type'])['display_type']):
vals.update(price_unit=0, account_id=False, quantity=0)
return super(AccountInvoiceLine, self).create(vals_list)

@api.multi
def write(self, values):
@@ -114,7 +114,8 @@ def _sub_select(self):
ai.partner_bank_id,
SUM ((invoice_type.sign_qty * ail.quantity) / u.factor * u2.factor) AS product_qty,
SUM(ail.price_subtotal_signed * invoice_type.sign) AS price_total,
SUM(ai.amount_total * invoice_type.sign) AS amount_total,
(ai.amount_total * invoice_type.sign) / (SELECT count(*) FROM account_invoice_line l where invoice_id = ai.id) *
count(*) * invoice_type.sign AS amount_total,
SUM(ABS(ail.price_subtotal_signed)) / CASE
WHEN SUM(ail.quantity / u.factor * u2.factor) <> 0::numeric
THEN SUM(ail.quantity / u.factor * u2.factor)
@@ -142,7 +142,7 @@
% set website_url = object.env['ir.config_parameter'].sudo().get_param('web.base.url')
Your Odoo domain is: <b><a href='${website_url}'>${website_url}</a></b><br />
Your sign in email is: <b><a href="/web/login?login=${object.email}" target="_blank">${object.email}</a></b><br /><br />
Never heard of Odoo? It’s a all-in-one business software loved by 3+ million users. It will considerably improve your experience at work and increase your productivity.
Never heard of Odoo? It’s an all-in-one business software loved by 3+ million users. It will considerably improve your experience at work and increase your productivity.
<br /><br />
Have a look at the <a href="https://www.odoo.com/page/tour?utm_source=db&amp;utm_medium=auth" style="color: #875A7B;">Odoo Tour</a> to discover the tool.
<br /><br />
@@ -70,13 +70,21 @@ def get_bban(self):
@api.model
def create(self, vals):
if vals.get('acc_number'):
vals['acc_number'] = pretty_iban(normalize_iban(vals['acc_number']))
try:
validate_iban(vals['acc_number'])
vals['acc_number'] = pretty_iban(normalize_iban(vals['acc_number']))
except ValidationError:
pass
return super(ResPartnerBank, self).create(vals)

@api.multi
def write(self, vals):
if vals.get('acc_number'):
vals['acc_number'] = pretty_iban(normalize_iban(vals['acc_number']))
try:
validate_iban(vals['acc_number'])
vals['acc_number'] = pretty_iban(normalize_iban(vals['acc_number']))
except ValidationError:
pass
return super(ResPartnerBank, self).write(vals)

@api.one
@@ -277,6 +277,13 @@ def _onchange_state(self):
if self.state_id:
self.country_id = self.state_id.country_id.id

@api.onchange('country_id')
def _onchange_country_id(self):
res = {'domain': {'state_id': []}}
if self.country_id:
res['domain']['state_id'] = [('country_id', '=', self.country_id.id)]
return res

# ----------------------------------------
# ORM override (CRUD, fields_view_get, ...)
# ----------------------------------------
@@ -48,13 +48,18 @@ def _compute_unassigned_leads_count(self):
team.unassigned_leads_count = counts.get(team.id, 0)

def _compute_opportunities(self):
opportunity_data = self.env['crm.lead'].read_group([
opportunity_data = self.env['crm.lead'].search([
('team_id', 'in', self.ids),
('probability', '<', 100),
('type', '=', 'opportunity'),
], ['planned_revenue', 'team_id'], ['team_id'])
counts = {datum['team_id'][0]: datum['team_id_count'] for datum in opportunity_data}
amounts = {datum['team_id'][0]: (datum['planned_revenue']) for datum in opportunity_data}
]).read(['planned_revenue', 'team_id'])
counts = {}
amounts = {}
for datum in opportunity_data:
counts.setdefault(datum['team_id'][0], 0)
amounts.setdefault(datum['team_id'][0], 0)
counts[datum['team_id'][0]] += 1
amounts[datum['team_id'][0]] += (datum.get('planned_revenue', 0))
for team in self:
team.opportunities_count = counts.get(team.id, 0)
team.opportunities_amount = amounts.get(team.id, 0)
@@ -277,7 +277,7 @@ def scheduler_manage_contract_expiration(self):
'fleet.mail_act_fleet_contract_to_renew', contract.expiration_date,
user_id=contract.user_id.id)

expired_contracts = self.search([('state', '!=', 'expired'), ('expiration_date', '<',fields.Date.today() )])
expired_contracts = self.search([('state', 'not in', ['expired', 'closed']), ('expiration_date', '<',fields.Date.today() )])
expired_contracts.write({'state': 'expired'})

futur_contracts = self.search([('state', 'not in', ['futur', 'closed']), ('start_date', '>', fields.Date.today())])
@@ -47,6 +47,7 @@
'report/hr_leave_reports.xml',

'views/hr_views.xml',
'views/hr_leave_template.xml',
],
'demo': [
'data/hr_holidays_demo.xml',
@@ -0,0 +1,6 @@
@include media-breakpoint-down(sm) {
.o_hr_holidays_dates {
display: flex;
flex-flow: column;
}
}
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="assets_backend" inherit_id="web.assets_backend">
<xpath expr="link[last()]" position="after">
<link rel="stylesheet" type="text/scss" href="/hr_holidays/static/scss/hr_leave_mobile.scss"/>
</xpath>
</template>
</odoo>
@@ -171,7 +171,7 @@
<div>
<field name="date_from" invisible="1"/>
<field name="date_to" invisible="1"/>
<div class="o_row o_row_readonly">
<div class="o_row o_row_readonly o_hr_holidays_dates">
<field name="request_date_from" class="oe_inline"
attrs="{'readonly': [('state', 'not in', ('draft', 'confirm'))]}"/>
<span class="oe_inline"
@@ -148,7 +148,7 @@ def _timesheet_postprocess_values(self, values):
:return: a dictionary mapping each record id to its corresponding
dictionnary values to write (may be empty).
"""
result = dict.fromkeys(self.ids, dict())
result = {id_: {} for id_ in self.ids}
sudo_self = self.sudo() # this creates only one env for all operation that required sudo()
# (re)compute the amount (depending on unit_amount, employee_id for the cost, and account_id for currency)
if any([field_name in values for field_name in ['unit_amount', 'employee_id', 'account_id']]):
@@ -232,3 +232,35 @@ def test_transfert_project(self):
self.task1.write({
'project_id': False
})

def test_recompute_amount_for_multiple_timesheets(self):
""" Check that amount is recomputed correctly when setting unit_amount for multiple timesheets at once. """
Timesheet = self.env['account.analytic.line']
self.empl_employee.timesheet_cost = 5.0
self.empl_employee2.timesheet_cost = 6.0
# create a timesheet for each employee
timesheet_1 = Timesheet.sudo(self.user_employee).create({
'project_id': self.project_customer.id,
'task_id': self.task1.id,
'name': '/',
'unit_amount': 1,
})
timesheet_2 = Timesheet.sudo(self.user_employee2).create({
'project_id': self.project_customer.id,
'task_id': self.task1.id,
'name': '/',
'unit_amount': 1,
})
timesheets = timesheet_1 + timesheet_2

# increase unit_amount to trigger amount recomputation
timesheets.sudo().write({
'unit_amount': 2,
})

# since timesheet costs are different for both employees, we should get different amounts
self.assertRecordValues(timesheets, [{
'amount': -10.0,
}, {
'amount': -12.0,
}])
@@ -13,8 +13,8 @@
* Sihirbaz sizden hesap planı şablonu, planın kurulacağı şirket, banka hesap
bilgileriniz, ilgili para birimi gibi bilgiler isteyecek.
""",
'author': 'Ahmet Altınışık',
'maintainer':'https://launchpad.net/~openerp-turkey',
'author': 'Ahmet Altınışık, Can Tecim',
'maintainer':'https://launchpad.net/~openerp-turkey, http://www.cantecim.com',
'depends': [
'account',
],
@@ -25,5 +25,6 @@
'data/account_data.xml',
'data/account_tax_template_data.xml',
'data/account_chart_template_data.xml',
'data/res.country.state.csv'
],
}
@@ -0,0 +1,82 @@
"id","country_id:id","name","code"
state_tr_01,base.tr,"Adana","01"
state_tr_02,base.tr,"Adıyaman","02"
state_tr_03,base.tr,"Afyon","03"
state_tr_04,base.tr,"Ağrı","04"
state_tr_05,base.tr,"Amasya","05"
state_tr_06,base.tr,"Ankara","06"
state_tr_07,base.tr,"Antalya","07"
state_tr_08,base.tr,"Artvin","08"
state_tr_09,base.tr,"Aydın","09"
state_tr_10,base.tr,"Balıkesir","10"
state_tr_11,base.tr,"Bilecik","11"
state_tr_12,base.tr,"Bingöl","12"
state_tr_13,base.tr,"Bitlis","13"
state_tr_14,base.tr,"Bolu","14"
state_tr_15,base.tr,"Burdur","15"
state_tr_16,base.tr,"Bursa","16"
state_tr_17,base.tr,"Çanakkale","17"
state_tr_18,base.tr,"Çankırı","18"
state_tr_19,base.tr,"Çorum","19"
state_tr_20,base.tr,"Denizli","20"
state_tr_21,base.tr,"Diyarbakır","21"
state_tr_22,base.tr,"Edirne","22"
state_tr_23,base.tr,"Elazığ","23"
state_tr_24,base.tr,"Erzincan","24"
state_tr_25,base.tr,"Erzurum","25"
state_tr_26,base.tr,"Eskişehir","26"
state_tr_27,base.tr,"Gaziantep","27"
state_tr_28,base.tr,"Giresun","28"
state_tr_29,base.tr,"Gümüşhane","29"
state_tr_30,base.tr,"Hakkari","30"
state_tr_31,base.tr,"Hatay","31"
state_tr_32,base.tr,"Isparta","32"
state_tr_33,base.tr,"İçel","33"
state_tr_34,base.tr,"İstanbul","34"
state_tr_35,base.tr,"İzmir","35"
state_tr_36,base.tr,"Kars","36"
state_tr_37,base.tr,"Kastamonu","37"
state_tr_38,base.tr,"Kayseri","38"
state_tr_39,base.tr,"Kırklareli","39"
state_tr_40,base.tr,"Kırşehir","40"
state_tr_41,base.tr,"Kocaeli","41"
state_tr_42,base.tr,"Konya","42"
state_tr_43,base.tr,"Kütahya","43"
state_tr_44,base.tr,"Malatya","44"
state_tr_45,base.tr,"Manisa","45"
state_tr_46,base.tr,"K.maraş","46"
state_tr_47,base.tr,"Mardin","47"
state_tr_48,base.tr,"Muğla","48"
state_tr_49,base.tr,"Muş","49"
state_tr_50,base.tr,"Nevşehir","50"
state_tr_51,base.tr,"Niğde","51"
state_tr_52,base.tr,"Ordu","52"
state_tr_53,base.tr,"Rize","53"
state_tr_54,base.tr,"Sakarya","54"
state_tr_55,base.tr,"Samsun","55"
state_tr_56,base.tr,"Siirt","56"
state_tr_57,base.tr,"Sinop","57"
state_tr_58,base.tr,"Sivas","58"
state_tr_59,base.tr,"Tekirdağ","59"
state_tr_60,base.tr,"Tokat","60"
state_tr_61,base.tr,"Trabzon","61"
state_tr_62,base.tr,"Tunceli","62"
state_tr_63,base.tr,"Şanlıurfa","63"
state_tr_64,base.tr,"Uşak","64"
state_tr_65,base.tr,"Van","65"
state_tr_66,base.tr,"Yozgat","66"
state_tr_67,base.tr,"Zonguldak","67"
state_tr_68,base.tr,"Aksaray","68"
state_tr_69,base.tr,"Bayburt","69"
state_tr_70,base.tr,"Karaman","70"
state_tr_71,base.tr,"Kırıkkale","71"
state_tr_72,base.tr,"Batman","72"
state_tr_73,base.tr,"Şırnak","73"
state_tr_74,base.tr,"Bartın","74"
state_tr_75,base.tr,"Ardahan","75"
state_tr_76,base.tr,"Iğdır","76"
state_tr_77,base.tr,"Yalova","77"
state_tr_78,base.tr,"Karabük","78"
state_tr_79,base.tr,"Kilis","79"
state_tr_80,base.tr,"Osmaniye","80"
state_tr_81,base.tr,"Düzce","81"
@@ -433,19 +433,21 @@ def get_activity_data(self, res_model, domain):
activity_domain.append(('res_id', 'in', res.ids))
grouped_activities = self.env['mail.activity'].read_group(
activity_domain,
['res_id', 'activity_type_id', 'res_name:max(res_name)', 'ids:array_agg(id)', 'date_deadline:min(date_deadline)'],
['res_id', 'activity_type_id', 'ids:array_agg(id)', 'date_deadline:min(date_deadline)'],
['res_id', 'activity_type_id'],
lazy=False)
# filter out unreadable records
if not domain:
res_ids = tuple(a['res_id'] for a in grouped_activities)
res = self.env[res_model].search([('id', 'in', res_ids)])
grouped_activities = [a for a in grouped_activities if a['res_id'] in res.ids]
activity_type_ids = self.env['mail.activity.type']
res_id_to_name = {}
res_id_to_deadline = {}
activity_data = defaultdict(dict)
for group in grouped_activities:
res_id = group['res_id']
res_name = group['res_name']
activity_type_id = group['activity_type_id'][0]
activity_type_ids |= self.env['mail.activity.type'].browse(activity_type_id) # we will get the name when reading mail_template_ids
res_id_to_name[res_id] = res_name
res_id_to_deadline[res_id] = group['date_deadline'] if (res_id not in res_id_to_deadline or group['date_deadline'] < res_id_to_deadline[res_id]) else res_id_to_deadline[res_id]
state = self._compute_state_from_date(group['date_deadline'], self.user_id.sudo().tz)
activity_data[res_id][activity_type_id] = {
@@ -455,6 +457,7 @@ def get_activity_data(self, res_model, domain):
'o_closest_deadline': group['date_deadline'],
}
res_ids_sorted = sorted(res_id_to_deadline, key=lambda item: res_id_to_deadline[item])
res_id_to_name = dict(self.env[res_model].browse(res_ids_sorted).name_get())
activity_type_infos = []
for elem in sorted(activity_type_ids, key=lambda item: item.sequence):
mail_template_info = []
Oops, something went wrong.

0 comments on commit f00c490

Please sign in to comment.
You can’t perform that action at this time.