diff options
| author | Christophe Simonis <chs@odoo.com> | 2018-06-15 13:27:17 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2018-06-15 13:27:27 +0200 |
| commit | 73652a0b196b51ec1f9a27880d0b398fb79bfca3 (patch) | |
| tree | 04e741fefdbb859dffa66a4037da7777ea980476 | |
| parent | 8a03563269c3dc55c9c7157494af51e2485f1a14 (diff) | |
| parent | 50860317ccd2c1b44f873598858a3cff87fa7ea6 (diff) | |
[MERGE] forward port branch saas-11.3 up to 50860317ccd
Note: 1aacc962620982528a3dfc90d2c1dd0027359375 has been ignored and will
be forward-ported later
129 files changed, 1227 insertions, 526 deletions
diff --git a/addons/account/i18n/ru.po b/addons/account/i18n/ru.po index a3f724f574f..71955ffdde2 100644 --- a/addons/account/i18n/ru.po +++ b/addons/account/i18n/ru.po @@ -35,13 +35,14 @@ # Yuriy Ney <k_wizard@mail.ru>, 2017 # Yuriy Ney <kwizardn@gmail.com>, 2018 # sergeiruzkiicode <sergei.ruzki@icode.by>, 2018 +# Илья Пономарев <horochiy92@gmail.com>, 2018 msgid "" msgstr "" "Project-Id-Version: Odoo Server saas~11.2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-03-22 14:10+0000\n" "PO-Revision-Date: 2018-03-22 14:10+0000\n" -"Last-Translator: sergeiruzkiicode <sergei.ruzki@icode.by>, 2018\n" +"Last-Translator: Илья Пономарев <horochiy92@gmail.com>, 2018\n" "Language-Team: Russian (https://www.transifex.com/odoo/teams/41243/ru/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -4790,12 +4791,12 @@ msgstr "" #. module: account #: model:ir.ui.view,arch_db:account.res_config_settings_view_form msgid "Import your bank statements in CAMT.053" -msgstr "" +msgstr "Импорт банковской выписки в формате CAMT.053" #. module: account #: model:ir.ui.view,arch_db:account.res_config_settings_view_form msgid "Import your bank statements in CSV" -msgstr "" +msgstr "Импорт Банковской Выписки в формате CSV" #. module: account #: model:ir.ui.view,arch_db:account.res_config_settings_view_form diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index ebc430f0603..d2555241023 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -427,7 +427,7 @@ class AccountInvoice(models.Model): """ computes the prefix of the number that will be assigned to the first invoice/bill/refund of a journal, in order to let the user manually change it. """ - if not self.env.user._is_admin(): + if not self.env.user._is_system(): for invoice in self: invoice.sequence_number_next_prefix = False invoice.sequence_number_next = '' @@ -1629,6 +1629,13 @@ class AccountInvoiceLine(models.Model): return accounts['income'] return accounts['expense'] + def _set_currency(self): + company = self.invoice_id.company_id + currency = self.invoice_id.currency_id + if company and currency: + if company.currency_id != currency: + self.price_unit = self.price_unit * currency.with_context(dict(self._context or {}, date=self.invoice_id.date_invoice)).rate + def _set_taxes(self): """ Used in on_change to set taxes and price.""" if self.invoice_id.type in ('out_invoice', 'out_refund'): @@ -1647,8 +1654,10 @@ class AccountInvoiceLine(models.Model): prec = self.env['decimal.precision'].precision_get('Product Price') if not self.price_unit or float_compare(self.price_unit, self.product_id.standard_price, precision_digits=prec) == 0: self.price_unit = fix_price(self.product_id.standard_price, taxes, fp_taxes) + self._set_currency() else: self.price_unit = fix_price(self.product_id.lst_price, taxes, fp_taxes) + self._set_currency() @api.onchange('product_id') def _onchange_product_id(self): @@ -1697,8 +1706,6 @@ class AccountInvoiceLine(models.Model): domain['uom_id'] = [('category_id', '=', product.uom_id.category_id.id)] if company and currency: - if company.currency_id != currency: - self.price_unit = self.price_unit * currency.with_context(dict(self._context or {}, date=self.invoice_id.date_invoice)).rate if self.uom_id and self.uom_id.id != product.uom_id.id: self.price_unit = product.uom_id._compute_price(self.price_unit, self.uom_id) diff --git a/addons/account/models/res_config_settings.py b/addons/account/models/res_config_settings.py index 601bda4541e..7282714202b 100644 --- a/addons/account/models/res_config_settings.py +++ b/addons/account/models/res_config_settings.py @@ -14,7 +14,7 @@ class ResConfigSettings(models.TransientModel): 'account.journal', related='company_id.currency_exchange_journal_id', string="Exchange Gain or Loss Journal", - domain=[('type', '=', 'general')], + domain="[('company_id', '=', company_id), ('type', '=', 'general')]", help='The accounting journal where automatic exchange differences will be registered') has_chart_of_accounts = fields.Boolean(compute='_compute_has_chart_of_accounts', string='Company has a chart of accounts') chart_template_id = fields.Many2one('account.chart.template', string='Template', diff --git a/addons/account/views/account_journal_dashboard_view.xml b/addons/account/views/account_journal_dashboard_view.xml index fe5d69d5eb9..0c27c843252 100644 --- a/addons/account/views/account_journal_dashboard_view.xml +++ b/addons/account/views/account_journal_dashboard_view.xml @@ -248,14 +248,16 @@ <span><t t-esc="dashboard.account_balance"/></span> </div> </div> - <div class="row" name="latest_statement" t-if="dashboard.last_balance != dashboard.account_balance"> - <div class="col-xs-7"> + <t t-if="dashboard.last_balance != dashboard.account_balance"> + <div class="row" name="latest_statement"> + <div class="col-xs-7"> <span title="Latest Statement">Latest Statement</span> - </div> - <div class="col-xs-5 text-right"> + </div> + <div class="col-xs-5 text-right"> <span><t t-esc="dashboard.last_balance"/></span> + </div> </div> - </div> + </t> </div> </t> <t t-name="JournalBodySalePurchase" id="account.JournalBodySalePurchase"> diff --git a/addons/account/views/report_journal.xml b/addons/account/views/report_journal.xml index 06dbab99ae4..c642b89347a 100644 --- a/addons/account/views/report_journal.xml +++ b/addons/account/views/report_journal.xml @@ -50,7 +50,7 @@ <td><span t-field="aml.date"/></td> <td><span t-field="aml.account_id.code"/></td> <td><span t-esc="aml.sudo().partner_id and aml.sudo().partner_id.name and aml.sudo().partner_id.name[:23] or ''"/></td> - <td><span t-esc="aml.name[:35]"/></td> + <td><span t-esc="aml.name and aml.name[:35]"/></td> <td><span t-esc="aml.debit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></td> <td><span t-esc="aml.credit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></td> <td t-if="data['form']['amount_currency'] and aml.amount_currency"> diff --git a/addons/account_bank_statement_import/account_bank_statement_import.py b/addons/account_bank_statement_import/account_bank_statement_import.py index 45c285a5d51..6fb102104c5 100644 --- a/addons/account_bank_statement_import/account_bank_statement_import.py +++ b/addons/account_bank_statement_import/account_bank_statement_import.py @@ -50,7 +50,11 @@ class AccountBankStatementImport(models.TransientModel): # Create the bank statements statement_ids, notifications = self._create_bank_statements(stmts_vals) # Now that the import worked out, set it as the bank_statements_source of the journal - journal.bank_statements_source = 'file_import' + if journal.bank_statements_source != 'file_import': + # Use sudo() because only 'account.group_account_manager' + # has write access on 'account.journal', but 'account.group_account_user' + # must be able to import bank statement files + journal.sudo().bank_statements_source = 'file_import' # Finally dispatch to reconciliation interface action = self.env.ref('account.action_bank_reconcile_bank_statements') return { diff --git a/addons/account_check_printing/i18n/tr.po b/addons/account_check_printing/i18n/tr.po index a57d2d5029c..f22ebc6235d 100644 --- a/addons/account_check_printing/i18n/tr.po +++ b/addons/account_check_printing/i18n/tr.po @@ -8,13 +8,14 @@ # Ayhan KIZILTAN <akiziltan76@hotmail.com>, 2018 # Martin Trigaux, 2018 # Alexander B. <road2monstercat@gmail.com>, 2018 +# Umur Akın <umura@projetgrup.com>, 2018 msgid "" msgstr "" "Project-Id-Version: Odoo Server saas~11.2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-03-22 14:10+0000\n" "PO-Revision-Date: 2018-03-22 14:10+0000\n" -"Last-Translator: Alexander B. <road2monstercat@gmail.com>, 2018\n" +"Last-Translator: Umur Akın <umura@projetgrup.com>, 2018\n" "Language-Team: Turkish (https://www.transifex.com/odoo/teams/41243/tr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -333,6 +334,8 @@ msgid "" "The ISO country code in two chars. \n" "You can use this field for quick search." msgstr "" +"İki karakterde ISO ülke kodu.\n" +"Hızlı arama için bu alanı kullanabilirsiniz." #. module: account_check_printing #: code:addons/account_check_printing/models/account_journal.py:26 diff --git a/addons/base_address_city/models/res_partner.py b/addons/base_address_city/models/res_partner.py index c35430d1f92..07c42694ef1 100644 --- a/addons/base_address_city/models/res_partner.py +++ b/addons/base_address_city/models/res_partner.py @@ -10,7 +10,7 @@ from odoo.tools.translate import _ class Partner(models.Model): _inherit = 'res.partner' - country_enforce_cities = fields.Boolean(related='country_id.enforce_cities') + country_enforce_cities = fields.Boolean(related='country_id.enforce_cities', readonly=True) city_id = fields.Many2one('res.city', string='City of Address') @api.onchange('city_id') diff --git a/addons/board/static/src/js/favorite_menu.js b/addons/board/static/src/js/favorite_menu.js index 701ebef2801..112b4d634fa 100644 --- a/addons/board/static/src/js/favorite_menu.js +++ b/addons/board/static/src/js/favorite_menu.js @@ -99,7 +99,10 @@ FavoriteMenu.include({ }) .then(function (r) { if (r) { - self.do_notify(_.str.sprintf(_t("'%s' added to dashboard"), name), ''); + self.do_notify( + _.str.sprintf(_t("'%s' added to dashboard"), name), + _t('Please refresh your browser for the changes to take effect.') + ); } else { self.do_warn(_t("Could not add filter to dashboard")); } diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py index 26f6629158d..3ec21c7eb1e 100644 --- a/addons/crm/models/crm_lead.py +++ b/addons/crm/models/crm_lead.py @@ -243,6 +243,8 @@ class Lead(models.Model): @api.model def _onchange_user_values(self, user_id): """ returns new values when user_id has changed """ + if not user_id: + return {} if user_id and self._context.get('team_id'): team = self.env['crm.team'].browse(self._context['team_id']) if user_id in team.member_ids.ids: diff --git a/addons/event/i18n/tr.po b/addons/event/i18n/tr.po index 67b6aeb2e6f..90c8084cbdc 100644 --- a/addons/event/i18n/tr.po +++ b/addons/event/i18n/tr.po @@ -1551,7 +1551,7 @@ msgstr "" #. module: event #: model:ir.model,name:event.model_event_confirm msgid "event.confirm" -msgstr "" +msgstr "event.confirm" #. module: event #: code:addons/event/models/event.py:503 diff --git a/addons/event/models/event.py b/addons/event/models/event.py index 491459b135a..1c2189a2d12 100644 --- a/addons/event/models/event.py +++ b/addons/event/models/event.py @@ -444,9 +444,14 @@ class EventRegistration(models.Model): @api.multi def message_get_suggested_recipients(self): recipients = super(EventRegistration, self).message_get_suggested_recipients() + public_users = self.env['res.users'].sudo() + public_groups = self.env.ref("base.group_public", raise_if_not_found=False) + if public_groups: + public_users = public_groups.sudo().with_context(active_test=False).mapped("users") try: for attendee in self: - if attendee.partner_id: + is_public = attendee.sudo().with_context(active_test=False).partner_id.user_ids in public_users if public_users else False + if attendee.partner_id and not is_public: attendee._message_add_suggested_recipient(recipients, partner=attendee.partner_id, reason=_('Customer')) elif attendee.email: attendee._message_add_suggested_recipient(recipients, email=attendee.email, reason=_('Customer Email')) diff --git a/addons/event/models/res_partner.py b/addons/event/models/res_partner.py index e91773c8fee..03934562824 100644 --- a/addons/event/models/res_partner.py +++ b/addons/event/models/res_partner.py @@ -10,6 +10,8 @@ class ResPartner(models.Model): event_count = fields.Integer("Events Count", compute='_compute_event_count', help="Number of events the partner has participated.") def _compute_event_count(self): + if not self.user_has_groups('event.group_event_user'): + return for partner in self: partner.event_count = self.env['event.event'].search_count([('registration_ids.partner_id', 'child_of', partner.ids)]) diff --git a/addons/event/report/event_event_templates.xml b/addons/event/report/event_event_templates.xml index 76b64138f44..8490dc4aaca 100644 --- a/addons/event/report/event_event_templates.xml +++ b/addons/event/report/event_event_templates.xml @@ -18,7 +18,7 @@ <img t-att-src="'data:image/png;base64,%s' % to_text(o.event_id.organizer_id.company_id.logo_web)" style="max-height:1cm; max-width:4cm;"/> </span> <h5 t-field="o.event_id.name"/> - <h5>( <i class="fa fa-clock-o"></i> <span itemprop="startDate" t-field="o.event_id.date_begin" t-options='{"hide_seconds": True}'> </span> <i>to</i> <span itemprop="endDate" t-field="o.event_id.date_end" t-options='{"hide_seconds": True}'> </span> )</h5> + <h5>( <i class="fa fa-clock-o"></i> <span itemprop="startDate" t-field="o.event_id.with_context(tz=o.event_id.date_tz).date_begin" t-options='{"hide_seconds": True}'> </span> <i>to</i> <span itemprop="endDate" t-field="o.event_id.with_context(tz=o.event_id.date_tz).date_end" t-options='{"hide_seconds": True}'> </span> )</h5> </div> <div class="row"> <div class="col-xs-12 text-center" id="o_event_name"> diff --git a/addons/event/views/res_partner_views.xml b/addons/event/views/res_partner_views.xml index 59d096efcd1..22aeba8686a 100644 --- a/addons/event/views/res_partner_views.xml +++ b/addons/event/views/res_partner_views.xml @@ -11,6 +11,7 @@ <button class="oe_stat_button" type="object" icon="fa-ticket" + groups="event.group_event_user" name="action_event_view" attrs="{'invisible': [('event_count','=', 0)]}"> <field string="Events" name="event_count" widget="statinfo"/> </button> diff --git a/addons/event_sale/i18n/tr.po b/addons/event_sale/i18n/tr.po index 1cf54f0f8c6..ab1b8afb73f 100644 --- a/addons/event_sale/i18n/tr.po +++ b/addons/event_sale/i18n/tr.po @@ -455,7 +455,7 @@ msgstr "Lütfen kayıtlarla ilgili ayrıntıları veriniz." #. module: event_sale #: model:ir.model,name:event_sale.model_registration_editor msgid "registration.editor" -msgstr "" +msgstr "registration.editor" #. module: event_sale #: model:ir.model,name:event_sale.model_registration_editor_line diff --git a/addons/fleet/i18n/tr.po b/addons/fleet/i18n/tr.po index 6986a11fd02..d707676ed82 100644 --- a/addons/fleet/i18n/tr.po +++ b/addons/fleet/i18n/tr.po @@ -158,6 +158,8 @@ msgstr "Sözleşmenin hala geçerli olup olmadığını seçin" msgid "" "Choose whether the service refer to contracts, vehicle services or both" msgstr "" +"Hizmetin sözleşmelerle mi, araç hizmetleriyle mi ya da her ikisiyle de mi " +"ilgili olduğunu seçin" #. module: fleet #: model:ir.ui.view,arch_db:fleet.fleet_vehicle_log_contract_view_form diff --git a/addons/google_calendar/i18n/tr.po b/addons/google_calendar/i18n/tr.po index 13557b095b7..ebf3cda9fcf 100644 --- a/addons/google_calendar/i18n/tr.po +++ b/addons/google_calendar/i18n/tr.po @@ -292,7 +292,7 @@ msgstr "Tokenınız geçersiz ya da iptal edilmiş!" #. module: google_calendar #: model:ir.model,name:google_calendar.model_google_calendar msgid "google.calendar" -msgstr "" +msgstr "google.calendar" #. module: google_calendar #: model:ir.model,name:google_calendar.model_res_config_settings diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index 995a7252a92..1a97029e4e0 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -92,7 +92,7 @@ class HolidaysRequest(models.Model): help='Number of hours of the leave request according to your working schedule.') meeting_id = fields.Many2one('calendar.event', string='Meeting') - parent_id = fields.Many2one('hr.leave', string='Parent') + parent_id = fields.Many2one('hr.leave', string='Parent', copy=False) linked_request_ids = fields.One2many('hr.leave', 'parent_id', string='Linked Requests') department_id = fields.Many2one('hr.department', string='Department', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) category_id = fields.Many2one('hr.employee.category', string='Employee Tag', readonly=True, diff --git a/addons/hr_recruitment/i18n/pt_BR.po b/addons/hr_recruitment/i18n/pt_BR.po index f313ca3b50e..1e3d3e4a631 100644 --- a/addons/hr_recruitment/i18n/pt_BR.po +++ b/addons/hr_recruitment/i18n/pt_BR.po @@ -12,13 +12,14 @@ # danimaribeiro <danimaribeiro@gmail.com>, 2016 # Adriel Kotviski <kotviski@gmail.com>, 2016 # Silmar <pinheirosilmar@gmail.com>, 2017 +# Thiago Alves Cavalcante <tkramer.tk@gmail.com>, 2018 msgid "" msgstr "" "Project-Id-Version: Odoo Server saas~11.2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-03-22 14:10+0000\n" "PO-Revision-Date: 2018-03-22 14:10+0000\n" -"Last-Translator: Silmar <pinheirosilmar@gmail.com>, 2017\n" +"Last-Translator: Thiago Alves Cavalcante <tkramer.tk@gmail.com>, 2018\n" "Language-Team: Portuguese (Brazil) (https://www.transifex.com/odoo/teams/41243/pt_BR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -414,7 +415,7 @@ msgstr "<span class=\"o_stat_text\">Rastreadores</span>" #. module: hr_recruitment #: model:ir.ui.view,arch_db:hr_recruitment.view_hr_recruitment_stage_kanban msgid "<span>Folded in Recruitment Pipe: </span>" -msgstr "" +msgstr "Dobrado na Lista de Recrutamento" #. module: hr_recruitment #: model:ir.model.fields,help:hr_recruitment.field_hr_job__alias_defaults @@ -484,7 +485,7 @@ msgstr "Modelo Apelidado" #. module: hr_recruitment #: model:ir.ui.menu,name:hr_recruitment.menu_crm_case_categ_all_app msgid "All Applications" -msgstr "" +msgstr "Todas as aplicações" #. module: hr_recruitment #: model:ir.model,name:hr_recruitment.model_hr_applicant @@ -608,7 +609,7 @@ msgstr "Anexos" #. module: hr_recruitment #: model:ir.model.fields,field_description:hr_recruitment.field_hr_recruitment_stage__template_id msgid "Automated Email" -msgstr "" +msgstr "E-mail Automatizado" #. module: hr_recruitment #: model:ir.model.fields,field_description:hr_recruitment.field_hr_applicant__availability @@ -650,7 +651,7 @@ msgstr "Categoria de candidato" #: code:addons/hr_recruitment/static/src/js/tour.js:16 #, python-format msgid "Click here to create a new job position." -msgstr "" +msgstr "Clique aqui para criar um novo cargo." #. module: hr_recruitment #: model:ir.model.fields,field_description:hr_recruitment.field_hr_applicant__date_closed @@ -722,7 +723,7 @@ msgstr "Criar Funcionário" #: model:ir.actions.act_window,name:hr_recruitment.create_job_simple #: model:ir.ui.view,arch_db:hr_recruitment.hr_job_simple_form msgid "Create a Job Position" -msgstr "" +msgstr "Criar um Cargo" #. module: hr_recruitment #: model:ir.ui.view,arch_db:hr_recruitment.hr_recruitment_source_tree @@ -915,7 +916,7 @@ msgstr "Apelido de E-mail" #. module: hr_recruitment #: model:ir.ui.view,arch_db:hr_recruitment.hr_job_survey msgid "Email alias" -msgstr "" +msgstr "Apelido de email" #. module: hr_recruitment #: model:ir.model.fields,help:hr_recruitment.field_hr_job__alias_id @@ -1039,7 +1040,7 @@ msgstr "Departamento de RH" #. module: hr_recruitment #: model:ir.model.fields,field_description:hr_recruitment.field_hr_job__hr_responsible_id msgid "HR Responsible" -msgstr "" +msgstr "Responsável do RH" #. module: hr_recruitment #: model:ir.ui.view,arch_db:hr_recruitment.view_hr_job_kanban @@ -1091,7 +1092,7 @@ msgstr "Qualificação Inicial" #: model:ir.model.fields,field_description:hr_recruitment.field_res_config_settings__module_hr_recruitment_survey #: model:ir.ui.view,arch_db:hr_recruitment.res_config_settings_view_form msgid "Interview Forms" -msgstr "" +msgstr "Formulários de Entrevista" #. module: hr_recruitment #: code:addons/hr_recruitment/models/hr_job.py:94 @@ -1104,12 +1105,12 @@ msgstr "Trabalho" #. module: hr_recruitment #: model:mail.template,subject:hr_recruitment.email_template_data_applicant_congratulations msgid "Job Application Confirmation: ${object.job_id.name | safe}" -msgstr "" +msgstr "Confirmação de pedido de emprego: ${object.job_id.name | safe}" #. module: hr_recruitment #: model:ir.ui.view,arch_db:hr_recruitment.crm_case_pivot_view_job msgid "Job Applications" -msgstr "" +msgstr "Solicitações de emprego" #. module: hr_recruitment #: model:utm.campaign,name:hr_recruitment.utm_campaign_job @@ -1152,12 +1153,12 @@ msgstr "Cargos" #. module: hr_recruitment #: model:ir.ui.view,arch_db:hr_recruitment.res_config_settings_view_form msgid "Job Posting" -msgstr "" +msgstr "Anúncio de emprego" #. module: hr_recruitment #: model:ir.model.fields,field_description:hr_recruitment.field_hr_recruitment_stage__job_id msgid "Job Specific" -msgstr "" +msgstr "Especificação de trabalho" #. module: hr_recruitment #: model:ir.ui.view,arch_db:hr_recruitment.hr_applicant_view_search @@ -1228,7 +1229,7 @@ msgstr "" #, python-format msgid "" "Let's have a look at the <b>applications pipeline</b> for this job position." -msgstr "" +msgstr "Vamos dar uma olhada na <b>lista de exigências</b> para este cargo. " #. module: hr_recruitment #: model:res.groups,name:hr_recruitment.group_hr_recruitment_manager diff --git a/addons/hr_recruitment/views/hr_job_views.xml b/addons/hr_recruitment/views/hr_job_views.xml index 2311188baed..201d58970cf 100644 --- a/addons/hr_recruitment/views/hr_job_views.xml +++ b/addons/hr_recruitment/views/hr_job_views.xml @@ -23,7 +23,6 @@ <field name="manager_id"/> <field name="state"/> <field name="user_id"/> - <field name="documents_count"/> <templates> <t t-name="kanban-box"> <div t-attf-class="#{kanban_color(record.color.raw_value)}"> @@ -49,7 +48,6 @@ <div class="o_recruitment_kanban_box o_kanban_primary_bottom bottom_block"> <a name="action_get_attachment_tree_view" type="object"> <span title='Documents'><i class='fa fa-book'/> - <t t-esc="record.documents_count.raw_value"/> </span> </a> </div> diff --git a/addons/hr_recruitment_survey/i18n/pt_BR.po b/addons/hr_recruitment_survey/i18n/pt_BR.po index 270f1dc87bf..f12f2ac4c2b 100644 --- a/addons/hr_recruitment_survey/i18n/pt_BR.po +++ b/addons/hr_recruitment_survey/i18n/pt_BR.po @@ -5,17 +5,18 @@ # Translators: # grazziano <gra.negocia@gmail.com>, 2016 # Clemilton Clementino <clemylton@hotmail.com>, 2016 -# Martin Trigaux <mat@odoo.com>, 2016 +# Martin Trigaux, 2016 # Mateus Lopes <mateus1@gmail.com>, 2016 # danimaribeiro <danimaribeiro@gmail.com>, 2016 # Rodrigo de Almeida Sottomaior Macedo <rmsolucoeseminformatic4@gmail.com>, 2016 +# Thiago Alves Cavalcante <tkramer.tk@gmail.com>, 2018 msgid "" msgstr "" -"Project-Id-Version: Odoo Server 10.saas~18\n" +"Project-Id-Version: Odoo Server saas~11.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-09-20 09:53+0000\n" -"PO-Revision-Date: 2017-09-20 09:53+0000\n" -"Last-Translator: Rodrigo de Almeida Sottomaior Macedo <rmsolucoeseminformatic4@gmail.com>, 2016\n" +"POT-Creation-Date: 2018-03-22 14:10+0000\n" +"PO-Revision-Date: 2018-03-22 14:10+0000\n" +"Last-Translator: Thiago Alves Cavalcante <tkramer.tk@gmail.com>, 2018\n" "Language-Team: Portuguese (Brazil) (https://www.transifex.com/odoo/teams/41243/pt_BR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -102,8 +103,8 @@ msgid "Basic information" msgstr "Informações básicas" #. module: hr_recruitment_survey -#: model:ir.model.fields,help:hr_recruitment_survey.field_hr_applicant_survey_id -#: model:ir.model.fields,help:hr_recruitment_survey.field_hr_job_survey_id +#: model:ir.model.fields,help:hr_recruitment_survey.field_hr_applicant__survey_id +#: model:ir.model.fields,help:hr_recruitment_survey.field_hr_job__survey_id msgid "" "Choose an interview form for this job position and you will be able to " "print/answer this interview from all applicants who apply for this job" @@ -201,7 +202,7 @@ msgid "Important" msgstr "Importante" #. module: hr_recruitment_survey -#: model:ir.model.fields,field_description:hr_recruitment_survey.field_hr_job_survey_id +#: model:ir.model.fields,field_description:hr_recruitment_survey.field_hr_job__survey_id #: model:ir.ui.view,arch_db:hr_recruitment_survey.view_hr_job_kanban_inherit msgid "Interview Form" msgstr "Formulário de Entrevista" @@ -209,7 +210,7 @@ msgstr "Formulário de Entrevista" #. module: hr_recruitment_survey #: model:ir.ui.view,arch_db:hr_recruitment_survey.res_config_settings_view_form msgid "Interview Forms" -msgstr "" +msgstr "Formulários de Entrevista" #. module: hr_recruitment_survey #: model:ir.model,name:hr_recruitment_survey.model_hr_job @@ -282,7 +283,7 @@ msgid "Regular meetings" msgstr "Reuniões regulares" #. module: hr_recruitment_survey -#: model:ir.model.fields,field_description:hr_recruitment_survey.field_hr_applicant_response_id +#: model:ir.model.fields,field_description:hr_recruitment_survey.field_hr_applicant__response_id msgid "Response" msgstr "Resposta" @@ -297,7 +298,7 @@ msgid "State of the art technology" msgstr "Estado da Arte da Tecnologia" #. module: hr_recruitment_survey -#: model:ir.model.fields,field_description:hr_recruitment_survey.field_hr_applicant_survey_id +#: model:ir.model.fields,field_description:hr_recruitment_survey.field_hr_applicant__survey_id msgid "Survey" msgstr "Pesquisa" diff --git a/addons/hr_timesheet_attendance/i18n/tr.po b/addons/hr_timesheet_attendance/i18n/tr.po index 5588db3e311..8865465e6d4 100644 --- a/addons/hr_timesheet_attendance/i18n/tr.po +++ b/addons/hr_timesheet_attendance/i18n/tr.po @@ -86,7 +86,7 @@ msgstr "Kullanıcı" #. module: hr_timesheet_attendance #: model:ir.model,name:hr_timesheet_attendance.model_hr_timesheet_attendance_report msgid "hr.timesheet.attendance.report" -msgstr "" +msgstr "hr.timesheet.attendance.report" #. module: hr_timesheet_attendance #: model:ir.ui.view,arch_db:hr_timesheet_attendance.view_hr_timesheet_attendance_report_pivot diff --git a/addons/iap/i18n/tr.po b/addons/iap/i18n/tr.po index 0a841f08079..7a9b5661000 100644 --- a/addons/iap/i18n/tr.po +++ b/addons/iap/i18n/tr.po @@ -130,4 +130,4 @@ msgstr "Hizmet Adı" #. module: iap #: model:ir.model,name:iap.model_iap_account msgid "iap.account" -msgstr "" +msgstr "iap.account" diff --git a/addons/im_livechat/i18n/tr.po b/addons/im_livechat/i18n/tr.po index 996f2a4e8a3..7b440f587db 100644 --- a/addons/im_livechat/i18n/tr.po +++ b/addons/im_livechat/i18n/tr.po @@ -64,6 +64,11 @@ msgid "" "country, GeoIP must be installed on your server, otherwise, the countries of" " the rule will not be taken into account.</span>" msgstr "" +"<span>Canlı destek kanalınız için kuralları tanımlayın. Belirtilen URL ve " +"ülke için aksiyon tanımlayabilir (desteği gizle, desteği otomatik aç, veya " +"sadece butonu göster)<br/>Ülkeyi tanımlayabilmek için, GeoIP'nin sunucuda " +"yüklenmiş olması gerekmektedir, aksi durumda ülke ile ilgili kurallar " +"geçersiz olacaktır.</span>" #. module: im_livechat #: model:ir.model.fields,field_description:im_livechat.field_im_livechat_channel_rule__action diff --git a/addons/l10n_nl/data/account_tax_template.xml b/addons/l10n_nl/data/account_tax_template.xml index c26dc9a8345..e9b937b98f5 100644 --- a/addons/l10n_nl/data/account_tax_template.xml +++ b/addons/l10n_nl/data/account_tax_template.xml @@ -593,7 +593,7 @@ <field name="refund_account_id" ref="vat_refund_h_non_eu"/> <field name="account_id" ref="vat_refund_h_non_eu"/> <field name="type_tax_use">none</field> - <field name="tag_ids" eval="[(6,0,[ref('tag_nl_34')])]"/> + <field name="tag_ids" eval="[(6,0,[ref('tag_nl_33')])]"/> <field name="tax_group_id" ref="tax_group_21_niet_eu"/> </record> <record id="btw_E2" model="account.tax.template"> @@ -735,7 +735,7 @@ <field name="refund_account_id" ref="vat_refund_h_d_non_eu"/> <field name="account_id" ref="vat_refund_h_d_non_eu"/> <field name="type_tax_use">none</field> - <field name="tag_ids" eval="[(6,0,[ref('tag_nl_34')])]"/> + <field name="tag_ids" eval="[(6,0,[ref('tag_nl_33')])]"/> <field name="tax_group_id" ref="tax_group_21_niet_eu"/> </record> <record id="btw_E2_d" model="account.tax.template"> diff --git a/addons/link_tracker/i18n/tr.po b/addons/link_tracker/i18n/tr.po index 21f4defb143..325781ee040 100644 --- a/addons/link_tracker/i18n/tr.po +++ b/addons/link_tracker/i18n/tr.po @@ -228,19 +228,19 @@ msgstr "Website Link Tıklamaları" #. module: link_tracker #: model:ir.model,name:link_tracker.model_link_tracker msgid "link.tracker" -msgstr "" +msgstr "link.tracker" #. module: link_tracker #: model:ir.model,name:link_tracker.model_link_tracker_click msgid "link.tracker.click" -msgstr "" +msgstr "link.tracker.click" #. module: link_tracker #: model:ir.model,name:link_tracker.model_link_tracker_code msgid "link.tracker.code" -msgstr "" +msgstr "link.tracker.code" #. module: link_tracker #: model:ir.actions.act_window,name:link_tracker.action_link_tracker_stats msgid "link.tracker.form.graph.action" -msgstr "" +msgstr "link.tracker.form.graph.action" diff --git a/addons/lunch/i18n/tr.po b/addons/lunch/i18n/tr.po index 6fd066e863d..4bb623040f0 100644 --- a/addons/lunch/i18n/tr.po +++ b/addons/lunch/i18n/tr.po @@ -986,4 +986,4 @@ msgstr "öğle yemeği ürün kategorisi" #. module: lunch #: model:ir.model,name:lunch.model_lunch_order_line_lucky msgid "lunch.order.line.lucky" -msgstr "" +msgstr "lunch.order.line.lucky" diff --git a/addons/mail/i18n/tr.po b/addons/mail/i18n/tr.po index 10f755b2fec..1aabb67b1ff 100644 --- a/addons/mail/i18n/tr.po +++ b/addons/mail/i18n/tr.po @@ -329,6 +329,8 @@ msgid "" "A shortcode is a keyboard shortcut. For instance, you type #gm and it will " "be transformed into \"Good Morning\"." msgstr "" +"Bir kısa kod, bir klavye kısayoludır. Örneğin, # gm yazarsınız ve " +"\"Günaydın\" a dönüşür." #. module: mail #: model:ir.model,name:mail.model_res_groups @@ -1518,6 +1520,8 @@ msgid "" "Email address of the sender. This field is set when no matching partner is " "found and replaces the author_id field in the chatter." msgstr "" +"Gönderenin e-posta adresi. Eşleşen bir ortak bulunmadığında ve sohbetteki " +"author_id alanının yerini aldığında bu alan ayarlanır." #. module: mail #: model:ir.ui.view,arch_db:mail.email_compose_message_wizard_form @@ -3123,7 +3127,7 @@ msgstr "" #. module: mail #: model:ir.model.fields,field_description:mail.field_mail_tracking_value__new_value_char msgid "New Value Char" -msgstr "" +msgstr "Yeni Karakter Değeri" #. module: mail #: model:ir.model.fields,field_description:mail.field_mail_tracking_value__new_value_datetime @@ -3143,12 +3147,12 @@ msgstr "Yeni Tam Sayı Değeri" #. module: mail #: model:ir.model.fields,field_description:mail.field_mail_tracking_value__new_value_monetary msgid "New Value Monetary" -msgstr "" +msgstr "Yeni Parasal Değer" #. module: mail #: model:ir.model.fields,field_description:mail.field_mail_tracking_value__new_value_text msgid "New Value Text" -msgstr "" +msgstr "Yeni Metin Değeri" #. module: mail #. openerp-web @@ -3275,7 +3279,7 @@ msgstr "" #: code:addons/mail/static/src/xml/web_kanban_activity.xml:22 #, python-format msgid "No activities planned." -msgstr "" +msgstr "Hiçbir etkinlik planlanmadı." #. module: mail #. openerp-web @@ -3591,7 +3595,7 @@ msgstr "Odoo" #, python-format msgid "" "Odoo has now the permission to send you native notifications on this device." -msgstr "" +msgstr "Odoo, artık bu cihazda yerel bildirimler göndermek için izin aldı." #. module: mail #. openerp-web @@ -3607,7 +3611,7 @@ msgstr "Odoo için izniniz gerekiyor" msgid "" "Odoo will not have the permission to send native notifications on this " "device." -msgstr "" +msgstr "Odoo, bu cihazda yerel bildirimler gönderme iznine sahip olmayacak." #. module: mail #. openerp-web @@ -3619,32 +3623,32 @@ msgstr "Çevrimdışı" #. module: mail #: model:ir.model.fields,field_description:mail.field_mail_tracking_value__old_value_char msgid "Old Value Char" -msgstr "" +msgstr "Eski Karakter Değeri" #. module: mail #: model:ir.model.fields,field_description:mail.field_mail_tracking_value__old_value_datetime msgid "Old Value DateTime" -msgstr "" +msgstr "Eski Tarih Saat Değeri" #. module: mail #: model:ir.model.fields,field_description:mail.field_mail_tracking_value__old_value_float msgid "Old Value Float" -msgstr "" +msgstr "Eski Sayısal Değer" #. module: mail #: model:ir.model.fields,field_description:mail.field_mail_tracking_value__old_value_integer msgid "Old Value Integer" -msgstr "" +msgstr "Eski Tam Sayı Değeri" #. module: mail #: model:ir.model.fields,field_description:mail.field_mail_tracking_value__old_value_monetary msgid "Old Value Monetary" -msgstr "" +msgstr "Eski Parasal Değer" #. module: mail #: model:ir.model.fields,field_description:mail.field_mail_tracking_value__old_value_text msgid "Old Value Text" -msgstr "" +msgstr "Eski Metin Değeri" #. module: mail #: selection:ir.model.fields,track_visibility:0 @@ -3701,21 +3705,21 @@ msgstr "Üst Belgeyi Aç" #: code:addons/mail/static/src/xml/discuss.xml:139 #, python-format msgid "Open channel settings" -msgstr "" +msgstr "Açık kanal ayarları" #. module: mail #. openerp-web #: code:addons/mail/static/src/xml/discuss.xml:187 #, python-format msgid "Open chat" -msgstr "" +msgstr "Konuşmayı aç" #. module: mail #. openerp-web #: code:addons/mail/static/src/xml/extended_chat_window.xml:15 #, python-format msgid "Open in Discuss" -msgstr "" +msgstr "Tartışmayı Aç" #. module: mail #: model:ir.model.fields,field_description:mail.field_res_partner__opt_out @@ -3881,6 +3885,9 @@ msgid "" " named. For example on a project, the parent_id of project subtypes refers " "to task-related subtypes." msgstr "" +"Otomatik abonelik için kullanılan alt alt türü. Bu alan doğru bir şekilde " +"adlandırılmamış. Örneğin, bir projede, proje alt türlerinin parent_id'i, " +"görevle ilgili alt türlere başvurur." #. module: mail #: model:ir.actions.act_window,name:mail.action_partner_mass_mail @@ -3905,7 +3912,7 @@ msgstr "" #: model:ir.model.fields,field_description:mail.field_mail_message__needaction_partner_ids #: model:ir.model.fields,field_description:mail.field_survey_mail_compose_message__needaction_partner_ids msgid "Partners with Need Action" -msgstr "" +msgstr "Eylem İhtiyacı Olan İş Ortakları" #. module: mail #: model:ir.model.fields,help:mail.field_email_template_preview__auto_delete @@ -4312,7 +4319,7 @@ msgstr "Yeni Şablon olarak kaydet" #: code:addons/mail/static/src/js/chat_window.js:40 #, python-format msgid "Say something" -msgstr "" +msgstr "Bir şey söyle" #. module: mail #: model:ir.ui.view,arch_db:mail.mail_activity_view_form_popup @@ -4436,7 +4443,7 @@ msgstr "" #: code:addons/mail/static/src/js/thread_field.js:92 #, python-format msgid "Sending Error" -msgstr "" +msgstr "Hata Gönderiliyor" #. module: mail #. openerp-web @@ -4483,7 +4490,7 @@ msgstr "" #: model:ir.ui.view,arch_db:mail.mail_shortcode_view_form #: model:ir.ui.view,arch_db:mail.mail_shortcode_view_tree msgid "Shortcodes" -msgstr "" +msgstr "Kısa kodlar" #. module: mail #: model:ir.model.fields,field_description:mail.field_mail_shortcode__source @@ -4500,7 +4507,7 @@ msgstr "Bir sonraki eylem tarihi bugünden önce olan tüm kayıtları göster" #: code:addons/mail/models/mail_channel.py:673 #, python-format msgid "Show an helper message" -msgstr "" +msgstr "Bir yardımcı mesajı göster" #. module: mail #: model:ir.model.fields,field_description:mail.field_email_template_preview__ref_ir_act_window @@ -4557,6 +4564,8 @@ msgid "" "Specify a model if the activity should be specific to a model and not " "available when managing activities for other models." msgstr "" +"Etkinliğin bir modele özgü olması ve diğer modellerin etkinliklerini " +"yönetirken kullanılamaması durumunda bir model belirtin." #. module: mail #. openerp-web @@ -4821,6 +4830,8 @@ msgid "" "This group is visible by non members. Invisible groups can add members " "through the invite button." msgstr "" +"Bu grup üye olmayanlar tarafından görülebilir. Görünmez gruplar, davet " +"butonuyla üye ekleyebilir." #. module: mail #: model:ir.ui.view,arch_db:mail.view_mail_search @@ -4924,13 +4935,13 @@ msgstr "İzleme" #: model:ir.ui.view,arch_db:mail.view_mail_tracking_value_form #: model:ir.ui.view,arch_db:mail.view_mail_tracking_value_tree msgid "Tracking Value" -msgstr "" +msgstr "İzleme Değeri" #. module: mail #: model:ir.actions.act_window,name:mail.action_view_mail_tracking_value #: model:ir.ui.menu,name:mail.menu_mail_tracking_value msgid "Tracking Values" -msgstr "" +msgstr "İzleme Değerleri" #. module: mail #: model:ir.model.fields,field_description:mail.field_mail_compose_message__tracking_value_ids @@ -4938,7 +4949,7 @@ msgstr "" #: model:ir.model.fields,field_description:mail.field_mail_message__tracking_value_ids #: model:ir.model.fields,field_description:mail.field_survey_mail_compose_message__tracking_value_ids msgid "Tracking values" -msgstr "" +msgstr "İzleme Değerleri" #. module: mail #: model:ir.model.fields,field_description:mail.field_mail_compose_message__message_type @@ -5191,7 +5202,7 @@ msgstr "Şablonu Kullan" #. module: mail #: model:ir.ui.view,arch_db:mail.res_config_settings_view_form msgid "Use your own email servers" -msgstr "" +msgstr "Kendi e-mail sunucusunu kullanın" #. module: mail #: model:ir.model.fields,help:mail.field_mail_message_subtype__sequence @@ -5299,7 +5310,7 @@ msgstr "Bu modelin ileti ve bildirimleri destekleyip desteklemediğidir." #. module: mail #: model:ir.ui.view,arch_db:mail.mail_channel_view_form msgid "Who can follow the group's activities?" -msgstr "" +msgstr "Grubun faaliyetlerini kim takip edebilir?" #. module: mail #. openerp-web @@ -5433,13 +5444,13 @@ msgstr "" #: code:addons/mail/static/src/js/thread_field.js:92 #, python-format msgid "Your message has not been sent." -msgstr "" +msgstr "Mesajınız gönderilemedi." #. module: mail #: code:addons/mail/models/ir_actions.py:30 #, python-format msgid "Your template should define email_from" -msgstr "" +msgstr "Şablonunuz email_from tanımlanabilir" #. module: mail #: code:addons/mail/models/mail_thread.py:948 @@ -5533,7 +5544,7 @@ msgstr "" #: code:addons/mail/models/mail_alias.py:267 #, python-format msgid "incorrectly configured alias (unknown reference record)" -msgstr "" +msgstr "yanlış yapılandırılmış takma ad (bilinmeyen referans kaydı)" #. module: mail #: model:ir.model,name:mail.model_ir_actions_server diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index a70e4d65205..d6b696c8124 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -500,11 +500,11 @@ class MailThread(models.AbstractModel): msg_comment = MailMessage.search([ ('model', '=', self._name), ('res_id', '=', self.id), - ('subtype_id', '=', subtype_comment.id)]) + ('subtype_id', '=', subtype_comment)]) msg_not_comment = MailMessage.search([ ('model', '=', self._name), ('res_id', '=', self.id), - ('subtype_id', '!=', subtype_comment.id)]) + ('subtype_id', '!=', subtype_comment)]) # update the messages msg_comment.write({"res_id": new_thread.id, "model": new_thread._name}) diff --git a/addons/mail/static/src/js/systray.js b/addons/mail/static/src/js/systray.js index f11531b6eab..30191cd3845 100644 --- a/addons/mail/static/src/js/systray.js +++ b/addons/mail/static/src/js/systray.js @@ -156,7 +156,7 @@ var MessagingMenu = Widget.extend({ if (channelID === 'channel_inbox' || channelID === 'mail_failure') { var resID = $(event.currentTarget).data('res_id'); var resModel = $(event.currentTarget).data('res_model'); - if (resModel && resID) { + if (resModel && resModel !== 'mail.channel' && resID) { this.do_action({ type: 'ir.actions.act_window', res_model: resModel, @@ -174,7 +174,11 @@ var MessagingMenu = Widget.extend({ domain: [['message_has_error', '=', true]], }); } else { - this.do_action('mail.mail_channel_action_client_chat', {clear_breadcrumbs: true}) + var clientChatOptions = {clear_breadcrumbs: true}; + if (resModel && resModel === 'mail.channel' && resID) { + clientChatOptions.active_id = resID; + } + this.do_action('mail.mail_channel_action_client_chat', clientChatOptions) .then(function () { self.trigger_up('hide_home_menu'); // we cannot 'go back to previous page' otherwise core.bus.trigger('change_menu_section', self.call('chat_manager', 'getDiscussMenuID')); diff --git a/addons/mail/views/res_partner_views.xml b/addons/mail/views/res_partner_views.xml index 0fc6007b449..0264859b615 100644 --- a/addons/mail/views/res_partner_views.xml +++ b/addons/mail/views/res_partner_views.xml @@ -7,7 +7,7 @@ <field name="model">res.partner</field> <field name="inherit_id" ref="base.view_partner_form"/> <field name="arch" type="xml"> - <xpath expr="//field[@name='user_id']" position="after"> + <xpath expr="//page[@name='sales_purchases']//field[@name='user_id']" position="after"> <field name="opt_out" string="Mailing Opt-Out" groups="base.group_no_one"/> <field name="message_bounce" groups="base.group_no_one"/> </xpath> diff --git a/addons/maintenance/i18n/tr.po b/addons/maintenance/i18n/tr.po index bbac3f16eee..fe2712e0e13 100644 --- a/addons/maintenance/i18n/tr.po +++ b/addons/maintenance/i18n/tr.po @@ -982,7 +982,7 @@ msgstr "Durumu değişti" #. module: maintenance #: model:ir.model.fields,field_description:maintenance.field_maintenance_request__name msgid "Subjects" -msgstr "" +msgstr "Konular" #. module: maintenance #: model:ir.model.fields,field_description:maintenance.field_maintenance_request__maintenance_team_id diff --git a/addons/mass_mailing/i18n/tr.po b/addons/mass_mailing/i18n/tr.po index 03ea4cd2a45..88b89e36056 100644 --- a/addons/mass_mailing/i18n/tr.po +++ b/addons/mass_mailing/i18n/tr.po @@ -1911,7 +1911,7 @@ msgstr "Ve bir sonraki siparişinizde20 TL tasarruf edin!" #. module: mass_mailing #: model:ir.model.fields,field_description:mass_mailing.field_mail_mass_mailing_campaign__campaign_id msgid "campaign_id" -msgstr "" +msgstr "campaign_id" #. module: mass_mailing #: model:ir.ui.view,arch_db:mass_mailing.view_mail_mass_mailing_list_form @@ -1937,12 +1937,12 @@ msgstr "" #. module: mass_mailing #: model:ir.model,name:mass_mailing.model_link_tracker msgid "link.tracker" -msgstr "" +msgstr "link.tracker" #. module: mass_mailing #: model:ir.model,name:mass_mailing.model_link_tracker_click msgid "link.tracker.click" -msgstr "" +msgstr "link.tracker.click" #. module: mass_mailing #: model:ir.model,name:mass_mailing.model_res_config_settings diff --git a/addons/mass_mailing/static/src/js/mass_mailing.js b/addons/mass_mailing/static/src/js/mass_mailing.js index e611d9dbe26..e1689b69e5b 100644 --- a/addons/mass_mailing/static/src/js/mass_mailing.js +++ b/addons/mass_mailing/static/src/js/mass_mailing.js @@ -41,7 +41,7 @@ FieldTextHtml.include({ var datarecord = this._super(); if (this.model === 'mail.mass_mailing') { // these fields can potentially get very long, let's remove them - datarecord = _.omit(datarecord, ['mailing_domain', 'contact_list_ids', 'body_html']); + datarecord = _.omit(datarecord, ['mailing_domain', 'contact_list_ids', 'body_html', 'attachment_ids']); } return datarecord; }, diff --git a/addons/mass_mailing_event_track/models/event.py b/addons/mass_mailing_event_track/models/event.py index 156625391c0..e5747875f21 100644 --- a/addons/mass_mailing_event_track/models/event.py +++ b/addons/mass_mailing_event_track/models/event.py @@ -16,7 +16,7 @@ class Event(models.Model): view_mode='form', target='current', context=dict( - default_mailing_model=self.env.ref('website_event_track.model_event_track').id, + default_mailing_model_id=self.env.ref('website_event_track.model_event_track').id, default_mailing_domain="[('event_id', 'in', %s), ('stage_id.is_cancel', '!=', True)]" % self.ids, ), ) diff --git a/addons/mrp/models/mrp_bom.py b/addons/mrp/models/mrp_bom.py index b1892c4db2a..922802f9659 100644 --- a/addons/mrp/models/mrp_bom.py +++ b/addons/mrp/models/mrp_bom.py @@ -80,6 +80,8 @@ class MrpBom(models.Model): def onchange_product_tmpl_id(self): if self.product_tmpl_id: self.product_uom_id = self.product_tmpl_id.uom_id.id + if self.product_id.product_tmpl_id != self.product_tmpl_id: + self.product_id = False @api.onchange('routing_id') def onchange_routing_id(self): diff --git a/addons/mrp/models/mrp_workorder.py b/addons/mrp/models/mrp_workorder.py index 17914b1b9dd..cc7a98635ea 100644 --- a/addons/mrp/models/mrp_workorder.py +++ b/addons/mrp/models/mrp_workorder.py @@ -364,6 +364,7 @@ class MrpWorkorder(models.Model): move_line = production_move.move_line_ids.filtered(lambda x: x.lot_id.id == self.final_lot_id.id) if move_line: move_line.product_uom_qty += self.qty_producing + move_line.qty_done += self.qty_producing else: move_line.create({'move_id': production_move.id, 'product_id': production_move.product_id.id, diff --git a/addons/mrp/models/stock_move.py b/addons/mrp/models/stock_move.py index 1099d8b549e..befe9ceb9d1 100644 --- a/addons/mrp/models/stock_move.py +++ b/addons/mrp/models/stock_move.py @@ -73,6 +73,13 @@ class StockMove(models.Model): order_finished_lot_ids = fields.Many2many('stock.production.lot', compute='_compute_order_finished_lot_ids') finished_lots_exist = fields.Boolean('Finished Lots Exist', compute='_compute_order_finished_lot_ids') + def _unreserve_initial_demand(self, new_move): + # If you were already putting stock.move.lots on the next one in the work order, transfer those to the new move + self.filtered(lambda m: m.production_id or m.raw_material_production_id)\ + .mapped('move_line_ids')\ + .filtered(lambda ml: ml.qty_done == 0.0)\ + .write({'move_id': new_move, 'product_uom_qty': 0}) + @api.depends('active_move_line_ids.qty_done', 'active_move_line_ids.product_uom_id') def _compute_done_quantity(self): super(StockMove, self)._compute_done_quantity() diff --git a/addons/mrp/views/mrp_workorder_views.xml b/addons/mrp/views/mrp_workorder_views.xml index 0aee35f12b1..16757f1acd4 100644 --- a/addons/mrp/views/mrp_workorder_views.xml +++ b/addons/mrp/views/mrp_workorder_views.xml @@ -196,18 +196,19 @@ <label for="duration"/> <div> <button style="pointer-events: none;" class="oe_inline label label-default"> - <field name="duration" widget="mrp_time_counter"/> + <field name="duration" widget="mrp_time_counter" help="Time the currently logged user spent on this workorder."/> </button> </div> </group> </group> <group> - <field name="time_ids" nolabel="1"> + <field name="time_ids" nolabel="1" context="{'default_workcenter_id': workcenter_id}"> <tree> <field name="date_start"/> <field name="date_end"/> <field name="duration" widget="float_time" sum="Total duration"/> <field name="user_id"/> + <field name="workcenter_id" invisible="1"/> <field name="loss_id" string="Efficiency"/> </tree> <form> @@ -219,6 +220,7 @@ </group> <group> <field name="user_id"/> + <field name="workcenter_id"/> <field name="loss_id"/> </group> </group> diff --git a/addons/payment_authorize/models/payment.py b/addons/payment_authorize/models/payment.py index 2896e566f43..2cb98f74b24 100644 --- a/addons/payment_authorize/models/payment.py +++ b/addons/payment_authorize/models/payment.py @@ -60,6 +60,15 @@ class PaymentAcquirerAuthorize(models.Model): @api.multi def authorize_form_generate_values(self, values): self.ensure_one() + # State code is only supported in US, use state name by default + # See https://developer.authorize.net/api/reference/ + state = values['partner_state'].name if values.get('partner_state') else '' + if values.get('partner_country') and values.get('partner_country') == self.env.ref('base.us', False): + state = values['partner_state'].code if values.get('partner_state') else '' + billing_state = values['billing_partner_state'].name if values.get('billing_partner_state') else '' + if values.get('billing_partner_country') and values.get('billing_partner_country') == self.env.ref('base.us', False): + billing_state = values['billing_partner_state'].code if values.get('billing_partner_state') else '' + base_url = self.env['ir.config_parameter'].get_param('web.base.url') authorize_tx_values = dict(values) temp_authorize_tx_values = { @@ -84,7 +93,7 @@ class PaymentAcquirerAuthorize(models.Model): 'first_name': values.get('partner_first_name'), 'last_name': values.get('partner_last_name'), 'phone': values.get('partner_phone'), - 'state': values.get('partner_state') and values['partner_state'].code or '', + 'state': state, 'billing_address': values.get('billing_partner_address'), 'billing_city': values.get('billing_partner_city'), 'billing_country': values.get('billing_partner_country') and values.get('billing_partner_country').name or '', @@ -93,7 +102,7 @@ class PaymentAcquirerAuthorize(models.Model): 'billing_first_name': values.get('billing_partner_first_name'), 'billing_last_name': values.get('billing_partner_last_name'), 'billing_phone': values.get('billing_partner_phone'), - 'billing_state': values.get('billing_partner_state') and values['billing_partner_state'].code or '', + 'billing_state': billing_state, } temp_authorize_tx_values['returndata'] = authorize_tx_values.pop('return_url', '') temp_authorize_tx_values['x_fp_hash'] = self._authorize_generate_hashing(temp_authorize_tx_values) diff --git a/addons/payment_ogone/controllers/main.py b/addons/payment_ogone/controllers/main.py index 1d03a688630..409e09b8a9e 100644 --- a/addons/payment_ogone/controllers/main.py +++ b/addons/payment_ogone/controllers/main.py @@ -110,7 +110,7 @@ class OgoneController(http.Controller): def feedback(self, **kwargs): try: tx = request.env['payment.transaction'].sudo()._ogone_form_get_tx_from_data(kwargs) - tx._ogone_s2s_validate() + tx._ogone_s2s_validate_tree(kwargs) except ValidationError: return 'ko' return 'ok' diff --git a/addons/payment_stripe/static/src/js/stripe.js b/addons/payment_stripe/static/src/js/stripe.js index e4474fe72ce..956765e8042 100644 --- a/addons/payment_stripe/static/src/js/stripe.js +++ b/addons/payment_stripe/static/src/js/stripe.js @@ -87,74 +87,30 @@ odoo.define('payment_stripe.stripe', function(require) { payment_form.append('<i class="fa fa-spinner fa-spin"/>'); payment_form.attr('disabled','disabled'); - var acquirer_id = payment_form.find('input[type="radio"][data-provider="stripe"]:checked').data('acquirer-id'); - if (! acquirer_id) { - return false; - } - + var payment_tx_url = payment_form.find('input[name="prepare_tx_url"]').val(); var access_token = $("input[name='access_token']").val() || $("input[name='token']").val() || ''; - var so_id = $("input[name='return_url']").val().match(/quote\/([0-9]+)/) || undefined; - if (so_id) { - so_id = parseInt(so_id[1]); - } - var invoice_id = $("input[name='return_url']").val().match(/invoices\/([0-9]+)/) || undefined; - if (invoice_id) { - invoice_id = parseInt(invoice_id[1]); - } - - var currency = $("input[name='currency']").val(); - var currency_id = $("input[name='currency_id']").val(); - var amount = parseFloat($("input[name='amount']").val() || '0.0'); + var get_input_value = function(name) { + return provider_form.find('input[name="' + name + '"]').val(); + } - if ($('.o_website_payment').length !== 0) { - var invoice_num = $("input[name='invoice_num']").val(); - var url = _.str.sprintf("/website_payment/transaction/v2/%f/%s/%s", - amount, currency_id, invoice_num); + var acquirer_id = parseInt(provider_form.find('#acquirer_stripe').val()); + var amount = parseFloat(get_input_value("amount") || '0.0'); + var currency = get_input_value("currency"); + var email = get_input_value("email"); + var invoice_num = get_input_value("invoice_num"); + var merchant = get_input_value("merchant"); - var create_tx = ajax.jsonRpc(url, 'call', { - acquirer_id: acquirer_id - }).then(function (data) { - try { provider_form[0].innerHTML = data; } catch (e) {} - }); - } - else if ($('.o_website_quote').length !== 0) { - var url = _.str.sprintf("/quote/%s/transaction/", so_id); - var create_tx = ajax.jsonRpc(url, 'call', { - access_token: access_token, - acquirer_id: acquirer_id - }).then(function (data) { - try { provider_form[0].innerHTML = data; } catch (e) {}; - }); - } else if (window.location.href.includes("/my/orders/")) { - var create_tx = ajax.jsonRpc('/pay/sale/' + so_id + '/form_tx/', 'call', { - access_token: access_token, - acquirer_id: acquirer_id - }).then(function (data) { - try { provider_form.innerHTML = data; } catch (e) {}; - }); - } else if (window.location.href.includes("/my/invoices/")) { - var create_tx = ajax.jsonRpc('/invoice/pay/' + invoice_id + '/form_tx/', 'call', { - access_token: access_token, - acquirer_id: acquirer_id - }).then(function (data) { - try { provider_form.innerHTML = data; } catch (e) {}; - }); - } - else { - var create_tx = ajax.jsonRpc('/shop/payment/transaction/' + acquirer_id, 'call', { - so_id: so_id, - access_token: access_token, - acquirer_id: acquirer_id - }).then(function (data) { - try { provider_form.innerHTML = data; } catch (e) {}; - }); - } - create_tx.done(function () { + ajax.jsonRpc(payment_tx_url, 'call', { + acquirer_id: acquirer_id, + access_token: access_token, + }).then(function(data) { + try { provider_form[0].innerHTML = data; } catch (e) {}; + }).done(function () { getStripeHandler().open({ - name: $("input[name='merchant']").val(), - description: $("input[name='invoice_num']").val(), - email: $("input[name='email']").val(), + name: merchant, + description: invoice_num, + email: email, currency: currency, amount: _.contains(int_currencies, currency) ? amount : amount * 100, }); diff --git a/addons/phone_validation/i18n/tr.po b/addons/phone_validation/i18n/tr.po index d154d793e22..b86582c48e2 100644 --- a/addons/phone_validation/i18n/tr.po +++ b/addons/phone_validation/i18n/tr.po @@ -95,4 +95,4 @@ msgstr "" #. module: phone_validation #: model:ir.model,name:phone_validation.model_phone_validation_mixin msgid "phone.validation.mixin" -msgstr "" +msgstr "phone.validation.mixin" diff --git a/addons/point_of_sale/i18n/tr.po b/addons/point_of_sale/i18n/tr.po index 4b4e51b656a..fd552931a40 100644 --- a/addons/point_of_sale/i18n/tr.po +++ b/addons/point_of_sale/i18n/tr.po @@ -4132,6 +4132,9 @@ msgid "" "You cannot confirm all orders of this session, because they have not the 'paid' status.\n" "{reference} is in state {state}, total amount: {total}, paid: {paid}" msgstr "" +"Bu oturumun tüm siparişlerini onaylayamazsınız, çünkü \"ödendi\" durumları " +"yoktur. {Reference} durum {state} durumundadır, toplam tutar: {total}, " +"ödendi: {paid}" #. module: point_of_sale #: code:addons/point_of_sale/models/pos_session.py:151 diff --git a/addons/point_of_sale/models/pos_session.py b/addons/point_of_sale/models/pos_session.py index 8d1dcf69074..74da78ddf51 100644 --- a/addons/point_of_sale/models/pos_session.py +++ b/addons/point_of_sale/models/pos_session.py @@ -38,8 +38,8 @@ class PosSession(models.Model): paid=order.amount_paid, )) order.action_pos_order_done() - orders = session.order_ids.filtered(lambda order: order.state in ['invoiced', 'done']) - orders.sudo()._reconcile_payments() + orders_to_reconcile = session.order_ids.filtered(lambda order: order.state in ['invoiced', 'done'] and order.partner_id) + orders_to_reconcile.sudo()._reconcile_payments() config_id = fields.Many2one( 'pos.config', string='Point of Sale', diff --git a/addons/point_of_sale/models/product.py b/addons/point_of_sale/models/product.py index 43a959bcfa4..ed9f2dce8cd 100644 --- a/addons/point_of_sale/models/product.py +++ b/addons/point_of_sale/models/product.py @@ -27,6 +27,18 @@ class ProductTemplate(models.Model): self.available_in_pos = False +class ProductProduct(models.Model): + _inherit = 'product.product' + + @api.multi + def unlink(self): + product_ctx = dict(self.env.context or {}, active_test=False) + if self.env['pos.session'].search_count([('state', '!=', 'closed')]): + if self.with_context(product_ctx).search_count([('id', 'in', self.ids), ('product_tmpl_id.available_in_pos', '=', True)]): + raise UserError(_('You cannot delete a product saleable in point of sale while a session is still opened.')) + return super(ProductProduct, self).unlink() + + class UomCateg(models.Model): _inherit = 'uom.category' diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 63c9e1c0cb0..c73c7f75165 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -1406,6 +1406,7 @@ exports.Orderline = Backbone.Model.extend({ this.set_unit_price(this.product.get_price(this.order.pricelist, this.get_quantity())); this.order.fix_tax_included_price(this); } + this.trigger('change', this); }, // return the quantity of product get_quantity: function(){ @@ -2124,7 +2125,7 @@ exports.Order = Backbone.Model.extend({ company_registry: company.company_registry, contact_address: company.partner_id[1], vat: company.vat, - vat_label: company.country.vat_label, + vat_label: company.country && company.country.vat_label || '', name: company.name, phone: company.phone, logo: this.pos.company_logo_base64, diff --git a/addons/portal/controllers/mail.py b/addons/portal/controllers/mail.py index 9fb2c6b94ac..89dbded3676 100644 --- a/addons/portal/controllers/mail.py +++ b/addons/portal/controllers/mail.py @@ -100,7 +100,7 @@ class PortalChatter(http.Controller): raise Forbidden() # Non-employee see only messages with not internal subtype (aka, no internal logs) if not request.env['res.users'].has_group('base.group_user'): - domain = expression.AND([['&', '&', ('subtype_id', '!=', False), ('subtype_id.internal', '=', False)], domain]) + domain = expression.AND([['&', ('subtype_id', '!=', False), ('subtype_id.internal', '=', False)], domain]) Message = request.env['mail.message'].sudo() return { 'messages': Message.search(domain, limit=limit, offset=offset).portal_message_format(), diff --git a/addons/portal/i18n/tr.po b/addons/portal/i18n/tr.po index 6ea7eb0fe95..2aac19a95f8 100644 --- a/addons/portal/i18n/tr.po +++ b/addons/portal/i18n/tr.po @@ -626,7 +626,7 @@ msgstr "oturum açıldı" #. module: portal #: model:ir.model,name:portal.model_portal_mixin msgid "portal.mixin" -msgstr "" +msgstr "portal.mixin" #. module: portal #: model:ir.ui.view,arch_db:portal.portal_my_details diff --git a/addons/portal/wizard/portal_wizard.py b/addons/portal/wizard/portal_wizard.py index 22d6765aac7..44eb1637619 100644 --- a/addons/portal/wizard/portal_wizard.py +++ b/addons/portal/wizard/portal_wizard.py @@ -134,7 +134,7 @@ class PortalWizardUser(models.TransientModel): if wizard_user.partner_id.company_id: company_id = wizard_user.partner_id.company_id.id else: - company_id = self.env['res.company']._company_default_get('res.users') + company_id = self.env['res.company']._company_default_get('res.users').id user_portal = wizard_user.sudo().with_context(company_id=company_id)._create_user() else: user_portal = user diff --git a/addons/pos_cache/i18n/tr.po b/addons/pos_cache/i18n/tr.po index 85565d72609..22c95880db7 100644 --- a/addons/pos_cache/i18n/tr.po +++ b/addons/pos_cache/i18n/tr.po @@ -110,7 +110,7 @@ msgstr "Ürün Alanı" #. module: pos_cache #: model:ir.model,name:pos_cache.model_pos_cache msgid "pos.cache" -msgstr "" +msgstr "pos.cache" #. module: pos_cache #: model:ir.model,name:pos_cache.model_pos_config diff --git a/addons/pos_restaurant/i18n/tr.po b/addons/pos_restaurant/i18n/tr.po index f403a4cc836..fef517cdeba 100644 --- a/addons/pos_restaurant/i18n/tr.po +++ b/addons/pos_restaurant/i18n/tr.po @@ -752,14 +752,14 @@ msgstr "pos.config" #. module: pos_restaurant #: model:ir.model,name:pos_restaurant.model_restaurant_floor msgid "restaurant.floor" -msgstr "" +msgstr "restaurant.floor" #. module: pos_restaurant #: model:ir.model,name:pos_restaurant.model_restaurant_printer msgid "restaurant.printer" -msgstr "" +msgstr "restaurant.printer" #. module: pos_restaurant #: model:ir.model,name:pos_restaurant.model_restaurant_table msgid "restaurant.table" -msgstr "" +msgstr "restaurant.table" diff --git a/addons/product/models/product.py b/addons/product/models/product.py index 5470ba084c5..51b450cba2b 100644 --- a/addons/product/models/product.py +++ b/addons/product/models/product.py @@ -220,6 +220,7 @@ class ProductProduct(models.Model): for supplier_info in self.seller_ids: if supplier_info.name.id == self._context.get('partner_id'): self.code = supplier_info.product_code or self.default_code + break else: self.code = self.default_code @@ -229,6 +230,7 @@ class ProductProduct(models.Model): if supplier_info.name.id == self._context.get('partner_id'): product_name = supplier_info.product_name or self.default_code self.partner_ref = '%s%s' % (self.code and '[%s] ' % self.code or '', product_name) + break else: self.partner_ref = self.name_get()[0][1] diff --git a/addons/product/models/product_attribute.py b/addons/product/models/product_attribute.py index 8060468b2ab..b7883a6c82f 100644 --- a/addons/product/models/product_attribute.py +++ b/addons/product/models/product_attribute.py @@ -4,6 +4,7 @@ from odoo import api, fields, models, _ from odoo.addons import decimal_precision as dp from odoo.exceptions import UserError, ValidationError +from odoo.osv import expression class ProductAttribute(models.Model): @@ -107,7 +108,7 @@ class ProductAttributeLine(models.Model): # search on a m2o and one on a m2m, probably this will quickly become # difficult to compute - check if performance optimization is required if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'): - args = ['|', ('attribute_id', operator, name), ('value_ids', operator, name)] + args = expression.AND([['|', ('attribute_id', operator, name), ('value_ids', operator, name)], args]) attribute_ids = self._search(args, limit=limit, access_rights_uid=name_get_uid) return self.browse(attribute_ids).name_get() return super(ProductAttributeLine, self)._name_search(name=name, args=args, operator=operator, limit=limit, name_get_uid=name_get_uid) diff --git a/addons/product/tests/__init__.py b/addons/product/tests/__init__.py index b0122192ff8..96caad34928 100644 --- a/addons/product/tests/__init__.py +++ b/addons/product/tests/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import test_variants, test_pricelist, test_product_pricelist +from . import test_variants, test_pricelist, test_product_pricelist, test_seller diff --git a/addons/product/tests/test_seller.py b/addons/product/tests/test_seller.py new file mode 100644 index 00000000000..36693317c34 --- /dev/null +++ b/addons/product/tests/test_seller.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.tests.common import TransactionCase + + +class TestSeller(TransactionCase): + + def setUp(self): + super(TestSeller, self).setUp() + self.product_service = self.env.ref('product.product_product_2') + self.product_service.default_code = 'DEFCODE' + self.asustec = self.env.ref('base.res_partner_1') + self.camptocamp = self.env.ref('base.res_partner_12') + + def test_10_sellers(self): + self.product_service.write({'seller_ids': [ + (0, 0, {'name': self.asustec.id, 'product_code': 'ASUCODE'}), + (0, 0, {'name': self.camptocamp.id, 'product_code': 'C2CCODE'}), + ]}) + + default_code = self.product_service.code + self.assertEqual("DEFCODE", default_code, "Default code not used in product name") + + context_code = self.product_service\ + .with_context(partner_id=self.camptocamp.id)\ + .code + self.assertEqual('C2CCODE', context_code, "Partner's code not used in product name with context set") diff --git a/addons/product_expiry/i18n/tr.po b/addons/product_expiry/i18n/tr.po index 450843980a7..af48243a9f9 100644 --- a/addons/product_expiry/i18n/tr.po +++ b/addons/product_expiry/i18n/tr.po @@ -107,6 +107,8 @@ msgid "" "Number of days before the goods should be removed from the stock. It will be" " computed on the lot/serial number." msgstr "" +"Malların stoktan çıkarılmadan önce gereken gün sayısı. Bu lot / seri " +"numarası üzerinde hesaplanacaktır.." #. module: product_expiry #: model:ir.model.fields,help:product_expiry.field_product_product__use_time diff --git a/addons/project/controllers/portal.py b/addons/project/controllers/portal.py index 96d845105e2..27ecc3c6a7f 100644 --- a/addons/project/controllers/portal.py +++ b/addons/project/controllers/portal.py @@ -142,7 +142,7 @@ class CustomerPortal(CustomerPortal): # pager pager = portal_pager( url="/my/tasks", - url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby, 'filterby': filterby}, + url_args={'date_begin': date_begin, 'date_end': date_end, 'sortby': sortby, 'filterby': filterby, 'search_in': search_in, 'search': search}, total=task_count, page=page, step=self._items_per_page diff --git a/addons/project/i18n/tr.po b/addons/project/i18n/tr.po index 4e4795b6648..aa60fd117ae 100644 --- a/addons/project/i18n/tr.po +++ b/addons/project/i18n/tr.po @@ -1523,6 +1523,8 @@ msgid "" "Lets the company customize which Pad installation should be used to link to " "new pads (for example: http://etherpad.com/)." msgstr "" +"Şirketin yeni pedlere bağlantı kurmak için hangi Pad kurulumunun " +"kullanılması gerektiğini özelleştirir (örneğin: http://etherpad.com/)." #. module: project #: model:ir.model.fields,help:project.field_project_project__analytic_account_id diff --git a/addons/project/models/project.py b/addons/project/models/project.py index 4d486326217..c469614e1f0 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -872,7 +872,7 @@ class Task(models.Model): groups = [new_group] + groups for group_name, group_method, group_data in groups: - if group_name in ('customer'): + if group_name == 'customer': continue group_data['has_button_access'] = True diff --git a/addons/purchase/models/account_invoice.py b/addons/purchase/models/account_invoice.py index c24f2f75664..401bcdfa8b3 100644 --- a/addons/purchase/models/account_invoice.py +++ b/addons/purchase/models/account_invoice.py @@ -57,7 +57,7 @@ class AccountInvoice(models.Model): taxes = line.taxes_id invoice_line_tax_ids = line.order_id.fiscal_position_id.map_tax(taxes, line.product_id, line.order_id.partner_id) invoice_line = self.env['account.invoice.line'] - date = self.date + date = self.date or self.date_invoice data = { 'purchase_line_id': line.id, 'name': line.order_id.name + ': ' + line.name, @@ -113,7 +113,7 @@ class AccountInvoice(models.Model): def _onchange_currency_id(self): if self.currency_id: for line in self.invoice_line_ids.filtered(lambda r: r.purchase_line_id): - date = self.date or fields.Date.today() + date = self.date or self.date_invoice or fields.Date.today() company = self.company_id line.price_unit = line.purchase_id.currency_id._convert( line.purchase_line_id.price_unit, self.currency_id, company, date, round=False) diff --git a/addons/purchase/views/purchase_template.xml b/addons/purchase/views/purchase_template.xml index 9c5d5c5975c..d844cb9ec77 100644 --- a/addons/purchase/views/purchase_template.xml +++ b/addons/purchase/views/purchase_template.xml @@ -5,7 +5,7 @@ <div> <strong>The ordered quantity has been updated.</strong> <ul> - <li><t t-esc="line.order_id.product_id.display_name"/>:</li> + <li><t t-esc="line.product_id.display_name"/>:</li> Ordered Quantity: <t t-esc="line.product_qty" /> -> <t t-esc="float(product_qty)"/><br/> <t t-if='line.order_id.product_id.type in ("consu", "product")'> Received Quantity: <t t-esc="line.qty_received" /><br/> diff --git a/addons/purchase_stock/models/account_invoice.py b/addons/purchase_stock/models/account_invoice.py index 28b7bf8bd0b..87431c00ef7 100644 --- a/addons/purchase_stock/models/account_invoice.py +++ b/addons/purchase_stock/models/account_invoice.py @@ -57,7 +57,7 @@ class AccountInvoice(models.Model): valuation_price_unit = po_currency._convert( i_line.purchase_line_id.product_uom._compute_price(i_line.purchase_line_id.price_unit, i_line.uom_id), inv.currency_id, - company=po_company, date=inv.date_invoice, round=False, + company=po_company, date=inv.date or inv.date_invoice, round=False, ) stock_move_obj = self.env['stock.move'] valuation_stock_move = stock_move_obj.search([ @@ -90,7 +90,7 @@ class AccountInvoice(models.Model): # In this condition, we have a real price-valuated product which has not yet been received valuation_price_unit = po_currency._convert( i_line.purchase_line_id.price_unit, inv.currency_id, - company=po_company, date=inv.date_invoice, round=False, + company=po_company, date=inv.date or inv.date_invoice, round=False, ) interim_account_price = valuation_price_unit * line_quantity diff --git a/addons/purchase_stock/models/purchase.py b/addons/purchase_stock/models/purchase.py index 270812d5f7e..6524c13056e 100644 --- a/addons/purchase_stock/models/purchase.py +++ b/addons/purchase_stock/models/purchase.py @@ -117,7 +117,7 @@ class PurchaseOrder(models.Model): result['context'] = {} pick_ids = self.mapped('picking_ids') # choose the view_mode accordingly - if len(pick_ids) > 1: + if not pick_ids or len(pick_ids) > 1: result['domain'] = "[('id','in',%s)]" % (pick_ids.ids) elif len(pick_ids) == 1: res = self.env.ref('stock.view_picking_form', False) diff --git a/addons/repair/i18n/tr.po b/addons/repair/i18n/tr.po index 88357d2a8f6..d93d5460fb6 100644 --- a/addons/repair/i18n/tr.po +++ b/addons/repair/i18n/tr.po @@ -990,4 +990,4 @@ msgstr "stock.traceability.report" #. module: repair #: model:ir.model,name:repair.model_stock_warn_insufficient_qty_repair msgid "stock.warn.insufficient.qty.repair" -msgstr "" +msgstr "stock.warn.insufficient.qty.repair" diff --git a/addons/repair/models/repair.py b/addons/repair/models/repair.py index 53e6887b5df..be10a0c1ccd 100644 --- a/addons/repair/models/repair.py +++ b/addons/repair/models/repair.py @@ -200,9 +200,11 @@ class Repair(models.Model): def action_validate(self): self.ensure_one() precision = self.env['decimal.precision'].precision_get('Product Unit of Measure') - available_qty = self.env['stock.quant']._get_available_quantity(self.product_id, self.location_id, self.lot_id, strict=True) - if float_compare(available_qty, self.product_qty, precision_digits=precision) >= 0: - return self.action_repair_confirm() + available_qty_owner = self.env['stock.quant']._get_available_quantity(self.product_id, self.location_id, self.lot_id, owner_id=self.partner_id, strict=True) + available_qty_noown = self.env['stock.quant']._get_available_quantity(self.product_id, self.location_id, self.lot_id, strict=True) + for available_qty in [available_qty_owner, available_qty_noown]: + if float_compare(available_qty, self.product_qty, precision_digits=precision) >= 0: + return self.action_repair_confirm() else: return { 'name': _('Insufficient Quantity'), @@ -428,8 +430,15 @@ class Repair(models.Model): if self.filtered(lambda repair: not repair.repaired): raise UserError(_("Repair must be repaired in order to make the product moves.")) res = {} + precision = self.env['decimal.precision'].precision_get('Product Unit of Measure') Move = self.env['stock.move'] for repair in self: + # Try to create move with the appropriate owner + owner_id = False + available_qty_owner = self.env['stock.quant']._get_available_quantity(repair.product_id, repair.location_id, repair.lot_id, owner_id=repair.partner_id, strict=True) + if float_compare(available_qty_owner, repair.product_qty, precision_digits=precision) >= 0: + owner_id = repair.partner_id.id + moves = self.env['stock.move'] for operation in repair.operations: move = Move.create({ @@ -447,6 +456,7 @@ class Repair(models.Model): 'qty_done': operation.product_uom_qty, 'package_id': False, 'result_package_id': False, + 'owner_id': owner_id, 'location_id': operation.location_id.id, #TODO: owner stuff 'location_dest_id': operation.location_dest_id.id,})], 'repair_id': repair.id, @@ -469,6 +479,7 @@ class Repair(models.Model): 'qty_done': repair.product_qty, 'package_id': False, 'result_package_id': False, + 'owner_id': owner_id, 'location_id': repair.location_id.id, #TODO: owner stuff 'location_dest_id': repair.location_id.id,})], 'repair_id': repair.id, diff --git a/addons/repair/report/repair_templates_repair_order.xml b/addons/repair/report/repair_templates_repair_order.xml index 0e255cbc69d..ccd7dcfa53c 100644 --- a/addons/repair/report/repair_templates_repair_order.xml +++ b/addons/repair/report/repair_templates_repair_order.xml @@ -2,7 +2,7 @@ <odoo> <data> <template id="report_repairorder"> - <t t-foreach="docs" t-as="o"> + <t t-set="o" t-value="doc"/> <t t-call="web.external_layout"> <t t-set="o" t-value="o.with_context({'lang': o.partner_id.lang})" /> <div class="page"> @@ -155,7 +155,6 @@ <div class="oe_structure"/> </div> </t> - </t> </template> <template id="report_repairorder2"> diff --git a/addons/sale/report/report_all_channels_sales_views.xml b/addons/sale/report/report_all_channels_sales_views.xml index 793b568528e..201e229a186 100644 --- a/addons/sale/report/report_all_channels_sales_views.xml +++ b/addons/sale/report/report_all_channels_sales_views.xml @@ -4,7 +4,7 @@ <field name="name">report.all.channels.sales.pivot</field> <field name="model">report.all.channels.sales</field> <field name="arch" type="xml"> - <pivot string="Sales by Channel Analysis"> + <pivot string="Sales by Channel Analysis" disable_linking="True"> <field name="name" type="row"/> <field name="price_total" string="Total Price" type="measure"/> </pivot> diff --git a/addons/sale_payment/i18n/tr.po b/addons/sale_payment/i18n/tr.po index e5930a93beb..8a6ddb72af1 100644 --- a/addons/sale_payment/i18n/tr.po +++ b/addons/sale_payment/i18n/tr.po @@ -176,7 +176,7 @@ msgstr "Ödeme İşlemi" #. module: sale_payment #: model:ir.ui.view,arch_db:sale_payment.crm_team_salesteams_view_kanban_inherit_website_portal_sale msgid "Payment to Capture" -msgstr "" +msgstr "Yakalanan Ödeme" #. module: sale_payment #: model:ir.ui.view,arch_db:sale_payment.crm_team_salesteams_view_kanban_inherit_website_portal_sale diff --git a/addons/sale_timesheet/__init__.py b/addons/sale_timesheet/__init__.py index 4480f53802e..eca4161450d 100644 --- a/addons/sale_timesheet/__init__.py +++ b/addons/sale_timesheet/__init__.py @@ -1,7 +1,18 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from odoo import api, SUPERUSER_ID + from . import models from . import wizard from . import controllers from . import report + +def uninstall_hook(cr, registry): + env = api.Environment(cr, SUPERUSER_ID, {}) + env['product.template'].search([ + ('service_type', '=', 'timesheet') + ]).write({'service_type': 'manual'}) + env['product.product'].search([ + ('service_type', '=', 'timesheet') + ]).write({'service_type': 'manual'}) diff --git a/addons/sale_timesheet/__manifest__.py b/addons/sale_timesheet/__manifest__.py index c3c44ab8e48..57532d279d6 100644 --- a/addons/sale_timesheet/__manifest__.py +++ b/addons/sale_timesheet/__manifest__.py @@ -34,8 +34,9 @@ have real delivered quantities in sales orders. 'demo': [ 'data/sale_service_demo.xml', ], - 'auto_install': True, 'qweb': [ 'static/src/xml/timesheet_plan.xml', ], + 'auto_install': True, + 'uninstall_hook': 'uninstall_hook', } diff --git a/addons/stock/i18n/tr.po b/addons/stock/i18n/tr.po index 5eb3786cd5d..cd3c1a68696 100644 --- a/addons/stock/i18n/tr.po +++ b/addons/stock/i18n/tr.po @@ -6851,7 +6851,7 @@ msgstr "stock.fixed.putaway.strat" #. module: stock #: model:ir.model,name:stock.model_stock_overprocessed_transfer msgid "stock.overprocessed.transfer" -msgstr "" +msgstr "stock.overprocessed.transfer" #. module: stock #: model:ir.model,name:stock.model_stock_return_picking_line @@ -6871,12 +6871,12 @@ msgstr "stock.traceability.report" #. module: stock #: model:ir.model,name:stock.model_stock_warn_insufficient_qty msgid "stock.warn.insufficient.qty" -msgstr "" +msgstr "stock.warn.insufficient.qty" #. module: stock #: model:ir.model,name:stock.model_stock_warn_insufficient_qty_scrap msgid "stock.warn.insufficient.qty.scrap" -msgstr "" +msgstr "stock.warn.insufficient.qty.scrap" #. module: stock #: model:ir.ui.view,arch_db:stock.view_inventory_form diff --git a/addons/stock/models/product.py b/addons/stock/models/product.py index 75223abea24..ae8cc4d98fd 100644 --- a/addons/stock/models/product.py +++ b/addons/stock/models/product.py @@ -98,13 +98,13 @@ class Product(models.Model): domain_move_in = [('product_id', 'in', self.ids)] + domain_move_in_loc domain_move_out = [('product_id', 'in', self.ids)] + domain_move_out_loc - if lot_id: + if lot_id is not None: domain_quant += [('lot_id', '=', lot_id)] - if owner_id: + if owner_id is not None: domain_quant += [('owner_id', '=', owner_id)] domain_move_in += [('restrict_partner_id', '=', owner_id)] domain_move_out += [('restrict_partner_id', '=', owner_id)] - if package_id: + if package_id is not None: domain_quant += [('package_id', '=', package_id)] if dates_in_the_past: domain_move_in_done = list(domain_move_in) diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index 443607f7b2a..0dccd0a29a6 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -665,7 +665,7 @@ class StockMove(models.Model): self.product_uom = product.uom_id.id return {'domain': {'product_uom': [('category_id', '=', product.uom_id.category_id.id)]}} - @api.onchange('date') + @api.onchange('date_expected') def onchange_date(self): if self.date_expected: self.date = self.date_expected @@ -874,11 +874,6 @@ class StockMove(models.Model): package_id=package_id, owner_id=owner_id, strict=strict ) except UserError: - # If it raises here, it means that the `available_quantity` brought by a done move line - # is not available on the quants itself. This could be the result of an inventory - # adjustment that removed totally of partially `available_quantity`. When this happens, we - # chose to do nothing. This situation could not happen on MTS move, because in this case - # `available_quantity` is directly the quantity on the quants themselves. taken_quantity = 0 # Find a candidate move line to update or create a new one. @@ -995,7 +990,17 @@ class StockMove(models.Model): available_move_lines[(move_line.location_id, move_line.lot_id, move_line.result_package_id, move_line.owner_id)] -= move_line.product_qty for (location_id, lot_id, package_id, owner_id), quantity in available_move_lines.items(): need = move.product_qty - sum(move.move_line_ids.mapped('product_qty')) - taken_quantity = move._update_reserved_quantity(need, quantity, location_id, lot_id, package_id, owner_id) + # `quantity` is what is brought by chained done move lines. We double check + # here this quantity is available on the quants themselves. If not, this + # could be the result of an inventory adjustment that removed totally of + # partially `quantity`. When this happens, we chose to reserve the maximum + # still available. This situation could not happen on MTS move, because in + # this case `quantity` is directly the quantity on the quants themselves. + available_quantity = self.env['stock.quant']._get_available_quantity( + move.product_id, location_id, lot_id=lot_id, package_id=package_id, owner_id=owner_id, strict=True) + if float_is_zero(available_quantity, precision_rounding=move.product_id.uom_id.rounding): + continue + taken_quantity = move._update_reserved_quantity(need, min(quantity, available_quantity), location_id, lot_id, package_id, owner_id) if float_is_zero(taken_quantity, precision_rounding=move.product_id.uom_id.rounding): continue if need - taken_quantity == 0.0: @@ -1077,6 +1082,9 @@ class StockMove(models.Model): break return extra_move + def _unreserve_initial_demand(self, new_move): + pass + def _action_done(self): self.filtered(lambda move: move.state == 'draft')._action_confirm() # MRP allows scrapping draft moves @@ -1117,9 +1125,7 @@ class StockMove(models.Model): move_line.write({'product_uom_qty': move_line.qty_done}) except UserError: pass - - # If you were already putting stock.move.lots on the next one in the work order, transfer those to the new move - move.move_line_ids.filtered(lambda x: x.qty_done == 0.0).write({'move_id': new_move, 'product_uom_qty': 0}) + move._unreserve_initial_demand(new_move) move.move_line_ids._action_done() # Check the consistency of the result packages; there should be an unique location across # the contained quants. diff --git a/addons/stock/report/report_stockpicking_operations.xml b/addons/stock/report/report_stockpicking_operations.xml index 6120e95adcc..f1259409334 100644 --- a/addons/stock/report/report_stockpicking_operations.xml +++ b/addons/stock/report/report_stockpicking_operations.xml @@ -99,6 +99,7 @@ <span t-if="o.state != 'done'" t-field="ml.product_uom_qty"/> <span t-if="o.state == 'done'" t-field="ml.qty_done"/> <span t-field="ml.product_uom_id" groups="uom.group_uom"/> + </td> <td width="20%" t-if="o.picking_type_id.code != 'incoming'"> <span t-esc="ml.location_id.display_name"/> @@ -115,12 +116,16 @@ </div> </td> <td width="15%" class=" text-center h6" t-if="has_serial_number"> - <img t-if="has_serial_number and (ml.lot_id or ml.lot_name)" t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('Code128', ml.lot_id.name, 600, 100)" style="width:100%;height:35px"/> + <img t-if="has_serial_number and (ml.lot_id or ml.lot_name)" t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s&humanreadable=1' % ('Code128', ml.lot_id.name, 600, 100)" style="width:100%;height:35px;"/> + </td> <td width="15%" class="text-center" t-if="has_barcode"> <t t-if="product_barcode != move.product_id.barcode"> <span t-if="move.product_id and move.product_id.barcode"> - <img t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('Code128', move.product_id.barcode, 600, 100)" style="width:100%;height:35px"/> + <img t-if="len(move.product_id.barcode) == 13" t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('EAN13', move.product_id.barcode, 600, 100)" style="width:100%;height:35px"/> + <img t-elif="len(move.product_id.barcode) == 8" t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('EAN8', move.product_id.barcode, 600, 100)" style="width:100%;height:35px"/> + <img t-else="" t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('Code128', move.product_id.barcode, 600, 100)" style="width:100%;height:35px"/> + </span> <t t-set="product_barcode" t-value="move.product_id.barcode"/> </t> diff --git a/addons/stock/tests/test_move.py b/addons/stock/tests/test_move.py index 28861355303..afa5560a298 100644 --- a/addons/stock/tests/test_move.py +++ b/addons/stock/tests/test_move.py @@ -1901,18 +1901,29 @@ class StockMove(TransactionCase): ml.qty_done = 1 res_dict_for_back_order = picking_pack_cust.button_validate() backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id')) - backorder_wizard.with_context(debug=True).process() + backorder_wizard.process() backorder = self.env['stock.picking'].search([('backorder_id', '=', picking_pack_cust.id)]) - backordered_ml = backorder.move_line_ids - quant_lot3 = self.env['stock.quant'].search([('lot_id', '=', backordered_ml.lot_id.id)]) + backordered_move = backorder.move_lines # due to the rounding, the backordered quantity is 0.999 ; we shoudln't be able to reserve # 0.999 on a tracked by serial number quant - self.assertEqual(backordered_ml.product_uom_qty, 0) - self.assertTrue(backordered_ml.lot_id) + backordered_move._action_assign() + self.assertEqual(backordered_move.reserved_availability, 0) # force the serial number and validate - backordered_ml.qty_done = 1 + lot3 = self.env['stock.production.lot'].search([('name', '=', "lot3")]) + backorder.write({'move_line_ids': [(0, 0, { + 'product_id': self.product2.id, + 'product_uom_id': self.uom_unit.id, + 'qty_done': 1, + 'product_uom_qty': 0, + 'lot_id': lot3.id, + 'package_id': False, + 'result_package_id': False, + 'location_id': backordered_move.location_id.id, + 'location_dest_id': backordered_move.location_dest_id.id, + 'move_id': backordered_move.id, + })]}) overprocessed_wizard = backorder.button_validate() overprocessed_wizard = self.env['stock.overprocessed.transfer'].browse(overprocessed_wizard['res_id']) @@ -1921,6 +1932,57 @@ class StockMove(TransactionCase): self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.customer_location), 3) self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.pack_location), 0) + def test_link_assign_10(self): + """ Test the assignment mechanism with partial availability. + """ + # make some stock: + # stock location: 2.0 + # pack location: -1.0 + self.env['stock.quant']._update_available_quantity(self.product1, self.stock_location, 2.0) + self.assertEqual(len(self.env['stock.quant']._gather(self.product1, self.stock_location)), 1.0) + + move_out = self.env['stock.move'].create({ + 'name': 'test_link_assign_out', + 'location_id': self.pack_location.id, + 'location_dest_id': self.customer_location.id, + 'product_id': self.product1.id, + 'product_uom': self.uom_unit.id, + 'product_uom_qty': 1.0, + }) + move_out._action_confirm() + move_out._action_assign() + move_out.quantity_done = 1.0 + move_out._action_done() + self.assertEqual(len(self.env['stock.quant']._gather(self.product1, self.pack_location)), 1.0) + + move_stock_pack = self.env['stock.move'].create({ + 'name': 'test_link_assign_1_1', + 'location_id': self.stock_location.id, + 'location_dest_id': self.pack_location.id, + 'product_id': self.product1.id, + 'product_uom': self.uom_unit.id, + 'product_uom_qty': 2.0, + }) + move_pack_cust = self.env['stock.move'].create({ + 'name': 'test_link_assign_1_2', + 'location_id': self.pack_location.id, + 'location_dest_id': self.customer_location.id, + 'product_id': self.product1.id, + 'product_uom': self.uom_unit.id, + 'product_uom_qty': 2.0, + }) + move_stock_pack.write({'move_dest_ids': [(4, move_pack_cust.id, 0)]}) + move_pack_cust.write({'move_orig_ids': [(4, move_stock_pack.id, 0)]}) + + (move_stock_pack + move_pack_cust)._action_confirm() + move_stock_pack._action_assign() + move_stock_pack.quantity_done = 2.0 + move_stock_pack._action_done() + self.assertEqual(len(move_pack_cust.move_line_ids), 1) + + self.assertAlmostEqual(move_pack_cust.reserved_availability, 1.0) + self.assertEqual(move_pack_cust.state, 'partially_available') + def test_use_unreserved_move_line_1(self): """ Test that validating a stock move linked to an untracked product reserved by another one correctly unreserves the other one. diff --git a/addons/stock_account/models/product.py b/addons/stock_account/models/product.py index 7d4ac1ac2a9..14807df4fc2 100644 --- a/addons/stock_account/models/product.py +++ b/addons/stock_account/models/product.py @@ -201,39 +201,45 @@ class ProductProduct(models.Model): fifo_automated_values[(row[0], row[1])] = (row[2], row[3], list(row[4])) for product in self: - if product.cost_method in ['standard', 'average']: - qty_available = product.with_context(company_owned=True).qty_available - price_used = product.standard_price - if to_date: - price_used = product.get_history_price( - self.env.user.company_id.id, - date=to_date, - ) - product.stock_value = price_used * qty_available - product.qty_at_date = qty_available - elif product.cost_method == 'fifo': - if to_date: - if product.product_tmpl_id.valuation == 'manual_periodic': - domain = [('product_id', '=', product.id), ('date', '<=', to_date)] + StockMove._get_all_base_domain() - moves = StockMove.search(domain) + if to_date: + price_used = product.get_history_price( + self.env.user.company_id.id, + date=to_date, + ) if product.cost_method in ['standard', 'average'] else 0.0 + if product.product_tmpl_id.valuation == 'manual_periodic': + domain = [('product_id', '=', product.id), ('date', '<=', to_date)] + StockMove._get_all_base_domain() + moves = StockMove.search(domain) + product.qty_at_date = product.with_context(company_owned=True, owner_id=False).qty_available + if product.cost_method == 'fifo': product.stock_value = sum(moves.mapped('value')) - product.qty_at_date = product.with_context(company_owned=True).qty_available product.stock_fifo_manual_move_ids = StockMove.browse(moves.ids) - elif product.product_tmpl_id.valuation == 'real_time': - valuation_account_id = product.categ_id.property_stock_valuation_account_id.id - value, quantity, aml_ids = fifo_automated_values.get((product.id, valuation_account_id)) or (0, 0, []) + elif product.cost_method in ['standard', 'average']: + product.stock_value = product.qty_at_date * price_used + elif product.product_tmpl_id.valuation == 'real_time': + valuation_account_id = product.categ_id.property_stock_valuation_account_id.id + value, quantity, aml_ids = fifo_automated_values.get((product.id, valuation_account_id)) or (0, 0, []) + product.qty_at_date = quantity + if product.cost_method == 'fifo': product.stock_value = value - product.qty_at_date = quantity product.stock_fifo_real_time_aml_ids = self.env['account.move.line'].browse(aml_ids) - else: - product.stock_value, moves = product._sum_remaining_values() - product.qty_at_date = product.with_context(company_owned=True).qty_available - if product.product_tmpl_id.valuation == 'manual_periodic': - product.stock_fifo_manual_move_ids = moves - elif product.product_tmpl_id.valuation == 'real_time': - valuation_account_id = product.categ_id.property_stock_valuation_account_id.id - value, quantity, aml_ids = fifo_automated_values.get((product.id, valuation_account_id)) or (0, 0, []) + elif product.cost_method in ['standard', 'average']: + product.stock_value = quantity * price_used + else: + if product.product_tmpl_id.valuation == 'manual_periodic': + product.qty_at_date = product.with_context(company_owned=True, owner_id=False).qty_available + if product.cost_method == 'fifo': + product.stock_value, product.stock_fifo_manual_move_ids = product._sum_remaining_values() + elif product.cost_method in ['standard', 'average']: + product.stock_value = product.qty_at_date * product.standard_price + elif product.product_tmpl_id.valuation == 'real_time': + valuation_account_id = product.categ_id.property_stock_valuation_account_id.id + value, quantity, aml_ids = fifo_automated_values.get((product.id, valuation_account_id)) or (0, 0, []) + product.qty_at_date = quantity + if product.cost_method == 'fifo': + product.stock_value = value product.stock_fifo_real_time_aml_ids = self.env['account.move.line'].browse(aml_ids) + elif product.cost_method in ['standard', 'average']: + product.stock_value = quantity * product.standard_price def action_valuation_at_date_details(self): """ Returns an action with either a list view of all the valued stock moves of `self` if the @@ -404,4 +410,3 @@ class ProductCategory(models.Model): 'message': _("Changing your cost method is an important change that will impact your inventory valuation. Are you sure you want to make that change?"), } } - diff --git a/addons/stock_account/models/stock.py b/addons/stock_account/models/stock.py index f7bdf08ffea..07cb19163d7 100644 --- a/addons/stock_account/models/stock.py +++ b/addons/stock_account/models/stock.py @@ -596,7 +596,8 @@ class StockMove(models.Model): def _create_account_move_line(self, credit_account_id, debit_account_id, journal_id): self.ensure_one() AccountMove = self.env['account.move'] - quantity = self.env.context.get('forced_quantity', self.product_qty if self._is_in() else -1 * self.product_qty) + quantity = self.env.context.get('forced_quantity', self.product_qty) + quantity = quantity if self._is_in() else -1 * quantity # Make an informative `ref` on the created account move to differentiate between classic # movements, vacuum and edition of past moves. diff --git a/addons/stock_account/tests/test_stockvaluation.py b/addons/stock_account/tests/test_stockvaluation.py index 5bba1036eab..200e91af00b 100644 --- a/addons/stock_account/tests/test_stockvaluation.py +++ b/addons/stock_account/tests/test_stockvaluation.py @@ -2079,6 +2079,8 @@ class TestStockValuation(TransactionCase): self.assertEqual(len(move1.account_move_ids), 1) + self.assertAlmostEqual(self.product1.qty_available, 10.0) + self.assertAlmostEqual(self.product1.qty_at_date, 10.0) self.assertEqual(self.product1.stock_value, 100) # --------------------------------------------------------------------- @@ -2121,6 +2123,8 @@ class TestStockValuation(TransactionCase): self.assertEqual(len(move2.account_move_ids), 1) + self.assertAlmostEqual(self.product1.qty_available, 20.0) + self.assertAlmostEqual(self.product1.qty_at_date, 20.0) self.assertEqual(self.product1.stock_value, 220) # --------------------------------------------------------------------- @@ -2165,6 +2169,8 @@ class TestStockValuation(TransactionCase): self.assertEqual(len(move3.account_move_ids), 1) + self.assertAlmostEqual(self.product1.qty_available, 12.0) + self.assertAlmostEqual(self.product1.qty_at_date, 12.0) self.assertEqual(self.product1.stock_value, 140) # --------------------------------------------------------------------- @@ -2198,6 +2204,7 @@ class TestStockValuation(TransactionCase): # Ending # --------------------------------------------------------------------- self.assertEqual(self.product1.qty_available, 6) + self.assertAlmostEqual(self.product1.qty_at_date, 6.0) self.assertEqual(self.product1.stock_value, 72) self.assertEqual(sum(self._get_stock_input_move_lines().mapped('debit')), 0) self.assertEqual(sum(self._get_stock_input_move_lines().mapped('credit')), 220) @@ -2553,8 +2560,33 @@ class TestStockValuation(TransactionCase): move2.move_line_ids.qty_done = 1.0 move2._action_done() + self.assertAlmostEqual(self.product1.qty_available, 2.0) + self.assertAlmostEqual(self.product1.qty_at_date, 2.0) self.assertAlmostEqual(self.product1.standard_price, 7.5) + def test_average_perpetual_5(self): + ''' Set owner on incoming move => no valuation ''' + self.product1.product_tmpl_id.cost_method = 'average' + + move1 = self.env['stock.move'].create({ + 'name': 'Receive 1 unit at 10', + 'location_id': self.supplier_location.id, + 'location_dest_id': self.stock_location.id, + 'product_id': self.product1.id, + 'product_uom': self.uom_unit.id, + 'product_uom_qty': 1.0, + 'price_unit': 10, + }) + move1._action_confirm() + move1._action_assign() + move1.move_line_ids.qty_done = 1.0 + move1.move_line_ids.owner_id = self.owner1.id + move1._action_done() + + self.assertAlmostEqual(self.product1.qty_available, 1.0) + self.assertAlmostEqual(self.product1.qty_at_date, 0.0) + self.assertAlmostEqual(self.product1.stock_value, 0.0) + def test_average_negative_1(self): """ Test edit in the past. Receive 10, send 20, edit the second move to only send 10. """ @@ -2837,6 +2869,77 @@ class TestStockValuation(TransactionCase): self.assertEqual(move7.value, 100.0) self.assertEqual(self.product1.standard_price, 10) + def test_average_manual_1(self): + ''' Set owner on incoming move => no valuation ''' + self.product1.product_tmpl_id.cost_method = 'average' + self.product1.product_tmpl_id.valuation = 'manual_periodic' + + move1 = self.env['stock.move'].create({ + 'name': 'Receive 1 unit at 10', + 'location_id': self.supplier_location.id, + 'location_dest_id': self.stock_location.id, + 'product_id': self.product1.id, + 'product_uom': self.uom_unit.id, + 'product_uom_qty': 1.0, + 'price_unit': 10, + }) + move1._action_confirm() + move1._action_assign() + move1.move_line_ids.qty_done = 1.0 + move1.move_line_ids.owner_id = self.owner1.id + move1._action_done() + + self.assertAlmostEqual(self.product1.qty_available, 1.0) + self.assertAlmostEqual(self.product1.qty_at_date, 0.0) + self.assertAlmostEqual(self.product1.stock_value, 0.0) + + def test_standard_perpetual_1(self): + ''' Set owner on incoming move => no valuation ''' + self.product1.product_tmpl_id.cost_method = 'standard' + + move1 = self.env['stock.move'].create({ + 'name': 'Receive 1 unit at 10', + 'location_id': self.supplier_location.id, + 'location_dest_id': self.stock_location.id, + 'product_id': self.product1.id, + 'product_uom': self.uom_unit.id, + 'product_uom_qty': 1.0, + 'price_unit': 10, + }) + move1._action_confirm() + move1._action_assign() + move1.move_line_ids.qty_done = 1.0 + move1.move_line_ids.owner_id = self.owner1.id + move1._action_done() + + self.assertAlmostEqual(self.product1.qty_available, 1.0) + self.assertAlmostEqual(self.product1.qty_at_date, 0.0) + self.assertAlmostEqual(self.product1.stock_value, 0.0) + + def test_standard_manual_1(self): + ''' Set owner on incoming move => no valuation ''' + self.product1.product_tmpl_id.cost_method = 'standard' + self.product1.product_tmpl_id.valuation = 'manual_periodic' + + move1 = self.env['stock.move'].create({ + 'name': 'Receive 1 unit at 10', + 'location_id': self.supplier_location.id, + 'location_dest_id': self.stock_location.id, + 'product_id': self.product1.id, + 'product_uom': self.uom_unit.id, + 'product_uom_qty': 1.0, + 'price_unit': 10, + }) + move1._action_confirm() + move1._action_assign() + move1.move_line_ids.qty_done = 1.0 + move1.move_line_ids.owner_id = self.owner1.id + move1._action_done() + + self.assertAlmostEqual(self.product1.qty_available, 1.0) + self.assertAlmostEqual(self.product1.qty_at_date, 0.0) + self.assertAlmostEqual(self.product1.stock_value, 0.0) + def test_change_cost_method_1(self): """ Change the cost method from FIFO to AVCO. """ @@ -2889,6 +2992,8 @@ class TestStockValuation(TransactionCase): move3.move_line_ids.qty_done = 1.0 move3._action_done() + self.assertAlmostEqual(self.product1.qty_available, 19) + self.assertAlmostEqual(self.product1.qty_at_date, 19) self.assertEqual(self.product1.stock_value, 240) # --------------------------------------------------------------------- @@ -2957,6 +3062,8 @@ class TestStockValuation(TransactionCase): move3.move_line_ids.qty_done = 1.0 move3._action_done() + self.assertAlmostEqual(self.product1.qty_available, 19) + self.assertAlmostEqual(self.product1.qty_at_date, 19) self.assertEqual(self.product1.stock_value, 240) # --------------------------------------------------------------------- @@ -3030,6 +3137,8 @@ class TestStockValuation(TransactionCase): self.assertEqual(move1.value, 10) self.assertEqual(move1.remaining_value, 10) self.assertEqual(move1.remaining_qty, 1) + self.assertAlmostEqual(self.product1.qty_available, 0.0) + self.assertAlmostEqual(self.product1.qty_at_date, 2.0) self.assertEqual(self.product1.stock_value, 10) self.assertTrue(len(move1.account_move_ids), 1) @@ -3179,8 +3288,10 @@ class TestStockValuation(TransactionCase): move1.move_line_ids.qty_done = 10 move1._action_done() move1.date = date2 + move1.account_move_ids.write({'date': date2}) self.assertEqual(self.product1.qty_available, 10) + self.assertAlmostEqual(self.product1.qty_at_date, 10.0) self.assertEqual(self.product1.stock_value, 100) # receive 20 @@ -3197,8 +3308,10 @@ class TestStockValuation(TransactionCase): move2.move_line_ids.qty_done = 20 move2._action_done() move2.date = date3 + move2.account_move_ids.write({'date': date3}) self.assertEqual(self.product1.qty_available, 30) + self.assertAlmostEqual(self.product1.qty_at_date, 30.0) self.assertEqual(self.product1.stock_value, 300) # send 15 @@ -3215,8 +3328,10 @@ class TestStockValuation(TransactionCase): move3.move_line_ids.qty_done = 15 move3._action_done() move3.date = date4 + move3.account_move_ids.write({'date': date4}) self.assertEqual(self.product1.qty_available, 15) + self.assertAlmostEqual(self.product1.qty_at_date, 15.0) self.assertEqual(self.product1.stock_value, 150) # set the standard price to 5 @@ -3224,6 +3339,7 @@ class TestStockValuation(TransactionCase): self.env['product.price.history'].search([('product_id', '=', self.product1.id)], order='datetime desc, id DESC', limit=1).datetime = date5 self.assertEqual(self.product1.qty_available, 15) + self.assertAlmostEqual(self.product1.qty_at_date, 15.0) self.assertEqual(self.product1.stock_value, 75) # send 20 @@ -3240,8 +3356,10 @@ class TestStockValuation(TransactionCase): move4.move_line_ids.qty_done = 20 move4._action_done() move4.date = date6 + move4.account_move_ids.write({'date': date6}) self.assertEqual(self.product1.qty_available, -5) + self.assertAlmostEqual(self.product1.qty_at_date, -5.0) self.assertEqual(self.product1.stock_value, -25) # set the standard price to 7.5 @@ -3262,11 +3380,13 @@ class TestStockValuation(TransactionCase): move5.move_line_ids.qty_done = 100 move5._action_done() move5.date = date8 + move5.account_move_ids.write({'date': date8}) self.assertEqual(self.product1.qty_available, 95) + self.assertAlmostEqual(self.product1.qty_at_date, 95.0) self.assertEqual(self.product1.stock_value, 712.5) - # Quantity at date + # Quantity available at date self.assertEqual(self.product1.with_context(to_date=Date.to_string(date1)).qty_available, 0) self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).qty_available, 10) self.assertEqual(self.product1.with_context(to_date=Date.to_string(date3)).qty_available, 30) @@ -3284,12 +3404,25 @@ class TestStockValuation(TransactionCase): self.assertEqual(self.product1.with_context(to_date=Date.to_string(date6)).stock_value, -25) self.assertEqual(self.product1.with_context(to_date=Date.to_string(date8)).stock_value, 712.5) + # Quantity at date + self.assertAlmostEqual(self.product1.with_context(to_date=Date.to_string(date1)).qty_at_date, 0.0) + self.assertAlmostEqual(self.product1.with_context(to_date=Date.to_string(date2)).qty_at_date, 10.0) + self.assertAlmostEqual(self.product1.with_context(to_date=Date.to_string(date3)).qty_at_date, 30.0) + self.assertAlmostEqual(self.product1.with_context(to_date=Date.to_string(date4)).qty_at_date, 15.0) + self.assertAlmostEqual(self.product1.with_context(to_date=Date.to_string(date5)).qty_at_date, 15.0) + self.assertAlmostEqual(self.product1.with_context(to_date=Date.to_string(date6)).qty_at_date, -5.0) + self.assertAlmostEqual(self.product1.with_context(to_date=Date.to_string(date7)).qty_at_date, -5.0) + self.assertAlmostEqual(self.product1.with_context(to_date=Date.to_string(date8)).qty_at_date, 95.0) + # edit the done quantity of move1, decrease it self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).qty_available, 10) + self.assertAlmostEqual(self.product1.with_context(to_date=Date.to_string(date2)).qty_at_date, 10.0) move1.quantity_done = 5 + move1.account_move_ids.write({'date': date2}) # the quantity at date will reflect the change directly self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).qty_available, 5) + self.assertAlmostEqual(self.product1.with_context(to_date=Date.to_string(date2)).qty_at_date, 5.0) # as when we decrease a quantity on a recreipt, we consider it as a out move with the price # of today, the value will be decrease of 100 - (5*7.5) @@ -3301,12 +3434,17 @@ class TestStockValuation(TransactionCase): # edit move 4, send 15 instead of 20 # we now have +5 + 20 - 15 -20 = -10 * a standard price of 5 + self.assertAlmostEqual(self.product1.with_context(to_date=Date.to_string(date6)).qty_available, -10.0) + self.assertAlmostEqual(self.product1.with_context(to_date=Date.to_string(date6)).qty_at_date, -10.0) self.assertEqual(self.product1.with_context(to_date=Date.to_string(date6)).stock_value, -50) move4.quantity_done = 15 + move4.account_move_ids.write({'date': date6}) # -(20*5) + (5*7.5) self.assertEqual(move4.value, -62.5) # we now have +5 + 20 - 15 -15 = -5 * a standard price of 5 + self.assertAlmostEqual(self.product1.with_context(to_date=Date.to_string(date6)).qty_available, -5.0) + self.assertAlmostEqual(self.product1.with_context(to_date=Date.to_string(date6)).qty_at_date, -5.0) self.assertEqual(self.product1.with_context(to_date=Date.to_string(date6)).stock_value, -25) def test_at_date_fifo_1(self): @@ -3342,6 +3480,7 @@ class TestStockValuation(TransactionCase): move1.account_move_ids.write({'date': date1}) self.assertEqual(self.product1.qty_available, 10) + self.assertAlmostEqual(self.product1.qty_at_date, 10.0) self.assertEqual(self.product1.stock_value, 100) # receive 10@12 @@ -3362,6 +3501,7 @@ class TestStockValuation(TransactionCase): move2.account_move_ids.write({'date': date2}) self.assertEqual(self.product1.qty_available, 20) + self.assertAlmostEqual(self.product1.qty_at_date, 20) self.assertEqual(self.product1.stock_value, 220) # send 15 @@ -3381,6 +3521,7 @@ class TestStockValuation(TransactionCase): move3.account_move_ids.write({'date': date3}) self.assertEqual(self.product1.qty_available, 5) + self.assertAlmostEqual(self.product1.qty_at_date, 5.0) self.assertEqual(self.product1.stock_value, 60) # send 20 @@ -3400,6 +3541,7 @@ class TestStockValuation(TransactionCase): move4.account_move_ids.write({'date': date4}) self.assertEqual(self.product1.qty_available, -15) + self.assertAlmostEqual(self.product1.qty_at_date, -15.0) self.assertEqual(self.product1.stock_value, -180) # receive 100@15 @@ -3420,6 +3562,7 @@ class TestStockValuation(TransactionCase): move5.account_move_ids.write({'date': date5}) self.assertEqual(self.product1.qty_available, 85) + self.assertAlmostEqual(self.product1.qty_at_date, 85.0) self.assertEqual(self.product1.stock_value, 1320) # run the vacuum to compensate the negative stock move @@ -3427,6 +3570,7 @@ class TestStockValuation(TransactionCase): move4.account_move_ids[0].write({'date': date6}) self.assertEqual(self.product1.qty_available, 85) + self.assertAlmostEqual(self.product1.qty_at_date, 85.0) self.assertEqual(self.product1.stock_value, 1275) # Edit the quantity done of move1, increase it. @@ -3499,6 +3643,7 @@ class TestStockValuation(TransactionCase): move1.account_move_ids.write({'date': date1}) self.assertEqual(self.product1.qty_available, 10) + self.assertAlmostEqual(self.product1.qty_at_date, 10.0) self.assertEqual(self.product1.stock_value, 100) # receive 10@15 @@ -3519,6 +3664,7 @@ class TestStockValuation(TransactionCase): move2.account_move_ids.write({'date': date2}) self.assertEqual(self.product1.qty_available, 20) + self.assertAlmostEqual(self.product1.qty_at_date, 20.0) self.assertEqual(self.product1.stock_value, 250) # send 30 @@ -3538,6 +3684,7 @@ class TestStockValuation(TransactionCase): move3.account_move_ids.write({'date': date3}) self.assertEqual(self.product1.qty_available, -10) + self.assertAlmostEqual(self.product1.qty_at_date, -10.0) self.assertEqual(self.product1.stock_value, -150) # receive 10@20 @@ -3558,6 +3705,7 @@ class TestStockValuation(TransactionCase): move4.account_move_ids.write({'date': date4}) self.assertEqual(self.product1.qty_available, 0) + self.assertAlmostEqual(self.product1.qty_at_date, 0.0) self.assertEqual(self.product1.stock_value, 50) # receive 10@10 @@ -3578,6 +3726,7 @@ class TestStockValuation(TransactionCase): move5.account_move_ids.write({'date': date5}) self.assertEqual(self.product1.qty_available, 10) + self.assertAlmostEqual(self.product1.qty_at_date, 10.0) self.assertEqual(self.product1.stock_value, 150) # run the vacuum to compensate the negative stock move @@ -3585,6 +3734,7 @@ class TestStockValuation(TransactionCase): move3.account_move_ids[0].write({'date': date6}) self.assertEqual(self.product1.qty_available, 10) + self.assertAlmostEqual(self.product1.qty_at_date, 10.0) self.assertEqual(self.product1.stock_value, 100) # --------------------------------------------------------------------- diff --git a/addons/test_mail/tests/test_mail_activity.py b/addons/test_mail/tests/test_mail_activity.py index e8b9c980480..dcd3a4eeca7 100644 --- a/addons/test_mail/tests/test_mail_activity.py +++ b/addons/test_mail/tests/test_mail_activity.py @@ -1,17 +1,20 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from datetime import date +from datetime import date, datetime from dateutil.relativedelta import relativedelta from unittest.mock import patch from unittest.mock import DEFAULT -from odoo import exceptions +import pytz + +from odoo import exceptions, tests from odoo.addons.test_mail.tests.common import BaseFunctionalTest from odoo.addons.test_mail.models.test_mail_models import MailTestActivity from odoo.tools import mute_logger +@tests.tagged('mail_activity') class TestMailActivity(BaseFunctionalTest): @classmethod @@ -73,14 +76,18 @@ class TestMailActivity(BaseFunctionalTest): }) def test_activity_mixin(self): - today = date.today() + self.user_employee.tz = self.user_admin.tz with self.sudoAs('ernest'): self.assertEqual(self.test_record.env.user, self.user_employee) + now_utc = datetime.now(pytz.UTC) + now_user = now_utc.astimezone(pytz.timezone(self.env.user.tz or 'UTC')) + today_user = now_user.date() + # Test various scheduling of activities act1 = self.test_record.activity_schedule( 'test_mail.mail_act_test_todo', - today + relativedelta(days=1), + today_user + relativedelta(days=1), user_id=self.user_admin.id) self.assertEqual(act1.automated, True) @@ -91,13 +98,13 @@ class TestMailActivity(BaseFunctionalTest): act2 = self.test_record.activity_schedule( 'test_mail.mail_act_test_meeting', - today + relativedelta(days=-1)) + today_user + relativedelta(days=-1)) self.assertEqual(self.test_record.activity_state, 'overdue') self.assertEqual(self.test_record.activity_user_id, self.user_employee) act3 = self.test_record.activity_schedule( 'test_mail.mail_act_test_todo', - today + relativedelta(days=3), + today_user + relativedelta(days=3), user_id=self.user_employee.id) self.assertEqual(self.test_record.activity_state, 'overdue') self.assertEqual(self.test_record.activity_user_id, self.user_employee) @@ -116,7 +123,7 @@ class TestMailActivity(BaseFunctionalTest): self.assertEqual(self.test_record.activity_state, 'overdue') self.test_record.activity_reschedule( ['test_mail.mail_act_test_meeting', 'test_mail.mail_act_test_todo'], - date_deadline=today + relativedelta(days=3) + date_deadline=today_user + relativedelta(days=3) ) self.assertEqual(self.test_record.activity_state, 'planned') diff --git a/addons/web/static/lib/qweb/qweb-test-widgets.xml b/addons/web/static/lib/qweb/qweb-test-widgets.xml new file mode 100644 index 00000000000..503880bcc34 --- /dev/null +++ b/addons/web/static/lib/qweb/qweb-test-widgets.xml @@ -0,0 +1,26 @@ +<templates> + <t t-name="date-simple"><t t-esc='value' /></t> + <params id="date-simple">{"value": "1988-09-16"}</params> + <result id="date-simple">1988-09-16</result> + + <t t-name="datetime-simple"><t t-esc='value' /></t> + <params id="datetime-simple">{"value": "1988-09-16 14:00:00"}</params> + <result id="datetime-simple">1988-09-16 14:00:00</result> + + <t t-name="datetime-widget-datetime"><t t-esc='value' t-options="{'widget': 'datetime'}" /></t> + <params id="datetime-widget-datetime">{"value": "1988-09-16 14:00:00"}</params> + <result id="datetime-widget-datetime">09/16/1988 16:00:00</result> + + <t t-name="datetime-widget-date"><t t-esc='value' t-options="{'widget': 'date'}" /></t> + <params id="datetime-widget-date">{"value": "1988-09-16 14:00:00"}</params> + <result id="datetime-widget-date">09/16/1988</result> + + <t t-name="datetime-widget-date-tz2"><t t-esc='value' t-options="{'widget': 'date'}" /></t> + <params id="datetime-widget-date-tz2">{"value": "1988-09-16 01:00:00"}</params> + <result id="datetime-widget-date-tz2">09/16/1988</result> + + <t t-name="datetime-widget-date-tz"><t t-esc='value' t-options="{'widget': 'date'}" /></t> + <params id="datetime-widget-date-tz">{"value": "1988-09-16 23:00:00"}</params> + <result id="datetime-widget-date-tz">09/17/1988</result> + +</templates> diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 01b4cb4371d..43b4e349a66 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -498,7 +498,13 @@ var FieldDate = InputField.extend({ * @private */ _makeDatePicker: function () { - return new datepicker.DateWidget(this, {defaultDate: this.value}); + return new datepicker.DateWidget( + this, + _.defaults( + this.nodeOptions.datepicker || {}, + {defaultDate: this.value} + ) + ); }, /** diff --git a/addons/web_editor/static/lib/summernote/src/js/module/Editor.js b/addons/web_editor/static/lib/summernote/src/js/module/Editor.js index b7ba30bfcd1..99947c346cf 100644 --- a/addons/web_editor/static/lib/summernote/src/js/module/Editor.js +++ b/addons/web_editor/static/lib/summernote/src/js/module/Editor.js @@ -628,9 +628,9 @@ define([ } var anchors = []; - // ODOO: adding this branch to modify existing anchor + // ODOO: adding this branch to modify existing anchor if it fully contains the range var ancestor_anchor = dom.ancestor(rng.sc, dom.isAnchor); - if(ancestor_anchor) { + if(ancestor_anchor && ancestor_anchor === dom.ancestor(rng.ec, dom.isAnchor)) { anchors.push($(ancestor_anchor).html(linkText).get(0)); } else if (isTextChanged) { // Create a new link when text changed. diff --git a/addons/web_editor/static/src/js/editor/rte.summernote.js b/addons/web_editor/static/src/js/editor/rte.summernote.js index ce20c53ff49..14c0e26cab9 100644 --- a/addons/web_editor/static/src/js/editor/rte.summernote.js +++ b/addons/web_editor/static/src/js/editor/rte.summernote.js @@ -488,7 +488,7 @@ function prettify_html(html) { while (i--) space += ' '; return space; }, - reg = /^<\/?(a|span|font|strong|u|i|strong|b)(\s|>)/i, + reg = /^<\/?(a|span|font|u|em|i|strong|b)(\s|>)/i, inline_level = Infinity, tokens = _.compact(_.flatten(_.map(html.split(/</), function (value) { value = value.replace(/\s+/g, ' ').split(/>/); diff --git a/addons/web_editor/static/src/js/widgets/widgets.js b/addons/web_editor/static/src/js/widgets/widgets.js index ab8f166d221..d0df042fa82 100644 --- a/addons/web_editor/static/src/js/widgets/widgets.js +++ b/addons/web_editor/static/src/js/widgets/widgets.js @@ -1406,6 +1406,8 @@ var LinkDialog = Dialog.extend({ if (dom.ancestor(nodes[i], dom.isImg)) { this.data.images.push(dom.ancestor(nodes[i], dom.isImg)); text += '[IMG]'; + } else if (!is_link && nodes[i].nodeType === 1) { + // just use text nodes from listBetween } else if (!is_link && i===0) { text += nodes[i].textContent.slice(so, Infinity); } else if (!is_link && i===nodes.length-1) { diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index 0e5443ad79e..aa703071d9b 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -6,6 +6,7 @@ import traceback import os import unittest +import pytz import werkzeug import werkzeug.routing import werkzeug.utils @@ -74,6 +75,10 @@ class Http(models.AbstractModel): context = {} if not request.context.get('tz'): context['tz'] = request.session.get('geoip', {}).get('time_zone') + try: + pytz.timezone(context['tz'] or '') + except pytz.UnknownTimeZoneError: + context.pop('tz') request.website = request.env['website'].get_current_website() # can use `request.env` since auth methods are called context['website_id'] = request.website.id diff --git a/addons/website_event/controllers/main.py b/addons/website_event/controllers/main.py index a06d9500233..bc1edfc5bb9 100644 --- a/addons/website_event/controllers/main.py +++ b/addons/website_event/controllers/main.py @@ -264,7 +264,7 @@ class WebsiteEventController(http.Controller): urls = event._get_event_resource_urls(Attendees.ids) return request.render("website_event.registration_complete", { - 'attendees': Attendees, + 'attendees': Attendees.sudo(), 'event': event, 'google_url': urls.get('google_url'), 'iCal_url': urls.get('iCal_url') diff --git a/addons/website_event/static/src/js/website_event.js b/addons/website_event/static/src/js/website_event.js index ebe38118559..53a304c707e 100644 --- a/addons/website_event/static/src/js/website_event.js +++ b/addons/website_event/static/src/js/website_event.js @@ -59,12 +59,16 @@ var EventRegistrationForm = Widget.extend({ $button.attr('disabled', true); return ajax.jsonRpc($form.attr('action'), 'call', post).then(function (modal) { var $modal = $(modal); + $modal.modal({backdrop: 'static', keyboard: false}); $modal.find('.modal-body > div').removeClass('container'); // retrocompatibility - REMOVE ME in master / saas-19 $modal.insertAfter($form).modal(); $modal.on('click', '.js_goto_event', function () { $modal.modal('hide'); $button.prop('disabled', false); }); + $modal.on('click', '.close', function () { + $button.prop('disabled', false); + }); }); } }, diff --git a/addons/website_event_track/views/event_track_templates.xml b/addons/website_event_track/views/event_track_templates.xml index 70ed14e680a..dbfceeb8ca6 100644 --- a/addons/website_event_track/views/event_track_templates.xml +++ b/addons/website_event_track/views/event_track_templates.xml @@ -50,8 +50,8 @@ <input type="text" class="form-control" placeholder="Filter Tracks..." id="event_track_search"/> </div> </section> - <t t-set="dayslist" t-value="days.keys()"/> - <t t-set="dayslist2" t-value="list(dayslist).sort()"/> <!-- display days in the right order --> + <t t-set="dayslist" t-value="list(days.keys())"/> + <t t-set="dayslist2" t-value="dayslist.sort()"/> <!-- display days in the right order --> <section class="container" t-foreach="dayslist" t-as="day"> <t t-set="locations" t-value="days[day]['locations']"/> <t t-set="dates" t-value="days[day]['dates']"/> diff --git a/addons/website_forum/models/forum.py b/addons/website_forum/models/forum.py index bb01a3fc3f9..7186e19f112 100644 --- a/addons/website_forum/models/forum.py +++ b/addons/website_forum/models/forum.py @@ -422,6 +422,11 @@ class Post(models.Model): raise KarmaError('User karma not sufficient to post an image or link.') return content + @api.constrains('parent_id') + def _check_parent_id(self): + if not self._check_recursion(): + raise ValidationError(_('You cannot create recursive forum posts.')) + @api.model def create(self, vals): if 'content' in vals and vals.get('forum_id'): diff --git a/addons/website_livechat/controllers/main.py b/addons/website_livechat/controllers/main.py index 753e4eef1ae..31af89c2e63 100644 --- a/addons/website_livechat/controllers/main.py +++ b/addons/website_livechat/controllers/main.py @@ -20,13 +20,17 @@ class WebsiteLivechat(http.Controller): @http.route('/livechat/channel/<model("im_livechat.channel"):channel>', type='http', auth='public', website=True) def channel_rating(self, channel, **kw): # get the last 100 ratings and the repartition per grade - ratings = request.env['rating.rating'].search([('res_model', '=', 'mail.channel'), ('res_id', 'in', channel.sudo().channel_ids.ids)], order='create_date desc', limit=100) - repartition = channel.sudo().channel_ids.rating_get_grades() + domain = [ + ('res_model', '=', 'mail.channel'), ('res_id', 'in', channel.sudo().channel_ids.ids), + ('consumed', '=', True), ('rating', '>=', 1), + ] + ratings = request.env['rating.rating'].search(domain, order='create_date desc', limit=100) + repartition = channel.sudo().channel_ids.rating_get_grades(domain=domain) # compute percentage percentage = dict.fromkeys(['great', 'okay', 'bad'], 0) for grade in repartition: - percentage[grade] = repartition[grade] * 100 / sum(repartition.values()) if sum(repartition.values()) else 0 + percentage[grade] = round(repartition[grade] * 100.0 / sum(repartition.values()), 1) if sum(repartition.values()) else 0 # the value dict to render the template values = { diff --git a/addons/website_mass_mailing/controllers/main.py b/addons/website_mass_mailing/controllers/main.py index d1aa21f5cd4..455ab1bdae0 100644 --- a/addons/website_mass_mailing/controllers/main.py +++ b/addons/website_mass_mailing/controllers/main.py @@ -11,7 +11,7 @@ class MassMailController(MassMailController): def mailing(self, mailing_id, email=None, res_id=None, **post): mailing = request.env['mail.mass_mailing'].sudo().browse(mailing_id) if mailing.exists(): - if mailing.mailing_model_name == 'mail.mass_mailing.contact': + if mailing.mailing_model_real == 'mail.mass_mailing.contact': contacts = request.env['mail.mass_mailing.contact'].sudo().search([('email', '=', email)]) return request.render('website_mass_mailing.page_unsubscribe', { 'contacts': contacts, diff --git a/addons/website_sale/views/sale_order_views.xml b/addons/website_sale/views/sale_order_views.xml index f9f409351f7..26275bd265b 100644 --- a/addons/website_sale/views/sale_order_views.xml +++ b/addons/website_sale/views/sale_order_views.xml @@ -117,7 +117,7 @@ <record id="action_view_unpaid_quotation_tree" model="ir.actions.act_window"> <field name="name">Unpaid Orders</field> <field name="res_model">sale.order</field> - <field name="view_mode">tree,kanban</field> + <field name="view_mode">tree,kanban,form</field> <field name="view_type">form</field> <field name="domain">[('state', '=', 'sent'), ('team_id.team_type', '=', 'website')]</field> <field name="context" eval="{'show_sale': True, 'create': False}"/> @@ -135,7 +135,7 @@ <field name="name">Abandoned Carts</field> <field name="res_model">sale.order</field> <field name="view_type">form</field> - <field name="view_mode">tree,kanban</field> + <field name="view_mode">tree,kanban,form</field> <field name="domain">[('state', '=', 'draft'), ('order_line', '!=', False), ('partner_id', '!=', context.get('public_partner_id')), ('team_id.team_type', '=', 'website'), ('date_order', '<=', (datetime.datetime.utcnow() - datetime.timedelta(hours=1)).strftime('%Y-%m-%d %H:%M:%S'))]</field> <field name="context" eval="{'show_sale': True, 'create': False, 'public_partner_id': ref('base.public_partner')}"/> <field name="view_id" ref="sale.view_quotation_tree"/> diff --git a/addons/website_sale_stock/models/product_product.py b/addons/website_sale_stock/models/product_product.py index 829efd3f2dc..cfab171bb32 100644 --- a/addons/website_sale_stock/models/product_product.py +++ b/addons/website_sale_stock/models/product_product.py @@ -11,7 +11,7 @@ class ProductProduct(models.Model): cart_qty = fields.Integer(compute='_compute_cart_qty') def _compute_cart_qty(self): - website = getattr(request, 'website', None) + website = request and getattr(request, 'website', None) if not website: return cart = website.sale_get_order() diff --git a/addons/website_sale_wishlist/models/product_wishlist.py b/addons/website_sale_wishlist/models/product_wishlist.py index 6c73cf50608..381d5eceb45 100644 --- a/addons/website_sale_wishlist/models/product_wishlist.py +++ b/addons/website_sale_wishlist/models/product_wishlist.py @@ -36,14 +36,15 @@ class ProductWishlist(models.Model): @api.model def current(self): - """Get all wishlist items that belong to current user or session.""" - return self.search([ + """Get all wishlist items that belong to current user or session, + filter products that are unpublished.""" + return self.sudo().search([ "|", ("partner_id", "=", self.env.user.partner_id.id), "&", ("partner_id", "=", False), ("session", "=", self.env.user.current_session), - ]) + ]).filtered('product_id.product_tmpl_id.website_published') @api.model def _add_to_wishlist(self, pricelist_id, currency_id, website_id, price, product_id, partner_id=False, session=False): diff --git a/doc/cla/corporate/adhoc.md b/doc/cla/corporate/adhoc.md index 627065bafab..428f46b0056 100644 --- a/doc/cla/corporate/adhoc.md +++ b/doc/cla/corporate/adhoc.md @@ -13,3 +13,4 @@ List of contributors: Damián Soriano ds@adhoc.com.ar https://github.com/damiansoriano Juan José Scarafía jjs@adhoc.com.ar https://github.com/jjscarafia Nicolás Mac Rouillon nmr@adhoc.com.ar https://github.com/nicomacr +Katherine Zaoral kz@adhoc.com.ar https://github.com/zaoral diff --git a/doc/cla/corporate/eficent.md b/doc/cla/corporate/eficent.md index 284e2b7b691..70184f115c8 100644 --- a/doc/cla/corporate/eficent.md +++ b/doc/cla/corporate/eficent.md @@ -14,7 +14,6 @@ List of contributors: Aarón Henríquez ahenriquez@eficent.com https://github.com/aheficent Lois Rilo lois.rilo@eficent.com https://github.com/lreficent -Roser Garcia roser.garcia@eficent.com https://github.com/rgarnau Miquel Raich miquel.raich@eficent.com https://github.com/mreficent Jordi Ballester jordi.ballester@eficent.com https://github.com/jbeficent Hector Villarreal hector.villarreal@eficent.com https://github.com/hveficent diff --git a/doc/cla/corporate/modoolar.md b/doc/cla/corporate/modoolar.md new file mode 100644 index 00000000000..a3ee461fab4 --- /dev/null +++ b/doc/cla/corporate/modoolar.md @@ -0,0 +1,19 @@ +Serbia, 2018-06-11 + +Modoolar agrees to the terms of the Odoo Corporate Contributor License +Agreement v1.0. + +I declare that I am authorized and able to make this agreement and sign this +declaration. + +Signed, + +Petar Najman petar.najman@modoolar.com https://github.com/pnajman-modoolar + +List of contributors: + +- Aleksandar Gajić aleksandar.gajic@modoolar.com https://github.com/agajic-modoolar +- Igor Jovanović igor.jovanovic@modoolar.com https://github.com/ijovanovic-modoolar +- Mladen Meseldžija mladen.meseldzija@modoolar.com https://github.com/mmeseldzija-modoolar +- Petar Najman petar.najman@modoolar.com https://github.com/pnajman-modoolar +- Slađan Kantar sladjan.kantar@modoolar.com https://github.com/skantar diff --git a/doc/cla/corporate/shine-it.md b/doc/cla/corporate/shine-it.md new file mode 100644 index 00000000000..975f9d885f4 --- /dev/null +++ b/doc/cla/corporate/shine-it.md @@ -0,0 +1,17 @@ +China, 2018-04-28 + +Shine IT agrees to the terms of the Odoo Corporate Contributor License +Agreement v1.0. + +I declare that I am authorized and able to make this agreement and sign this +declaration. + +Signed, + +Tony Gu tony@openerp.cn https://github.com/digitalsatori + +List of contributors: +Tony Gu tony@openerp.cn https://github.com/digitalsatori +Joshua Jan joshua@openerp.cn https://github.com/joshuajan +Xiao Guo xerxes@openerp.cn https://github.com/xerxesnoPT + diff --git a/doc/cla/corporate/tvtmarine-automation.md b/doc/cla/corporate/tvtmarine-automation.md index de0906f0331..59e3c250ab3 100644 --- a/doc/cla/corporate/tvtmarine-automation.md +++ b/doc/cla/corporate/tvtmarine-automation.md @@ -13,7 +13,7 @@ David Tran david.tran@tvtmarine.com https://github.com/tvtma/ List of contributors: David Tran david.tran@tvtmarine.com https://github.com/davidtranhp -Long Do dhlong.1209@gmail.com https://github.com/hoanglong87 +Long Do long.do@tvtmarine.com https://github.com/hoanglong87 Hao Hoang hao.hoang@ma.tvtmarine.com https://github.com/hoanghao2001 Tommy Tran tu.tran@tvtmarine.com https://github.com/tutran81 -Emily Ha emily.ha@tvtmarine.com https://github.com/emilyha
\ No newline at end of file +Emily Ha emily.ha@tvtmarine.com https://github.com/emilyha diff --git a/doc/cla/individual/Zelwak.md b/doc/cla/individual/Zelwak.md new file mode 100644 index 00000000000..40c8f303d42 --- /dev/null +++ b/doc/cla/individual/Zelwak.md @@ -0,0 +1,11 @@ + + +France, 2018-06-07 + +I here by agree to the terms of the Odoo Individual Contributor License Agreement v1.0. + +I declare that I am authorized and able to make this agreement and sign this declaration. + +Signed, + +Flavien CHÊNE me@flavienchene.fr https://github.com/Zelwak diff --git a/doc/cla/individual/mduvergey.md b/doc/cla/individual/mduvergey.md new file mode 100644 index 00000000000..3b9422711ec --- /dev/null +++ b/doc/cla/individual/mduvergey.md @@ -0,0 +1,11 @@ +France, 2018-05-24 + +I hereby agree to the terms of the Odoo Individual Contributor License +Agreement v1.0. + +I declare that I am authorized and able to make this agreement and sign this +declaration. + +Signed, + +Martin Duvergey martin.duvergey@gpsante.fr https://github.com/mduvergey diff --git a/doc/cla/individual/schout-it.md b/doc/cla/individual/schout-it.md new file mode 100644 index 00000000000..35451db875d --- /dev/null +++ b/doc/cla/individual/schout-it.md @@ -0,0 +1,11 @@ +Belgium, 2018-05-17 + +I hereby agree to the terms of the Odoo Individual Contributor License +Agreement v1.0. + +I declare that I am authorized and able to make this agreement and sign this +declaration. + +Signed, + +Rod Schouteden rod@schout-it.be https://github.com/schout-it diff --git a/doc/howtos/themes.rst b/doc/howtos/themes.rst index 9b715ec7a05..a4ca988306f 100644 --- a/doc/howtos/themes.rst +++ b/doc/howtos/themes.rst @@ -686,7 +686,7 @@ The previous code will create the snippet’s content, but we still need to plac .. code-block:: xml <template id="place_into_bar" inherit_id="website.snippets" name="Place into bar"> - <xpath expr="//div[@id='snippet_content']/div[@class='o_panel_body']" position="inside"> + <xpath expr="//div[@id='snippet_structure']/div[@class='o_panel_body']" position="inside"> <t t-snippet="theme_tutorial.snippet_testimonial" t-thumbnail="/theme_tutorial/static/src/img/ui/snippet_thumb.jpg"/> </xpath> diff --git a/doc/reference/cmdline.rst b/doc/reference/cmdline.rst index 4171f12c5e1..12cd5f7a9d8 100644 --- a/doc/reference/cmdline.rst +++ b/doc/reference/cmdline.rst @@ -221,6 +221,45 @@ database 'verify-ca' or 'verify-full' Default value is 'prefer' +.. _reference/cmdline/server/internationalisation: + +Internationalisation +-------------------- + +Use these options to translate Odoo to another language. See i18n section of +the user manual. Option '-d' is mandatory. Option '-l' is mandatory in case +of importation + +.. option:: --load-language <languages> + + specifies the languages (separated by commas) for the translations you + want to be loaded + +.. option:: -l, --language <language> + + specify the language of the translation file. Use it with --i18n-export + or --i18n-import + +.. option:: --i18n-export <filename> + + export all sentences to be translated to a CSV file, a PO file or a TGZ + archive and exit. + +.. option:: --i18n-import <filename> + + import a CSV or a PO file with translations and exit. The '-l' option is + required. + +.. option:: --i18n-overwrite + + overwrites existing translation terms on updating a module or importing + a CSV or a PO file. + +.. option:: --modules + + specify modules to export. Use in combination with --i18n-export + + built-in HTTP ------------- diff --git a/doc/reference/javascript_reference.rst b/doc/reference/javascript_reference.rst index 141c614f29c..720157fef37 100644 --- a/doc/reference/javascript_reference.rst +++ b/doc/reference/javascript_reference.rst @@ -1435,11 +1435,27 @@ order. - Supported field types: *date*, *datetime* + Options: + + - datepicker: extra settings for the datepicker_ widget. + + .. code-block:: xml + + <field name="datefield" options='{"datepicker": {"daysOfWeekDisabled": [0, 6]}}'/> + - datetime (FieldDateTime) This is the default field type for fields of type *datetime*. - Supported field types: *date*, *datetime* + Options: + + - datepicker: extra settings for the datepicker_ widget. + + .. code-block:: xml + + <field name="datefield" options='{"datepicker": {"daysOfWeekDisabled": [0, 6]}}'/> + - monetary (FieldMonetary) This is the default field type for fields of type 'monetary'. It is used to display a currency. If there is a currency fields given in option, it will @@ -1938,4 +1954,6 @@ Relational fields .. _event delegation: http://api.jquery.com/delegate/ +.. _datepicker: https://github.com/Eonasdan/bootstrap-datetimepicker + .. _deferred: http://api.jquery.com/category/deferred-object/ diff --git a/doc/setup/enterprise.rst b/doc/setup/enterprise.rst index 49ba8af4c84..66f8fe82671 100644 --- a/doc/setup/enterprise.rst +++ b/doc/setup/enterprise.rst @@ -46,7 +46,7 @@ On Linux, using an installer .. code-block:: console - $ python3 /usr/bin/odoo.py -d <database_name> -i web_enterprise --stop-after-init + $ python3 /usr/bin/odoo-bin -d <database_name> -i web_enterprise --stop-after-init * You should be able to connect to your Odoo Enterprise instance using your usual mean of identification. You can then link your database with your Odoo Enterprise Subscription by entering the code you received diff --git a/odoo/addons/base/data/res.country.state.csv b/odoo/addons/base/data/res.country.state.csv index 4b445f52cf9..b64c8f78f12 100644 --- a/odoo/addons/base/data/res.country.state.csv +++ b/odoo/addons/base/data/res.country.state.csv @@ -450,7 +450,7 @@ state_es_m,es,"Madrid","M" state_es_ma,es,"Málaga","MA" state_es_ml,es,"Melilla","ME" state_es_mu,es,"Murcia","MU" -state_es_na,es,"Nafarroa (Navarra)","NA" +state_es_na,es,"Navarra (Nafarroa)","NA" state_es_or,es,"Ourense (Orense)","OR" state_es_p,es,"Palencia","P" state_es_po,es,"Pontevedra","PO" diff --git a/odoo/addons/base/data/res_country_data.xml b/odoo/addons/base/data/res_country_data.xml index 0e865be0fdf..1648d24430c 100644 --- a/odoo/addons/base/data/res_country_data.xml +++ b/odoo/addons/base/data/res_country_data.xml @@ -271,6 +271,7 @@ <field eval="'%(street)s\n%(street2)s\n%(city)s %(state_code)s %(zip)s\n%(country_name)s'" name="address_format" /> <field name="currency_id" ref="CAD" /> <field eval="1" name="phone_code" /> + <field name="vat_label">HST</field> </record> <record id="cc" model="res.country"> <field name="name">Cocos (Keeling) Islands</field> @@ -440,8 +441,10 @@ <field name="name">Dominican Republic</field> <field name="code">do</field> <field file="base/static/img/country_flags/do.png" name="image" type="base64" /> + <field eval="'%(street)s\n%(street2)s\n%(city)s %(state_name)s %(zip)s\n%(country_name)s'" name="address_format" /> <field name="currency_id" ref="DOP" /> - <field eval="0" name="phone_code" /> + <field eval="1" name="phone_code" /> + <field name="vat_label">RNC</field> </record> <record id="dz" model="res.country"> <field name="name">Algeria</field> diff --git a/odoo/addons/base/i18n/tr.po b/odoo/addons/base/i18n/tr.po index ff3637e92d3..5d994c17db8 100644 --- a/odoo/addons/base/i18n/tr.po +++ b/odoo/addons/base/i18n/tr.po @@ -16788,6 +16788,39 @@ msgid "" "\n" "You can activate a blog for each event allowing you to communicate on specific events. Visitors can subscribe to news to get informed." msgstr "" +"Etkinlikleri, Çalışmaları & Webinarları Organize Edin\n" +"\n" +"Planlayın, Tanıtın, Satın, Organize Edin\n" +"\n" +"Etkinlik başına ekstra özellik elde edin; birden çok sayfa, sponsorlar, çoklu konuşma, teklif formunu konuşun, ajanda, etkinlikle ilgili haberleri, belgeleri (sunum slaytları), etkinlik özel menüleri.\n" +"\n" +"Takiplerinizi Organize Edin\n" +"\n" +"Konuşma teklifinden yayına\n" +"\n" +"Ziyaretçilerin konuşmaları ve konuşmacıları göndermesine izin vermek için etkinliklerinize bir konuşma teklifi formu ekleyin. Her konuşmanın onaylama sürecini düzenleyin ve kolayca programlayın.\n" +"\n" +"Odoo'nun benzersiz ön ve arka uç entegrasyonu organizasyon yapmayı ve yayınlamayı çok kolaylaştırıyor. Güzel konuşmacı biyografilerini kolayca tasarlayın ve açıklamaları açıklayın.\n" +"\n" +"Ajanda ve Konuşma Listesi\n" +"\n" +"Güçlü bir kullanıcı arayüzü\n" +"\n" +"Web sitenizde otomatik olarak yayınlanan her etkinlik için güzel bir ajanda yapın. Ziyaretçilerin görüşmeleri kolayca aramasına ve göz atmasına izin verin, etiketlere, yerlere veya konuşmacılara göre filtreleyin.\n" +"\n" +"Sponsorları Yönetin\n" +"\n" +"Sponsorluk satın, sponsorlarınızı tanıtın\n" +"\n" +"Etkinliğinize sponsorlar ekleyin ve etkinliğin her sayfasının altındaki seviyeye (örneğin bronz, gümüş, altın) sponsorlar yayınlayın.\n" +"\n" +"Tam bir satış döngüsü entegrasyonu için Odoo eCommerce üzerinden sponsorluk paketlerini online olarak satın.\n" +"\n" +"Verimli Bir Şekilde İletişim Kurun\n" +"\n" +"Bazı etkinlikler için bir blog etkinleştirin\n" +"\n" +"Belirli etkinlikler hakkında iletişim kurmanızı sağlayan her etkinlik için bir blogu etkinleştirebilirsiniz. Ziyaretçiler bilgi almak için haberlere abone olabilirler." #. module: base #: model:ir.module.module,description:base.module_website_event @@ -16950,7 +16983,7 @@ msgstr "Diğer Sahiplik" #. module: base #: model:res.partner.industry,name:base.res_partner_industry_S msgid "Other Services" -msgstr "" +msgstr "Diğer Hizmetler" #. module: base #: selection:res.partner,type:0 @@ -17005,7 +17038,7 @@ msgstr "Sahibi" #. module: base #: model:res.partner.industry,full_name:base.res_partner_industry_P msgid "P EDUCATION" -msgstr "" +msgstr "P EĞİTİM" #. module: base #: selection:ir.actions.report,report_type:0 @@ -17221,12 +17254,12 @@ msgstr "Yol" #. module: base #: model:ir.module.module,shortdesc:base.module_account_payment msgid "Payment - Account" -msgstr "" +msgstr "Ödeme - Hesap" #. module: base #: model:ir.module.module,shortdesc:base.module_sale_payment msgid "Payment - Sale" -msgstr "" +msgstr "Ödeme - İnidirim" #. module: base #: model:ir.module.category,name:base.module_category_payment_acquirer @@ -17268,12 +17301,12 @@ msgstr "Ödeme Alıcısı: Paypal Uygulaması" #. module: base #: model:ir.module.module,summary:base.module_payment_payumoney msgid "Payment Acquirer: PayuMoney Implementation" -msgstr "" +msgstr "Ödeme Alıcısı: PayuMoney Uygulaması" #. module: base #: model:ir.module.module,summary:base.module_payment_stripe msgid "Payment Acquirer: Stripe Implementation" -msgstr "" +msgstr "Ödeme Alıcısı: Stripe Uygulaması" #. module: base #: model:ir.module.module,summary:base.module_payment_transfer @@ -17311,7 +17344,7 @@ msgstr "Bordro Muhasebesi" #. module: base #: model:ir.module.module,shortdesc:base.module_payment_payumoney msgid "PayuMoney Payment Acquirer" -msgstr "" +msgstr "PayuMoney Ödeme Alıcısı" #. module: base #: model:ir.module.module,summary:base.module_hr_appraisal @@ -17354,7 +17387,7 @@ msgstr "Telefon" #. module: base #: model:ir.module.module,shortdesc:base.module_phone_validation msgid "Phone Numbers Validation" -msgstr "" +msgstr "Telefon Numarası Doğrulama" #. module: base #: model:ir.ui.view,arch_db:base.view_partner_form @@ -17364,7 +17397,7 @@ msgstr "Telefon:" #. module: base #: model:res.country,name:base.pn msgid "Pitcairn Islands" -msgstr "" +msgstr "Pitcairn Adaları" #. module: base #: selection:ir.actions.act_window.view,view_mode:0 @@ -17392,11 +17425,13 @@ msgid "" "Please define at least one SMTP server, or provide the SMTP parameters " "explicitly." msgstr "" +"En az birtane SMTP sunucusu tanımlayın yada SMTP parametrelerini açıkça " +"belirtin." #. module: base #: model:ir.ui.view,arch_db:base.view_server_action_form msgid "Please set the Model to Create before choosing values" -msgstr "" +msgstr "Lütfen değerleri seçmeden önce Modeli Oluştur'a ayarlayın." #. module: base #: code:addons/base/models/res_users.py:251 @@ -17417,7 +17452,7 @@ msgstr "Satış Noktası" #. module: base #: model:ir.module.module,shortdesc:base.module_pos_data_drinks msgid "Point of Sale Common Data Drinks" -msgstr "" +msgstr "Satış Noktası Ortak Veri İçkileri" #. module: base #: model:ir.module.module,shortdesc:base.module_pos_discount @@ -17427,7 +17462,7 @@ msgstr "Satış Noktası İndirimleri" #. module: base #: model:ir.module.module,shortdesc:base.module_pos_reprint msgid "Point of Sale Receipt Reprinting" -msgstr "" +msgstr "Satış Noktası Makbuzunu Yeniden Yazdırma" #. module: base #: model:res.country,name:base.pl @@ -17442,7 +17477,7 @@ msgstr "Polonya - Muhasebe" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_pl_reports msgid "Poland - Accounting Reports" -msgstr "" +msgstr "Polonya - Muhasebe Raporları" #. module: base #: model:res.groups,name:base.group_portal @@ -17471,7 +17506,7 @@ msgstr "Portekiz" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_pt msgid "Portugal - Accounting" -msgstr "" +msgstr "Portekiz - Muhasebe" #. module: base #: model:ir.module.module,shortdesc:base.module_hw_posbox_homepage @@ -17486,7 +17521,7 @@ msgstr "PosBox Yazılım Güncelleyicisi" #. module: base #: model:ir.model.fields,help:base.field_ir_model_constraint__definition msgid "PostgreSQL constraint definition" -msgstr "" +msgstr "PostgreSQL kısıt tanımı" #. module: base #: model:ir.model.fields,help:base.field_ir_model_constraint__name @@ -17536,32 +17571,32 @@ msgstr "Faturayı Yazdır" #. module: base #: model:ir.module.module,shortdesc:base.module_print_docsaway msgid "Print Provider : DocsAway" -msgstr "" +msgstr "Yazdırma Sağlayıcısı : DocsAway" #. module: base #: model:ir.module.module,shortdesc:base.module_print_sale msgid "Print Sale" -msgstr "" +msgstr "Satış Yazdırma" #. module: base #: model:ir.module.module,summary:base.module_l10n_us_check_printing msgid "Print US Checks" -msgstr "" +msgstr "Birleşik Devletler Çeklerini Yazdırma" #. module: base #: model:ir.module.module,summary:base.module_hr_expense_check msgid "Print amount in words on checks issued for expenses" -msgstr "" +msgstr "Masraflar için verilen çeklerde yazılı tutar" #. module: base #: model:ir.module.module,summary:base.module_print_docsaway msgid "Print and Send Invoices with DocsAway.com" -msgstr "" +msgstr "DocsAway.com adresi ile birlikte Faturaları Yazdırın ve Gönderin" #. module: base #: model:ir.module.module,summary:base.module_print msgid "Print and Send Provider Base Module" -msgstr "" +msgstr "Yazdırma ve Gönderme Sağlayıcı Temel Modül" #. module: base #: model:ir.module.module,description:base.module_print @@ -17569,16 +17604,19 @@ msgid "" "Print and Send Provider Base Module. Print and send your invoice with a " "Postal Provider. This required to install a module implementing a provider." msgstr "" +"Yazdırma ve Gönderme Sağlayıcı Temel Modül. Faturanızı bir Posta Sağlayıcısı" +" ile yazdırın ve gönderin. Bu bir sağlayıcıyı uygulayan bir modülü kurmak " +"için gerekli." #. module: base #: model:ir.module.module,summary:base.module_print_sale msgid "Print and Send Sales Orders" -msgstr "" +msgstr "Satış Siparişlerini Yazdır ve Gönder" #. module: base #: model:ir.module.module,description:base.module_print_sale msgid "Print and Send your Sales Order by Post" -msgstr "" +msgstr "Posta ile Satış Siparişlerinizi Gönderin ve Yazdırın" #. module: base #: model:ir.model.fields,field_description:base.field_ir_actions_report__print_report_name @@ -17600,12 +17638,12 @@ msgstr "" #. module: base #: model:ir.module.module,shortdesc:base.module_website_sale_comparison msgid "Product Comparison And Product Attribute Category" -msgstr "" +msgstr "Ürün Kıyaslama ve Ürün Özellikleri Kategorisi" #. module: base #: model:ir.module.module,description:base.module_website_sale_comparison msgid "Product Comparison, Product Attribute Category and specification table" -msgstr "" +msgstr "Ürün Kıyaslaması, Ürün Özellikleri Kategorisi ve özelleştirme masası" #. module: base #: model:ir.module.module,shortdesc:base.module_product_email_template @@ -17737,12 +17775,12 @@ msgstr "" #. module: base #: model:ir.module.module,summary:base.module_helpdesk_sale_timesheet msgid "Project, Helpdesk, Timesheet and Sale Orders" -msgstr "" +msgstr "Proje, Yardım Masası, Zaman Çizelgesi ve Satış Siparişleri" #. module: base #: model:ir.module.module,summary:base.module_helpdesk_timesheet msgid "Project, Tasks, Timesheet" -msgstr "" +msgstr "Projeler, Görevler, Zaman Çizelgesi" #. module: base #: model:ir.module.module,summary:base.module_project @@ -17768,7 +17806,7 @@ msgstr "" #. module: base #: model:ir.module.module,description:base.module_website_theme_install msgid "Propose to install a theme on website installation" -msgstr "" +msgstr "Web sitesi kurulumuna bir tema yüklemeyi önerin" #. module: base #: model:ir.model.fields,help:base.field_ir_actions_server__link_field_id @@ -17781,7 +17819,7 @@ msgstr "" #. module: base #: model:ir.module.module,summary:base.module_hw_screen msgid "Provides support for customer facing displays" -msgstr "" +msgstr "Müşterinin karşısındaki ekranlar için destek sağlar" #. module: base #: model:res.groups,name:base.group_public @@ -17791,7 +17829,7 @@ msgstr "Genel" #. module: base #: model:res.partner.industry,name:base.res_partner_industry_O msgid "Public Administration" -msgstr "" +msgstr "Kamu Yönetimi" #. module: base #: model:res.groups,comment:base.group_public @@ -17810,7 +17848,7 @@ msgstr "Birlikleri, Gruplar ve Üyelikleri Yayınla" #. module: base #: model:ir.module.module,summary:base.module_website_event msgid "Publish Events and Manage Online Registrations on your Website" -msgstr "" +msgstr "Web sitenizde Etkinlikler Yayınlayın ve Çevrimiçi Kayıtları Yönetin" #. module: base #: model:ir.module.module,summary:base.module_website_crm_partner_assign @@ -17866,7 +17904,7 @@ msgstr "Satınalımlar" #. module: base #: model:ir.module.module,summary:base.module_mail_push msgid "Push notification for mobile app" -msgstr "" +msgstr "Mobil uygulama için bildirimleri aktarın" #. module: base #: model:ir.model.fields,field_description:base.field_ir_actions_server__code @@ -17883,7 +17921,7 @@ msgstr "Python Expression" #. module: base #: model:res.partner.industry,full_name:base.res_partner_industry_Q msgid "Q HUMAN HEALTH AND SOCIAL WORK ACTIVITIES" -msgstr "" +msgstr "Q İNSAN SAĞLIĞI VE SOSYAL ÇALIŞMA FAALİYETLERİ" #. module: base #: model:ir.ui.view,arch_db:base.view_view_search selection:ir.ui.view,type:0 @@ -17919,7 +17957,7 @@ msgstr "Kalite Kontrol" #: model:ir.module.module,summary:base.module_quality_mrp #: model:ir.module.module,summary:base.module_quality_mrp_workorder msgid "Quality Management with MRP" -msgstr "" +msgstr "MRP ile Kalite Yönetimi" #. module: base #: model:ir.module.module,description:base.module_website_event_questions @@ -17936,7 +17974,7 @@ msgstr "" #: model:ir.module.module,summary:base.module_sale_expense #: model:ir.module.module,summary:base.module_sale_stock msgid "Quotation, Sales Orders, Delivery & Invoicing Control" -msgstr "" +msgstr "Teklif, Satış Siparişi, Teslimat & Faturalama Kontrolü" #. module: base #: model:ir.module.module,summary:base.module_sale_management @@ -17950,11 +17988,13 @@ msgid "" "Qweb view cannot have 'Groups' define on the record. Use 'groups' attributes" " inside the view definition" msgstr "" +"Qweb görünümü, kayıtta 'Gruplar' tanımlayamaz. Görünüm tanımındaki 'gruplar'" +" özelliklerini kullan" #. module: base #: model:res.partner.industry,full_name:base.res_partner_industry_R msgid "R ARTS, ENTERTAINMENT AND RECREATION" -msgstr "" +msgstr "R SANAT, EĞLENCE VE REKREASYON" #. module: base #: model:ir.model.fields,field_description:base.field_res_currency_rate__rate @@ -17987,7 +18027,7 @@ msgstr "Salt Okunur" #. module: base #: model:res.partner.industry,name:base.res_partner_industry_L msgid "Real Estate" -msgstr "" +msgstr "Emlak" #. module: base #: model:ir.ui.view,arch_db:base.view_model_data_form @@ -18024,6 +18064,8 @@ msgid "" "Record cannot be modified right now: This cron task is currently being " "executed and may not be modified Please try again in a few minutes" msgstr "" +"Kayıt şu anda değiştirilemiyor: Bu cron görevi şu anda yürütülüyor ve " +"değiştirilemiyor Lütfen birkaç dakika içinde tekrar deneyin." #. module: base #: code:addons/base/models/ir_actions.py:238 code:addons/models.py:3915 @@ -18045,7 +18087,7 @@ msgstr "İşe Alım" #. module: base #: model:ir.module.module,summary:base.module_sale_subscription msgid "Recurring invoicing, renewals" -msgstr "" +msgstr "Tekrarlanan faturalar, yinelemeler" #. module: base #: code:addons/base/models/ir_module.py:352 @@ -18116,7 +18158,7 @@ msgstr "İlişki Adı" #. module: base #: model:ir.model.fields,field_description:base.field_ir_model_fields__relation_table msgid "Relation Table" -msgstr "" +msgstr "İlişki Tablosu" #. module: base #: model:ir.model.fields,field_description:base.field_ir_actions_report__attachment_use @@ -18126,22 +18168,22 @@ msgstr "Ekten yeniden yükle" #. module: base #: model:ir.ui.view,arch_db:base.view_server_action_form msgid "Remove 'More' top-menu contextual action related to this action" -msgstr "" +msgstr "Bu eyleme ilişkin 'Diğer' üst menü bağlamsal eylemini kaldırın" #. module: base #: model:ir.ui.view,arch_db:base.view_server_action_form msgid "Remove Contextual Action" -msgstr "" +msgstr "Bağlamsal Eylemi Kaldır" #. module: base #: model:ir.ui.view,arch_db:base.act_report_xml_view msgid "Remove from the 'Print' menu" -msgstr "" +msgstr "'Yazdır' menüsünden kaldır" #. module: base #: model:ir.ui.view,arch_db:base.act_report_xml_view msgid "Remove the contextual action related this report" -msgstr "" +msgstr "Bu raporla ilgili bağlamsal aksiyonu kaldır" #. module: base #: model:ir.module.module,summary:base.module_repair @@ -18273,7 +18315,7 @@ msgstr "Kaynak Adı" #. module: base #: model:ir.module.module,summary:base.module_project_forecast msgid "Resource management for Project" -msgstr "" +msgstr "Proje için kaynak yönetimi" #. module: base #: model:ir.module.module,shortdesc:base.module_pos_restaurant @@ -18298,7 +18340,7 @@ msgstr "Listelerine sınırla" #. module: base #: model:ir.module.module,summary:base.module_hr_timesheet msgid "Review and approve employees time reports" -msgstr "" +msgstr "Çalışanların zaman raporlarını gözden geçirin ve onaylayın" #. module: base #: model:ir.model.fields,field_description:base.field_report_paperformat__margin_right @@ -18328,7 +18370,7 @@ msgstr "Romanya - Muhasebe" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_ro_reports msgid "Romania - Accounting Reports" -msgstr "" +msgstr "Romanya - Muhasebe Raporları" #. module: base #: model:ir.model.fields,field_description:base.field_res_currency__rounding @@ -18380,12 +18422,12 @@ msgstr "Ruanda" #. module: base #: model:res.country,name:base.re msgid "Réunion" -msgstr "" +msgstr "Birleşme" #. module: base #: model:res.partner.industry,full_name:base.res_partner_industry_S msgid "S OTHER SERVICE ACTIVITIES" -msgstr "" +msgstr "S DİĞER HİZMET ETKİNLİKLERİ" #. module: base #: model:ir.module.module,shortdesc:base.module_account_sepa @@ -18395,22 +18437,22 @@ msgstr "SEPA Alacak Transferi" #. module: base #: model:ir.module.module,shortdesc:base.module_hr_expense_sepa msgid "SEPA Credit Transfer in Expenses" -msgstr "" +msgstr "Giderlerde SEPA Kredi Transferi" #. module: base #: model:ir.module.module,shortdesc:base.module_account_sepa_direct_debit msgid "SEPA Direct Debit" -msgstr "" +msgstr "SEPA Doğrudan Ödeme" #. module: base #: model:ir.module.module,summary:base.module_sms msgid "SMS Text Messaging" -msgstr "" +msgstr "SMS Metin Mesajı" #. module: base #: model:ir.module.module,shortdesc:base.module_sms msgid "SMS gateway" -msgstr "" +msgstr "SMS Ağ Geçidi" #. module: base #: model:ir.model.fields,field_description:base.field_ir_mail_server__smtp_port @@ -18447,12 +18489,12 @@ msgstr "Saint Barthélémy" #. module: base #: model:res.country,name:base.sh msgid "Saint Helena, Ascension and Tristan da Cunha" -msgstr "" +msgstr "Saint Helena, Ascension ve Tristan da Cunha" #. module: base #: model:res.country,name:base.kn msgid "Saint Kitts and Nevis" -msgstr "" +msgstr "Saint Kitts ve Nevis" #. module: base #: model:res.country,name:base.lc @@ -18472,12 +18514,12 @@ msgstr "Sen Piyer ve Miquelon" #. module: base #: model:res.country,name:base.vc msgid "Saint Vincent and the Grenadines" -msgstr "" +msgstr "Saint Vincent ve the Grenadines" #. module: base #: model:ir.module.module,summary:base.module_hr_contract_salary msgid "Salary Package Configurator" -msgstr "" +msgstr "Maaş Paketi Yapılandıcı" #. module: base #: model:ir.ui.view,arch_db:base.view_partner_form @@ -18492,12 +18534,12 @@ msgstr "Satış ve Satınalma Fişleri" #. module: base #: model:ir.module.module,shortdesc:base.module_sale_coupon msgid "Sale Coupon" -msgstr "" +msgstr "Satış Kuponu" #. module: base #: model:ir.module.module,shortdesc:base.module_sale_coupon_delivery msgid "Sale Coupon Delivery" -msgstr "" +msgstr "Satış Kuponu Teslimatı" #. module: base #: model:ir.module.module,shortdesc:base.module_sale_subscription_dashboard @@ -18541,7 +18583,7 @@ msgstr "Satış Zaman Çizelgesi" #. module: base #: model:ir.module.module,shortdesc:base.module_timesheet_grid_sale msgid "Sales Timesheet: Grid Support" -msgstr "" +msgstr "Satış Zaman Çizelgesi : Grid Desteği" #. module: base #: model:ir.module.module,shortdesc:base.module_sale_mrp @@ -18556,7 +18598,7 @@ msgstr "Satış ve Depo Yönetimi" #. module: base #: model:ir.module.module,summary:base.module_sale msgid "Sales internal machinery" -msgstr "" +msgstr "İç satış düzeneği" #. module: base #: model:ir.model.fields,field_description:base.field_res_partner__user_id @@ -18605,7 +18647,7 @@ msgstr "Kaydet" #. module: base #: model:ir.ui.view,arch_db:base.view_company_report_form_with_print msgid "Save and Print" -msgstr "" +msgstr "Kaydet ve Yazdır" #. module: base #: model:ir.model.fields,field_description:base.field_ir_actions_report__attachment @@ -18615,17 +18657,17 @@ msgstr "Eki Önek Olarak Kaydet" #. module: base #: model:ir.module.module,summary:base.module_website_calendar msgid "Schedule Appointments with Clients" -msgstr "" +msgstr "Müşteri Randevularını Planla" #. module: base #: model:ir.module.module,summary:base.module_mrp_maintenance msgid "Schedule and manage maintenance on machine and tools." -msgstr "" +msgstr "Makine ve araç bakımını yönet ve planla" #. module: base #: model:ir.module.module,summary:base.module_project_timesheet_holidays msgid "Schedule timesheet when on leaves" -msgstr "" +msgstr "İzin zaman çizelgesini planla" #. module: base #: selection:ir.actions.server,usage:0 @@ -18646,17 +18688,17 @@ msgstr "Planlanmış İşlemler" #. module: base #: model:ir.model.fields,field_description:base.field_ir_cron__user_id msgid "Scheduler User" -msgstr "" +msgstr "Kullanıcı Planlayıcısı" #. module: base #: model:res.partner.industry,name:base.res_partner_industry_M msgid "Scientific" -msgstr "" +msgstr "Bilimsel" #. module: base #: model:ir.module.module,shortdesc:base.module_hw_screen msgid "Screen Driver" -msgstr "" +msgstr "Ekran Sürücüsü" #. module: base #: model:ir.ui.view,arch_db:base.view_view_search selection:ir.ui.view,type:0 @@ -18793,7 +18835,7 @@ msgstr "Kendin" #. module: base #: model:ir.module.module,shortdesc:base.module_helpdesk_sale_timesheet msgid "Sell Helpdesk Timesheet" -msgstr "" +msgstr "Yardım Masası Zaman Çizelgesi Sat" #. module: base #: model:ir.module.module,summary:base.module_website_sale @@ -18803,7 +18845,7 @@ msgstr "Ürünlerin Çevrimiçi Satışı" #. module: base #: model:ir.module.module,summary:base.module_sale_timesheet msgid "Sell based on timesheets" -msgstr "" +msgstr "Zaman çizelgesini baz alarak sat" #. module: base #: model:ir.module.module,summary:base.module_account @@ -18836,38 +18878,58 @@ msgid "" "\n" "Have clear pricing strategies.\n" msgstr "" +"Teklifleri Online Gönderin\n" +"\n" +"Dakikalar içinde profesyonel, parlak teklifler hazırlayın\n" +"\n" +"\n" +"Dakikalar içinde profesyonel, parlak teklifler hazırlamak için şablonlar kullanın. Bu teklifleri e-postayla gönderin ve müşterinizin online olarak oturum açmasına izin verin. Satışlarınızı artırmak için çapraz satış ve indirimleri kullanın.\n" +"\n" +"Elektronik İmza\n" +"\n" +"Emaillerde daha fazla faks ve tarama yok\n" +"\n" +"Müşterilerinizin teklifleri çevrimiçi olarak imzalamasına izin verin. Bazı seçenekler önermek için satış teknikleri kullanın.\n" +"\n" +"Verileri kaydetmeye değil, satış yapmaya odaklanan ek süreyi harcayın.\n" +"\n" +"Verimli İletişim\n" +"\n" +"Net fiyatlandırma stratejiniz olsun.\n" #. module: base #: model:ir.module.module,summary:base.module_website_sign msgid "" "Send documents to sign online, receive and archive filled copies (esign)" msgstr "" +"Çevrimiçi olarak imzalamak, dolu kopyaları almak ve arşivlemek için " +"belgeleri gönderin (e-imza)" #. module: base #: model:ir.module.module,description:base.module_calendar_sms #: model:ir.module.module,summary:base.module_calendar_sms msgid "Send text messages as event reminders" -msgstr "" +msgstr "Etkinlik hatırlatıcı olarak metin mesajı gönder" #. module: base #: model:ir.module.module,description:base.module_delivery_dhl msgid "Send your shippings through DHL and track them online" -msgstr "" +msgstr "Gönderilerinizi DHL yoluyla gönderin ve çevrimiçi takip edin" #. module: base #: model:ir.module.module,description:base.module_delivery_fedex msgid "Send your shippings through Fedex and track them online" -msgstr "" +msgstr "Gönderilerinizi Fedex yoluyla gönderin ve çevrimiçi takip edin" #. module: base #: model:ir.module.module,description:base.module_delivery_ups msgid "Send your shippings through UPS and track them online" -msgstr "" +msgstr "Gönderilerinizi UPS yoluyla gönderin ve çevrimiçi takip edin" #. module: base #: model:ir.module.module,description:base.module_delivery_usps msgid "Send your shippings through USPS and track them online" -msgstr "" +msgstr "Gönderilerinizi USPS yoluyla gönderin ve çevrimiçi takip edin" #. module: base #: model:res.country,name:base.sn @@ -18953,7 +19015,7 @@ msgstr "Sunucu İşlemleri" #. module: base #: model:ir.model.fields,field_description:base.field_ir_cron__ir_actions_server_id msgid "Server action" -msgstr "" +msgstr "Sunucu eylemi" #. module: base #: selection:ir.model.fields,on_delete:0 @@ -19025,7 +19087,7 @@ msgstr "Paylaşım Kullanıcısı" #. module: base #: model:ir.module.module,summary:base.module_website_slides msgid "Share and Publish Videos, Presentations and Documents" -msgstr "" +msgstr "Videoları, Sunumları, Belgeleri Paylaşın ve Yayınlayın" #. module: base #: model:ir.ui.view,arch_db:base.ir_filters_view_search @@ -19040,22 +19102,22 @@ msgstr "Sevkiyat Adresi" #. module: base #: model:ir.model.fields,field_description:base.field_base_module_uninstall__show_all msgid "Show All" -msgstr "" +msgstr "Tümünü Göster" #. module: base #: model:ir.ui.view,arch_db:base.view_currency_search msgid "Show active currencies" -msgstr "" +msgstr "Etkin para birimlerini göster" #. module: base #: model:ir.ui.view,arch_db:base.view_currency_search msgid "Show inactive currencies" -msgstr "" +msgstr "Etkin olmayan para birimlerini göster" #. module: base #: model:ir.ui.view,arch_db:base.view_base_module_uninstall msgid "Show technical modules" -msgstr "" +msgstr "Teknik modülleri göster" #. module: base #: model:res.country,name:base.sl @@ -19095,7 +19157,7 @@ msgstr "Singapur - Muhasebesi" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_sg_reports msgid "Singapore - Accounting Reports" -msgstr "" +msgstr "Singapur - Muhasebe Raporları" #. module: base #: model:res.country,name:base.sx @@ -19110,7 +19172,7 @@ msgstr "Boyut" #. module: base #: sql_constraint:ir.model.fields:0 msgid "Size of the field cannot be negative." -msgstr "" +msgstr "Alan büyüklüğü negatif olamaz" #. module: base #: model:ir.ui.view,arch_db:base.res_config_installer @@ -19145,7 +19207,7 @@ msgstr "Slovenya - Hesapplananı" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_si_reports msgid "Slovenian - Accounting Reports" -msgstr "" +msgstr "Slovenya - Muhasebe Raporları" #. module: base #: model:ir.model.fields,field_description:base.field_res_partner__image_small @@ -19245,7 +19307,7 @@ msgstr "Güney Afrika" #. module: base #: model:res.country.group,name:base.south_america msgid "South America" -msgstr "" +msgstr "Güney Amerika" #. module: base #: model:res.country,name:base.gs @@ -19270,17 +19332,17 @@ msgstr "İspanya" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_es msgid "Spain - Accounting (PGCE 2008)" -msgstr "" +msgstr "İspanya - Muhasebe (PGCE 2008)" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_es_reports msgid "Spain - Accounting (PGCE 2008) Reports" -msgstr "" +msgstr "İspanya - Muhasebe (PGCE 2008) Raporları" #. module: base #: model:ir.module.module,shortdesc:base.module_base_sparse_field msgid "Sparse Fields" -msgstr "" +msgstr "Aralıklı Alanlar" #. module: base #: model:ir.module.category,name:base.module_category_specific_industry_applications @@ -19294,12 +19356,17 @@ msgid "" "password, otherwise leave empty. After a change of password, the user has to" " login again." msgstr "" +"Sadece bir kullanıcı oluşturuyor veya kullanıcının şifresini " +"değiştiriyorsanız bir değer belirtin, aksi halde boş bırakın. Şifre " +"değişikliği yapıldıktan sonra, kullanıcı tekrar giriş yapmalıdır." #. module: base #: model:ir.model.fields,help:base.field_ir_cron__doall msgid "" "Specify if missed occurrences should be executed when the server restarts." msgstr "" +"Sunucu yeniden başlatıldığında kaçırılan olayların yürütülmesi gerekip " +"gerekmediğini belirtin." #. module: base #: model:ir.module.module,summary:base.module_website_event_track @@ -19350,7 +19417,7 @@ msgstr "İl/Eyalet Adı" #. module: base #: model:res.country,name:base.ps msgid "State of Palestine" -msgstr "" +msgstr "Filistin Devleti" #. module: base #: model:ir.model.fields,field_description:base.field_res_country__state_ids @@ -19378,7 +19445,7 @@ msgstr "Adım" #: code:addons/base/models/ir_sequence.py:32 #, python-format msgid "Step must not be zero." -msgstr "" +msgstr "Adım sıfırdan farklı olmak zorundadır" #. module: base #: model:ir.module.module,summary:base.module_note_pad @@ -19398,12 +19465,12 @@ msgstr "Stok" #. module: base #: model:ir.module.module,shortdesc:base.module_stock_barcode_mobile msgid "Stock Barcode in Mobile" -msgstr "" +msgstr "Mobilde Stok Barkodu" #. module: base #: model:ir.module.module,summary:base.module_stock_barcode_mobile msgid "Stock Barcode scan in Mobile" -msgstr "" +msgstr "Mobilde Stok Barkod Taraması" #. module: base #: model:ir.model.fields,field_description:base.field_ir_model_fields__store @@ -19453,7 +19520,7 @@ msgstr "Adres2" #: model:ir.module.module,description:base.module_payment_stripe #: model:ir.module.module,shortdesc:base.module_payment_stripe msgid "Stripe Payment Acquirer" -msgstr "" +msgstr "Çizgili Ödeme Alıcısı" #. module: base #: model:ir.module.module,shortdesc:base.module_web_studio @@ -19473,7 +19540,7 @@ msgstr "Abonelik Yönetimi" #. module: base #: model:ir.model.fields,field_description:base.field_ir_sequence__date_range_ids msgid "Subsequences" -msgstr "" +msgstr "Alt Diziler" #. module: base #: model:res.country,name:base.sd @@ -19534,7 +19601,7 @@ msgstr "Anketler" #. module: base #: model:res.country,name:base.sj msgid "Svalbard and Jan Mayen" -msgstr "" +msgstr "Svalbard ve Jan Mayen" #. module: base #: model:res.country,name:base.sz @@ -19559,7 +19626,7 @@ msgstr "İsviçre - Muhasebe" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_ch_reports msgid "Switzerland - Accounting Reports" -msgstr "" +msgstr "İsviçre - Muhasebe Raporları" #. module: base #: model:ir.model.fields,field_description:base.field_res_currency__symbol @@ -19574,7 +19641,7 @@ msgstr "Sembol Pozisyonu" #. module: base #: model:ir.module.module,shortdesc:base.module_project_timesheet_synchro msgid "Synchronization with the external timesheet application" -msgstr "" +msgstr "Harici zaman çizelgesi uygulaması ile senkronizasyon." #. module: base #: model:res.country,name:base.sy @@ -19602,7 +19669,7 @@ msgstr "Sistem Güncellemesi" #. module: base #: model:res.country,name:base.st msgid "São Tomé and Príncipe" -msgstr "" +msgstr "São Tomé ve Príncipe" #. module: base #: model:res.partner.industry,full_name:base.res_partner_industry_T @@ -19610,6 +19677,8 @@ msgid "" "T ACTIVITIES OF HOUSEHOLDS AS EMPLOYERS;UNDIFFERENTIATED GOODS- AND " "SERVICES-PRODUCING ACTIVITIES OF HOUSEHOLDS FOR OWN USE" msgstr "" +"T İŞVEREN HİZMETLERİNİN FAALİYET ALANLARI VE BUNLARIN KULLANIMINA YÖNELİK " +"HİSSEDARLIK HİZMETLERİ VE HİZMET ÜRETİM FAALİYETLERİ" #. module: base #: selection:base.language.export,format:0 @@ -19622,6 +19691,8 @@ msgid "" "TGZ format: this is a compressed archive containing a PO file, directly suitable\n" " for uploading to Odoo's translation platform," msgstr "" +"TGZ formatı: Bu, Odoo'nun çeviri platformuna yüklenmek için doğrudan uygun " +"bir satın alma sipariş dosyası içeren sıkıştırılmış bir arşivdir." #. module: base #: model:ir.model.fields,field_description:base.field_res_company__vat @@ -19696,7 +19767,7 @@ msgstr "" #. module: base #: model:ir.module.module,summary:base.module_account_taxcloud msgid "TaxCloud make it easy for business to comply with sales tax law" -msgstr "" +msgstr "TaxCloud, işin satış vergisi kanunuyla uyumlu olmasını kolaylaştırır" #. module: base #: model:ir.module.module,shortdesc:base.module_website_hr @@ -19759,12 +19830,12 @@ msgstr "Bağlantıyı Sına" #. module: base #: model:ir.module.module,shortdesc:base.module_test_main_flows msgid "Test Main Flow" -msgstr "" +msgstr "Ana Akışı Test Et" #. module: base #: model:ir.module.module,shortdesc:base.module_test_performance msgid "Test Performance" -msgstr "" +msgstr "Performansı Test Et" #. module: base #: model:ir.module.module,summary:base.module_test_marketing_automation @@ -19790,7 +19861,7 @@ msgstr "Testler" #. module: base #: model:ir.module.module,description:base.module_test_read_group msgid "Tests for read_group" -msgstr "" +msgstr "read_group için test yap" #. module: base #: model:ir.module.module,description:base.module_test_converter @@ -19815,13 +19886,13 @@ msgstr "Tayland - Muhasebe" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_th_reports msgid "Thailand - Accounting Reports" -msgstr "" +msgstr "Tayland - Muhasebe Raporları" #. module: base #: code:addons/base/models/res_users.py:291 #, python-format msgid "The \"App Switcher\" action cannot be selected as home action." -msgstr "" +msgstr "App Switcher eylemi ana eylem olarak seçilemez." #. module: base #: model:ir.model.fields,help:base.field_res_country__code @@ -19829,6 +19900,8 @@ msgid "" "The ISO country code in two chars. \n" "You can use this field for quick search." msgstr "" +"İki karakterde ISO ülke kodu.\n" +"Hızlı arama için bu alanı kullanabilirsiniz." #. module: base #: code:addons/base/models/ir_model.py:367 @@ -19837,6 +19910,8 @@ msgid "" "The Selection Options expression is not a valid Pythonic expression. Please " "provide an expression in the [('key','Label'), ...] format." msgstr "" +"Seçim tercihleri ifadesi geçerli bir Pythonic ifade değil. Lütfen " +"[('anahtar','etiket'), ...] biçiminde bir ifade girin." #. module: base #: model:ir.model.fields,help:base.field_res_lang__grouping @@ -19895,7 +19970,7 @@ msgstr "Dil kodu tekil olmak zorunda !" #. module: base #: sql_constraint:res.country.state:0 msgid "The code of the state must be unique by country !" -msgstr "" +msgstr "Devletin kodu ülkeye göre eşsiz olmalı!" #. module: base #: sql_constraint:res.company:0 @@ -19924,6 +19999,8 @@ msgid "" "The corresponding related field, if any. This must be a dot-separated list " "of field names." msgstr "" +"Varsa uygun, ilgili alan. Bu, nokta isimleriyle ayrılmış bir alan adları " +"listesi olmalıdır." #. module: base #: sql_constraint:res.currency:0 @@ -19987,12 +20064,12 @@ msgstr "" #. module: base #: model:ir.ui.view,arch_db:base.view_base_module_uninstall msgid "The following apps will be uninstalled" -msgstr "" +msgstr "Aşağıdaki uygulamalar kaldırılacaktır" #. module: base #: model:ir.ui.view,arch_db:base.view_base_module_uninstall msgid "The following documents will be permanently lost" -msgstr "" +msgstr "Aşağıdaki belgeler kalıcı olarak kaybolacaktır." #. module: base #: code:addons/base/wizard/base_module_upgrade.py:69 @@ -20016,7 +20093,7 @@ msgstr "Eğer varsa, bu kişi ile iletişime görevlendirilmiş iç kullanıcı. #. module: base #: model:ir.model.fields,help:base.field_ir_model__inherited_model_ids msgid "The list of models that extends the current model." -msgstr "" +msgstr "Mevcut modeli genişleten modellerin listesi." #. module: base #: model:ir.model.fields,help:base.field_ir_filters__action_id @@ -20024,6 +20101,8 @@ msgid "" "The menu action this filter applies to. When left empty the filter applies " "to all menus for this model." msgstr "" +"Bu filtrenin menü eylemi için geçerlidir. Boş bırakıldığında, filtre bu " +"model için tüm menülere uygulanır." #. module: base #: code:addons/base/models/ir_model.py:136 @@ -20031,13 +20110,13 @@ msgstr "" msgid "" "The model name can only contain lowercase characters, digits, underscores " "and dots." -msgstr "" +msgstr "Model adı yalnızca küçük harf, rakam, alt çizgi ve nokta içerebilir." #. module: base #: code:addons/base/models/ir_model.py:134 #, python-format msgid "The model name must start with 'x_'." -msgstr "" +msgstr "Model adı 'x_' ile başlamalıdır." #. module: base #: model:ir.model.fields,help:base.field_ir_model_fields__model_id @@ -20084,7 +20163,7 @@ msgstr "Sonraki adım dosya biçimine bağlıdır:" #: model:ir.ui.view,arch_db:base.view_model_fields_form #: model:ir.ui.view,arch_db:base.view_model_form msgid "The only predefined variables are" -msgstr "" +msgstr "Sadece önceden tanımlanmış değişkenler" #. module: base #: code:addons/model.py:121 @@ -20118,6 +20197,10 @@ msgid "" "use the same timezone that is otherwise used to pick and render date and " "time values: your computer's timezone." msgstr "" +"Basılı raporlar içinde uygun tarih ve saat değerlerini yayınlamak için " +"kullanılan eşin zaman dilimi. Bu alan için bir değer belirlemek önemlidir. " +"Tarih ve saat değerlerini almak ve işlemek için kullanılan aynı saat " +"dilimini kullanmalısınız: bilgisayarınızın saat dilimi." #. module: base #: model:ir.model.fields,help:base.field_ir_actions_report__report_file @@ -20125,6 +20208,8 @@ msgid "" "The path to the main report file (depending on Report Type) or empty if the " "content is in another field" msgstr "" +"Ana rapor dosyasına giden yol (Rapor Türü'ne bağlı olarak) veya içerik başka" +" bir alanda ise boş" #. module: base #: model:ir.model.fields,help:base.field_ir_cron__priority @@ -20132,6 +20217,8 @@ msgid "" "The priority of the job, as an integer: 0 means higher priority, 10 means " "lower priority." msgstr "" +"Sayı olarak işin önceliği,: 0, daha yüksek öncelik anlamına gelir, 10, daha " +"düşük öncelik anlamına gelir." #. module: base #: model:ir.model.fields,help:base.field_res_currency_rate__rate @@ -20172,7 +20259,7 @@ msgstr "" #. module: base #: sql_constraint:res.currency:0 msgid "The rounding factor must be greater than 0!" -msgstr "" +msgstr "Yuvarlama faktörü 0'dan büyük olmalıdır !" #. module: base #: model:ir.ui.view,arch_db:base.view_base_language_install @@ -20180,6 +20267,8 @@ msgid "" "The selected language has been successfully installed. You must change the " "preferences of the user to view the changes." msgstr "" +"Seçilen dil başarıyla kuruldu. Değişiklikleri görüntülemek için kullanıcının" +" tercihlerini değiştirmeniz gerekir." #. module: base #: model:ir.ui.view,arch_db:base.view_base_module_upgrade_install @@ -20189,7 +20278,7 @@ msgstr "Seçtiğiniz modüller güncellendi / yüklendi !" #. module: base #: model:ir.model.fields,help:base.field_res_country_state__code msgid "The state code." -msgstr "" +msgstr "İl kodu." #. module: base #: code:addons/base/models/ir_model.py:492 @@ -20210,6 +20299,10 @@ msgid "" "browserPDF means the report will be rendered using Wkhtmltopdf and " "downloaded by the user." msgstr "" +"İşlenecek raporun türü, her birinin kendi oluşturma yöntemi vardır.HTML, " +"raporun doğrudan tarayıcınızda açılacağı anlamına gelir. Pdf raporun " +"Wkhtmltopdf kullanılarak oluşturulacağı ve kullanıcı tarafından indirileceği" +" anlamına gelir." #. module: base #: model:ir.model.fields,help:base.field_ir_filters__user_id @@ -20217,6 +20310,8 @@ msgid "" "The user this filter is private to. When left empty the filter is public and" " available to all users." msgstr "" +"Bu filtrenin kullanıcısı özeldir. Boş bırakıldığında, filtre herkese açıktır" +" ve tüm kullanıcılar tarafından kullanılabilir." #. module: base #: code:addons/models.py:5208 @@ -20300,6 +20395,10 @@ msgid "" " and reference view. The result is returned as an ordered list of pairs " "(view_id,view_mode)." msgstr "" +"Bu işlev alanı, bir eylemin sonucunu görüntülerken, görüntüleme modunu, " +"görünümleri ve referans görünümünü birleştirirken etkinleştirilmesi gereken " +"sıralı görünüm listesini hesaplar. Sonuç, bir çiftler listesi (view_id, " +"view_mode) olarak döndürülür." #. module: base #: model:ir.model.fields,help:base.field_ir_actions_report__attachment @@ -20327,6 +20426,9 @@ msgid "" "\n" "Updated for Odoo 9 by Bringsvor Consulting AS <www.bringsvor.com>\n" msgstr "" +"Bu, Odoo'da Norveç için muhasebe çizelgesini yöneten modüldür.\n" +"\n" +" Bringsvor Consulting AS tarafından Odoo 9 için güncellenmiştir <www.bringsvor.com>\n" #. module: base #: model:ir.module.module,description:base.module_test_mail @@ -20347,6 +20449,8 @@ msgid "" "This theme module is exclusively for master to keep the support of " "Bootswatch themes which were previously part of the website module in 8.0." msgstr "" +"Bu tema modülü, master'ın daha önce 8.0'da bulunan web sitesi modülünün bir " +"parçası olan Bootswatch temalarını desteklemesini sağlamak içindir." #. module: base #: model:ir.model.fields,field_description:base.field_res_lang__thousands_sep @@ -20361,17 +20465,17 @@ msgstr "Perşembe" #. module: base #: model:ir.module.module,summary:base.module_helpdesk msgid "Ticketing, Support, Issues" -msgstr "" +msgstr "Talep, Destek, Sorunlar" #. module: base #: model:ir.module.module,summary:base.module_website_helpdesk_livechat msgid "Ticketing, Support, Livechat" -msgstr "" +msgstr "Talep, Destek, Canlı Sohbet" #. module: base #: model:ir.module.module,summary:base.module_website_helpdesk_slides msgid "Ticketing, Support, Slides" -msgstr "" +msgstr "Talep, Destek, Slaytlar" #. module: base #: model:ir.model.fields,field_description:base.field_res_lang__time_format @@ -20381,12 +20485,12 @@ msgstr "Saat Biçimi" #. module: base #: model:ir.module.module,summary:base.module_timesheet_grid msgid "Timesheet Validation and Grid View" -msgstr "" +msgstr "Zaman Çizelgesi Onayı ve Grid Görünümü" #. module: base #: model:ir.module.module,shortdesc:base.module_project_timesheet_holidays msgid "Timesheet when on Leaves" -msgstr "" +msgstr "İzinlerde Zaman Çizelgesi" #. module: base #: model:ir.module.category,name:base.module_category_hr_timesheet @@ -20397,12 +20501,12 @@ msgstr "Zaman Çizelgeleri" #. module: base #: model:ir.module.module,shortdesc:base.module_timesheet_grid msgid "Timesheets Validation" -msgstr "" +msgstr "Zaman Çizelgesi Doğrulama" #. module: base #: model:ir.module.module,shortdesc:base.module_hr_timesheet_attendance msgid "Timesheets/attendances reporting" -msgstr "" +msgstr "Zaman çizelgesi/Katılım raporları" #. module: base #: model:ir.model.fields,field_description:base.field_res_partner__tz @@ -20419,7 +20523,7 @@ msgstr "Saat dilimi ofseti" #. module: base #: model:res.country,name:base.tl msgid "Timor-Leste" -msgstr "" +msgstr "Doğu Timor" #. module: base #: model:ir.model.fields,field_description:base.field_res_partner__title @@ -20471,6 +20575,8 @@ msgstr "Yükseltilecek" msgid "" "To enable it, make sure this directory exists and is writable on the server:" msgstr "" +"Bunu etkinleştirmek için, bu dizinin var olduğundan ve sunucuda yazılabilir " +"olduğundan emin olun:" #. module: base #: model:ir.ui.view,arch_db:base.view_server_action_form @@ -20510,7 +20616,7 @@ msgstr "Üst Marj (mm)" #. module: base #: model:ir.model.fields,help:base.field_ir_model__count msgid "Total number of records in this model" -msgstr "" +msgstr "Bu modeldeki toplam kayıt sayısı" #. module: base #: model:ir.module.module,summary:base.module_point_of_sale @@ -20546,17 +20652,17 @@ msgstr "Geçici Model" #. module: base #: model:ir.ui.view,arch_db:base.report_irmodeloverview msgid "Transient: False" -msgstr "" +msgstr "Geçici : Yanlış" #. module: base #: model:ir.ui.view,arch_db:base.report_irmodeloverview msgid "Transient: True" -msgstr "" +msgstr "Geçici : Doğru" #. module: base #: model:ir.module.module,shortdesc:base.module_transifex msgid "Transifex integration" -msgstr "" +msgstr "Transifex Entegrasyonu" #. module: base #: model:ir.model.fields,field_description:base.field_res_groups__trans_implied_ids @@ -20640,7 +20746,7 @@ msgstr "Çeviriler" #. module: base #: model:res.partner.industry,name:base.res_partner_industry_H msgid "Transportation" -msgstr "" +msgstr "Ulaştırma" #. module: base #: selection:ir.actions.act_window,view_type:0 @@ -20753,7 +20859,7 @@ msgstr "Türü:" #. module: base #: model:res.partner.industry,full_name:base.res_partner_industry_U msgid "U ACTIVITIES OF EXTRA TERRITORIAL ORGANISATIONS AND BODIES" -msgstr "" +msgstr "U SINIR ÖTESİ ORGANİZASYON ETKİNLİKLERİ VE BEDENLER" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_ae @@ -20768,7 +20874,7 @@ msgstr "UK - Accounting" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_uk_reports msgid "UK - Accounting Reports" -msgstr "" +msgstr "Birleşik Krallık - Muhasebe Raporları" #. module: base #: model:ir.module.module,shortdesc:base.module_website_delivery_ups @@ -20778,7 +20884,7 @@ msgstr "UPS Fatura Hesabım" #. module: base #: model:ir.module.module,shortdesc:base.module_delivery_ups msgid "UPS Shipping" -msgstr "" +msgstr "UPS Sevkıyatı" #. module: base #: selection:ir.attachment,type:0 @@ -20790,7 +20896,7 @@ msgstr "URL" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_us_reports msgid "US - Accounting Reports" -msgstr "" +msgstr "Birleşik Devlerler - Muhasebe Raporları" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_us_check_printing @@ -20805,7 +20911,7 @@ msgstr "ABD Çevresi Adaları" #. module: base #: model:ir.module.module,shortdesc:base.module_utm msgid "UTM Trackers" -msgstr "" +msgstr "UTM İzleyici" #. module: base #: model:res.country,name:base.ug @@ -20833,7 +20939,7 @@ msgstr "Döküman öntamımlı bir özellik olarak kullanıldığı için siline #: code:addons/base/models/ir_actions_report.py:622 #, python-format msgid "Unable to find Wkhtmltopdf on this system. The PDF can not be created." -msgstr "" +msgstr "Wkhtmltopdf bu sistemde bulunamadı. PDF oluşturulamıyor." #. module: base #: code:addons/base/models/ir_module.py:342 @@ -20876,7 +20982,7 @@ msgstr "Kaldır" #: model:ir.ui.view,arch_db:base.view_base_module_uninstall #, python-format msgid "Uninstall module" -msgstr "" +msgstr "Modülü kaldır" #. module: base #: selection:ir.module.module,state:0 @@ -20908,7 +21014,7 @@ msgstr "USA - Muhasebe Hesapları" #. module: base #: model:ir.module.module,shortdesc:base.module_delivery_usps msgid "United States Postal Service (USPS) Shipping" -msgstr "" +msgstr "Birleşik Devletler Posta Servisi (USPS) Teslimatı" #. module: base #: selection:ir.module.module.dependency,state:0 @@ -21011,7 +21117,7 @@ msgstr "Güncelleştirme Şartları" #. module: base #: selection:ir.actions.server,state:0 msgid "Update the Record" -msgstr "" +msgstr "Kaydı Güncelle" #. module: base #: model:ir.ui.view,arch_db:base.view_company_report_form @@ -21019,6 +21125,8 @@ msgid "" "Update your company details and upload your logo to get a beautiful " "document." msgstr "" +"Şirket bilgilerinizi güncelleyin ve güzel bir doküman almak için logonuzu " +"yükleyin." #. module: base #: model:ir.actions.client,name:base.modules_updates_act_cl @@ -21044,7 +21152,7 @@ msgstr "Uruguay" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_uy_reports msgid "Uruguay - Accounts Reports" -msgstr "" +msgstr "Uruguay - Hesap Raporları" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_uy @@ -21067,7 +21175,7 @@ msgstr "Use '1' for yes and '0' for no" #. module: base #: model:ir.model.fields,field_description:base.field_ir_sequence__use_date_range msgid "Use subsequences per date_range" -msgstr "" +msgstr "date_range başına aşağıdakileri kullanın" #. module: base #: model:ir.module.module,description:base.module_hr_gamification @@ -21078,6 +21186,11 @@ msgid "" "This allow the user to send badges to employees instead of simple users.\n" "Badge received are displayed on the user profile.\n" msgstr "" +"Oyunlaştırma işlemleri için İK kaynaklarını kullanın.\n" +"\n" +"İK sorumlusu artık mücadeleleri ve rozetleri yönetebilir.\n" +"Bu, kullanıcının basit kullanıcılar yerine çalışanlara rozet göndermesine izin verir. \n" +"Alınan rozet kullanıcı profilinde görüntülenir.\n" #. module: base #: code:addons/base/models/ir_fields.py:209 @@ -21089,7 +21202,7 @@ msgstr "Biçimini kullanın '%s'" #. module: base #: model:ir.model.fields,help:base.field_res_country__vat_label msgid "Use this field if you want to change vat label." -msgstr "" +msgstr "Vergi etiketini değiştirmek istiyorsanız bu alanı kullanın." #. module: base #: model:ir.model.fields,help:base.field_res_country__address_view_id @@ -21099,12 +21212,18 @@ msgid "" "display addresses (in reports for example), while this field is used to " "modify the input form for addresses." msgstr "" +"Tam adresi kodlamak için genel yolunu değiştirmek istiyorsanız, bu alanı " +"kullanın. Address_format alanının adresleri görüntüleme şeklini değiştirmek " +"için (örneğin raporlarda), bu alanın adresler için giriş formunu değiştirmek" +" için kullanıldığını unutmayın." #. module: base #: model:ir.model.fields,help:base.field_ir_model_fields__relation_table msgid "" "Used for custom many2many fields to define a custom relation table name" msgstr "" +"Özel bir ilişki tablosu adı tanımlamak için özel many2many alanları için " +"kullanılır" #. module: base #: model:ir.model.fields,help:base.field_ir_actions_act_window__usage @@ -21156,7 +21275,7 @@ msgstr "Kullanıcı Girişi" #. module: base #: model:ir.model.fields,field_description:base.field_res_users__log_ids msgid "User log entries" -msgstr "" +msgstr "Kullanıcı log girişleri" #. module: base #: model:ir.actions.act_window,name:base.ir_default_menu_action @@ -21239,7 +21358,7 @@ msgstr "Vergi No" #. module: base #: model:ir.module.module,shortdesc:base.module_base_vat_autocomplete msgid "VAT Number Autocomplete" -msgstr "" +msgstr "Otomatik Vergi Numarası Tamamlayıcı" #. module: base #: model:ir.module.module,shortdesc:base.module_base_vat @@ -21249,27 +21368,29 @@ msgstr "KDV Numara Doğrulaması" #. module: base #: model:ir.module.module,shortdesc:base.module_voip msgid "VOIP" -msgstr "" +msgstr "VOIP" #. module: base #: model:ir.module.module,shortdesc:base.module_voip_onsip msgid "VOIP OnSIP" -msgstr "" +msgstr "VOIP OnSIP" #. module: base #: model:ir.module.module,summary:base.module_website_crm_phone_validation msgid "Validate and format contact form numbers" -msgstr "" +msgstr "İletişim formu numaralarını doğrulayın ve biçimlendirin" #. module: base #: model:ir.module.module,summary:base.module_phone_validation msgid "Validate and format phone numbers" -msgstr "" +msgstr "Telefon numaralarını doğrula ve biçimlendir." #. module: base #: model:ir.module.module,summary:base.module_crm_phone_validation msgid "Validate and format phone numbers for leads and contacts" msgstr "" +"Bağlantılar ve potansiyel müşteriler için telefon numaralarını biçimlendir " +"ve doğrula" #. module: base #: model:ir.model.fields,field_description:base.field_ir_config_parameter__value @@ -21288,22 +21409,22 @@ msgstr "'%%(field)s' seçmeli alanında '%s' değeri bulunamadı" #. module: base #: model:ir.model.fields,field_description:base.field_ir_property__value_binary msgid "Value Binary" -msgstr "" +msgstr "Değer İkili" #. module: base #: model:ir.model.fields,field_description:base.field_ir_property__value_datetime msgid "Value Datetime" -msgstr "" +msgstr "Tarih-Saat Değeri" #. module: base #: model:ir.model.fields,field_description:base.field_ir_property__value_float msgid "Value Float" -msgstr "" +msgstr "Sayısal Değer" #. module: base #: model:ir.model.fields,field_description:base.field_ir_property__value_integer msgid "Value Integer" -msgstr "" +msgstr "Tam Sayı Değeri" #. module: base #: model:ir.model.fields,field_description:base.field_ir_actions_server__fields_lines @@ -21314,12 +21435,12 @@ msgstr "Değer Eşleme" #. module: base #: model:ir.model.fields,field_description:base.field_ir_property__value_reference msgid "Value Reference" -msgstr "" +msgstr "Referans Değeri" #. module: base #: model:ir.model.fields,field_description:base.field_ir_property__value_text msgid "Value Text" -msgstr "" +msgstr "Metin Değeri" #. module: base #: model:res.country,name:base.vu @@ -21338,7 +21459,7 @@ msgstr "" #. module: base #: model:ir.model.fields,field_description:base.field_res_country__vat_label msgid "Vat Label" -msgstr "" +msgstr "Vergi Etiketi" #. module: base #: model:ir.module.module,summary:base.module_fleet @@ -21348,7 +21469,7 @@ msgstr "Araç, finansal kiralama, sigorta, maliyetleri" #. module: base #: model:ir.module.module,shortdesc:base.module_account_3way_match msgid "Vendor Bill: Release to Pay" -msgstr "" +msgstr "Tedarikçi Faturaları: Ödeme Yap" #. module: base #: model:ir.actions.act_window,name:base.action_partner_supplier_form @@ -21384,7 +21505,7 @@ msgstr "Vietnam Hesap Planı" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_vn_reports msgid "Vietnam - Accounting Reports" -msgstr "" +msgstr "Vietnam - Muhasebe Raporları" #. module: base #: model:ir.model.fields,field_description:base.field_ir_actions_act_window_view__view_id @@ -21433,7 +21554,7 @@ msgstr "Görünüm Türü" #. module: base #: model:ir.module.module,summary:base.module_account_reports msgid "View and create reports" -msgstr "" +msgstr "Raporları oluştur ve görüntüle" #. module: base #: model:ir.model.fields,field_description:base.field_ir_ui_view__mode @@ -21453,7 +21574,7 @@ msgstr "" #: code:addons/base/models/ir_model.py:571 #, python-format msgid "View: %s" -msgstr "" +msgstr "Görünüm:%s" #. module: base #: model:ir.actions.act_window,name:base.action_ui_view @@ -21514,7 +21635,7 @@ msgstr "Maliyet Yüklemeleri" #. module: base #: model:res.country,name:base.wf msgid "Wallis and Futuna" -msgstr "" +msgstr "Wallis ve Futuna" #. module: base #: model:ir.module.category,name:base.module_category_warehouse @@ -21524,12 +21645,12 @@ msgstr "Depo" #. module: base #: model:ir.module.module,shortdesc:base.module_stock_barcode msgid "Warehouse Management Barcode Scanning" -msgstr "" +msgstr "Depo Yönetimi Barkod Taraması" #. module: base #: model:ir.module.module,shortdesc:base.module_stock_picking_batch msgid "Warehouse Management: Batch Picking" -msgstr "" +msgstr "Depo Yönetimi: Toplu Transfer" #. module: base #: code:addons/base/models/ir_mail_server.py:476 @@ -21555,7 +21676,7 @@ msgstr "Uyarılar" #. module: base #: model:res.partner.industry,name:base.res_partner_industry_E msgid "Water supply" -msgstr "" +msgstr "Su temini" #. module: base #: model:ir.ui.view,arch_db:base.view_base_module_upgrade_install @@ -21574,7 +21695,7 @@ msgstr "Web" #. module: base #: model:ir.module.module,shortdesc:base.module_web_clearbit msgid "Web Clearbit" -msgstr "" +msgstr "Web Clearbit" #. module: base #: model:ir.module.module,shortdesc:base.module_web_editor @@ -21584,7 +21705,7 @@ msgstr "Web Editörü" #. module: base #: model:ir.module.module,shortdesc:base.module_web_enterprise msgid "Web Enterprise" -msgstr "" +msgstr "Web Kurumsal" #. module: base #: model:ir.module.module,shortdesc:base.module_web_gantt @@ -21605,7 +21726,7 @@ msgstr "Web İkon Resmi" #: model:ir.module.module,shortdesc:base.module_http_routing #: model:ir.module.module,summary:base.module_http_routing msgid "Web Routing" -msgstr "" +msgstr "Web Rotası" #. module: base #: model:ir.ui.view,arch_db:base.view_translation_search @@ -21629,22 +21750,22 @@ msgstr "Web Sitesi Oluşturucusu" #. module: base #: model:ir.module.module,shortdesc:base.module_website_enterprise msgid "Website Enterprise" -msgstr "" +msgstr "Website Kurumsal" #. module: base #: model:ir.module.module,shortdesc:base.module_website_form_project msgid "Website Form - Project" -msgstr "" +msgstr "Website Formu - Proje" #. module: base #: model:ir.module.module,shortdesc:base.module_website_form_editor msgid "Website Form Builder" -msgstr "" +msgstr "Website Form Oluşturucu" #. module: base #: model:ir.module.module,shortdesc:base.module_website_helpdesk_form msgid "Website Form Helpdesk" -msgstr "" +msgstr "Website Yardım Masası Formu" #. module: base #: model:ir.module.module,shortdesc:base.module_website_gengo @@ -21659,12 +21780,12 @@ msgstr "Web Sitesi Google Haritalar" #. module: base #: model:ir.module.module,shortdesc:base.module_website_helpdesk msgid "Website Helpdesk" -msgstr "" +msgstr "Website Yardım Masası" #. module: base #: model:ir.module.module,shortdesc:base.module_website_helpdesk_livechat msgid "Website IM Livechat Helpdesk" -msgstr "" +msgstr "Website IM Canlı Destek Masası" #. module: base #: model:ir.module.module,shortdesc:base.module_website_links @@ -21709,32 +21830,32 @@ msgstr "Web Sitesi Satış - Satış Yönetimi" #. module: base #: model:ir.module.module,shortdesc:base.module_website_sale_coupon msgid "Website Sale Coupon" -msgstr "" +msgstr "Website İndirim Kuponu" #. module: base #: model:ir.module.module,shortdesc:base.module_website_sale_digital msgid "Website Sale Digital - Sell digital products" -msgstr "" +msgstr "Website Dijital Satış - Dijital Ürünleri Satın" #. module: base #: model:ir.module.module,shortdesc:base.module_website_sale_stock msgid "Website Sale Stock - Website Delivery Information" -msgstr "" +msgstr "Web Sitesi Satış Stoku - Web Sitesi Teslimat Bilgileri" #. module: base #: model:ir.module.module,shortdesc:base.module_website_sale_stock_options msgid "Website Sale Stock&Options" -msgstr "" +msgstr "Web Sitesi Satış Stok ve Seçenekleri" #. module: base #: model:ir.module.module,shortdesc:base.module_website_helpdesk_slides msgid "Website Slides Helpdesk" -msgstr "" +msgstr "Web Sitesi Slaytları Yardım Masası" #. module: base #: model:ir.module.module,shortdesc:base.module_website_studio msgid "Website Studio" -msgstr "" +msgstr "Website Stüdyo" #. module: base #: model:ir.module.module,shortdesc:base.module_website_theme_install @@ -21744,12 +21865,12 @@ msgstr "Web Sitesi Tema Yükleme" #. module: base #: model:ir.module.module,shortdesc:base.module_website_version msgid "Website Versioning" -msgstr "" +msgstr "Website Versiyonlama" #. module: base #: model:ir.module.module,shortdesc:base.module_website_sale_wishlist msgid "Website Wishlist" -msgstr "" +msgstr "Website Wishlisti" #. module: base #: model:ir.model.fields,help:base.field_res_company__website @@ -21799,6 +21920,9 @@ msgid "" "When no specific mail server is requested for a mail, the highest priority " "one is used. Default priority is 10 (smaller number = higher priority)" msgstr "" +"Posta için belirli bir posta sunucusu talep edilmediğinde, en yüksek öncelik" +" kullanılır. Varsayılan öncelik 10'dur (daha küçük sayı = daha yüksek " +"öncelik)" #. module: base #: model:ir.ui.view,arch_db:base.sequence_view @@ -21810,12 +21934,12 @@ msgstr "" #. module: base #: model:ir.model.fields,help:base.field_ir_model_fields__copy msgid "Whether the value is copied when duplicating a record." -msgstr "" +msgstr "Bir kayıt çoğaltılırken değer kopyalanıp kopyalanmayacağı." #. module: base #: model:ir.model.fields,help:base.field_ir_model_fields__store msgid "Whether the value is stored in the database." -msgstr "" +msgstr "Değerin veritabanında depolanıp depolanmadığı." #. module: base #: model:ir.model.fields,help:base.field_ir_model_fields__translate @@ -21829,7 +21953,7 @@ msgstr "" #. module: base #: model:res.partner.industry,name:base.res_partner_industry_G msgid "Wholesale/Retail" -msgstr "" +msgstr "Toptan/Perakende" #. module: base #: model:ir.actions.act_window,name:base.ir_action_window @@ -21865,7 +21989,7 @@ msgstr "Wkhtmltopdf başarısız oldu (hata kodu: %s). Mesaj: %s" #. module: base #: model:ir.module.module,summary:base.module_mrp_workorder msgid "Work Orders, Planing, Stock Reports." -msgstr "" +msgstr "İş Emri, Planlama, Stok Raporları" #. module: base #: model:ir.module.module,shortdesc:base.module_payment_sips @@ -21906,7 +22030,7 @@ msgstr "Yodlee" #. module: base #: model:ir.module.module,summary:base.module_account_yodlee msgid "Yodlee Finance" -msgstr "" +msgstr "Yodlee Finans" #. module: base #: model:ir.ui.view,arch_db:base.view_users_simple_form @@ -21967,7 +22091,7 @@ msgstr "Özyinelemeli Partner hiyerarşileri oluşturamazsınız." #: code:addons/base/models/ir_ui_view.py:357 #, python-format msgid "You cannot create recursive inherited views." -msgstr "" +msgstr "Yinelenen miras görünümler oluşturamazsınız." #. module: base #: code:addons/base/models/res_users.py:344 @@ -22075,6 +22199,9 @@ msgid "" "instead. If SSL is needed, an upgrade to Python 2.6 on the server-side " "should do the trick." msgstr "" +"Odoo Sunucusu SMTP üzerinden SSL desteklemez. STARTTLS yerine " +"kullanabilirsiniz. Python 2.6 sürümüne yükseltmeyi sunucu tarafında SSL " +"kullanılmıyorsa, işimizi görür." #. module: base #: code:addons/base/models/ir_mail_server.py:477 @@ -22176,17 +22303,17 @@ msgstr "base.update.translations" #. module: base #: selection:ir.model.fields,ttype:0 msgid "binary" -msgstr "" +msgstr "ikili" #. module: base #: selection:ir.model.fields,ttype:0 msgid "boolean" -msgstr "" +msgstr "mantıksal" #. module: base #: model:ir.module.module,shortdesc:base.module_delivery_bpost msgid "bpost Shipping" -msgstr "" +msgstr "bpost Sevkıyat" #. module: base #: selection:ir.model.fields,ttype:0 @@ -22201,7 +22328,7 @@ msgstr "seç" #. module: base #: model:ir.module.category,name:base.module_category_crm msgid "crm" -msgstr "" +msgstr "crm" #. module: base #: code:addons/base/models/ir_fields.py:314 @@ -22212,12 +22339,12 @@ msgstr "veritabanı id" #. module: base #: selection:ir.model.fields,ttype:0 msgid "date" -msgstr "" +msgstr "tarih" #. module: base #: selection:ir.model.fields,ttype:0 msgid "datetime" -msgstr "" +msgstr "tarih saat" #. module: base #: model:ir.ui.view,arch_db:base.wizard_lang_export @@ -22249,7 +22376,7 @@ msgstr "örn. Global İş Çözümleri" #. module: base #: model:ir.ui.view,arch_db:base.view_partner_form msgid "e.g. Mr." -msgstr "" +msgstr "örn. Bay" #. module: base #: model:ir.ui.view,arch_db:base.view_partner_form @@ -22261,12 +22388,12 @@ msgstr "örn. Satış Yöneticisi" #. module: base #: model:ir.ui.view,arch_db:base.view_server_action_form msgid "e.g. Update order quantity" -msgstr "" +msgstr "örn. Sipariş miktarını güncelle" #. module: base #: model:ir.ui.view,arch_db:base.view_company_form msgid "e.g. Your Bank Accounts, one per line" -msgstr "" +msgstr "örn. Banka Hesaplarınız, satır başına" #. module: base #: model:ir.ui.view,arch_db:base.view_base_import_language @@ -22283,7 +22410,7 @@ msgstr "örn. www.odoo.com" #. module: base #: model:ir.module.module,shortdesc:base.module_sale_ebay msgid "eBay Connector" -msgstr "" +msgstr "eBay Bağlayıcı" #. module: base #: model:ir.module.module,shortdesc:base.module_website_sale @@ -22325,7 +22452,7 @@ msgstr "yanlış" #. module: base #: selection:ir.model.fields,ttype:0 msgid "float" -msgstr "" +msgstr "sayısal" #. module: base #: model:ir.ui.view,arch_db:base.view_model_fields_form @@ -22334,6 +22461,8 @@ msgid "" "for record in self:\n" " record['size'] = len(record.name)" msgstr "" +"kendi kaydı için:\n" +"record['size'] = len(record.name)" #. module: base #: code:addons/base/models/res_lang.py:255 @@ -22344,7 +22473,7 @@ msgstr "" #. module: base #: model:ir.model,name:base.model_format_address_mixin msgid "format.address.mixin" -msgstr "" +msgstr "format.address.mixin" #. module: base #: selection:base.language.export,state:0 @@ -22354,7 +22483,7 @@ msgstr "alma" #. module: base #: selection:ir.model.fields,ttype:0 msgid "html" -msgstr "" +msgstr "html" #. module: base #: selection:base.language.install,state:0 @@ -22365,7 +22494,7 @@ msgstr "başlatma" #. module: base #: selection:ir.model.fields,ttype:0 msgid "integer" -msgstr "" +msgstr "tamsayı" #. module: base #: model:ir.ui.view,arch_db:base.view_partner_form @@ -22435,7 +22564,7 @@ msgstr "ir.config_parameter" #. module: base #: model:ir.model,name:base.model_ir_default msgid "ir.default" -msgstr "" +msgstr "ir.default" #. module: base #: model:ir.model,name:base.model_ir_exports @@ -22530,7 +22659,7 @@ msgstr "ir.qweb.field.float" #. module: base #: model:ir.model,name:base.model_ir_qweb_field_float_time msgid "ir.qweb.field.float_time" -msgstr "" +msgstr "ir.qweb.field.float_time" #. module: base #: model:ir.model,name:base.model_ir_qweb_field_html @@ -22615,17 +22744,17 @@ msgstr "ir.ui.view.custom" #. module: base #: selection:ir.model.fields,ttype:0 msgid "many2many" -msgstr "" +msgstr "many2many" #. module: base #: selection:ir.model.fields,ttype:0 msgid "many2one" -msgstr "" +msgstr "many2one" #. module: base #: selection:ir.model.fields,ttype:0 msgid "monetary" -msgstr "" +msgstr "monetary" #. module: base #: code:addons/base/models/ir_ui_view.py:488 @@ -22653,22 +22782,22 @@ msgstr "açık" #. module: base #: selection:ir.model.fields,ttype:0 msgid "one2many" -msgstr "" +msgstr "ne2many" #. module: base #: model:ir.module.module,shortdesc:base.module_pos_cache msgid "pos_cache" -msgstr "" +msgstr "pos_cache" #. module: base #: model:ir.module.module,shortdesc:base.module_pos_sale msgid "pos_sale" -msgstr "" +msgstr "pos_sale" #. module: base #: selection:ir.model.fields,ttype:0 msgid "reference" -msgstr "" +msgstr "referans" #. module: base #: model:ir.model,name:base.model_report_base_report_irmodulereference @@ -22703,7 +22832,7 @@ msgstr "res.users.log" #. module: base #: selection:ir.model.fields,ttype:0 msgid "selection" -msgstr "" +msgstr "seçim" #. module: base #: model:ir.module.module,shortdesc:base.module_social_media @@ -22728,12 +22857,12 @@ msgstr "" #. module: base #: model:ir.module.module,shortdesc:base.module_test_assetsbundle msgid "test-assetsbundle" -msgstr "" +msgstr "test-assetsbundle" #. module: base #: model:ir.module.module,shortdesc:base.module_test_pylint msgid "test-eval" -msgstr "" +msgstr "test - deneme sürümü" #. module: base #: model:ir.module.module,shortdesc:base.module_test_exceptions @@ -22778,7 +22907,7 @@ msgstr "test_convert" #. module: base #: selection:ir.model.fields,ttype:0 msgid "text" -msgstr "" +msgstr "metin" #. module: base #: model:ir.ui.view,arch_db:base.res_config_installer diff --git a/odoo/addons/base/models/ir_mail_server.py b/odoo/addons/base/models/ir_mail_server.py index 97f100fb94b..9cf939dcf05 100644 --- a/odoo/addons/base/models/ir_mail_server.py +++ b/odoo/addons/base/models/ir_mail_server.py @@ -22,6 +22,8 @@ from odoo.tools import ustr, pycompat _logger = logging.getLogger(__name__) _test_logger = logging.getLogger('odoo.tests') +SMTP_TIMEOUT = 60 + class MailDeliveryException(except_orm): """Specific exception subclass for mail delivery errors""" @@ -246,9 +248,9 @@ class IrMailServer(models.Model): "You could use STARTTLS instead. " "If SSL is needed, an upgrade to Python 2.6 on the server-side " "should do the trick.")) - connection = smtplib.SMTP_SSL(smtp_server, smtp_port) + connection = smtplib.SMTP_SSL(smtp_server, smtp_port, timeout=SMTP_TIMEOUT) else: - connection = smtplib.SMTP(smtp_server, smtp_port) + connection = smtplib.SMTP(smtp_server, smtp_port, timeout=SMTP_TIMEOUT) connection.set_debuglevel(smtp_debug) if smtp_encryption == 'starttls': # starttls() will perform ehlo() if needed first diff --git a/odoo/addons/base/models/ir_model.py b/odoo/addons/base/models/ir_model.py index 3b2fa5375dd..66f693a79c7 100644 --- a/odoo/addons/base/models/ir_model.py +++ b/odoo/addons/base/models/ir_model.py @@ -28,7 +28,7 @@ SAFE_EVAL_BASE = { def make_compute(text, deps): """ Return a compute function from its code body and dependencies. """ func = lambda self: safe_eval(text, SAFE_EVAL_BASE, {'self': self}, mode="exec") - deps = [arg.strip() for arg in (deps or "").split(",")] + deps = [arg.strip() for arg in deps.split(",")] if deps else [] return api.depends(*deps)(func) diff --git a/odoo/addons/base/models/qweb.py b/odoo/addons/base/models/qweb.py index 98697b87738..692db1bf0f3 100644 --- a/odoo/addons/base/models/qweb.py +++ b/odoo/addons/base/models/qweb.py @@ -308,8 +308,9 @@ class QWeb(object): raise e except Exception as e: path = _options['last_path_node'] - node = element.getroottree().xpath(path) - raise QWebException("Error when compiling AST", e, path, etree.tostring(node[0], encoding='unicode'), name) + element, document = self.get_template(template, options) + node = element.getroottree().xpath(path) if ':' not in path else None + raise QWebException("Error when compiling AST", e, path, node and etree.tostring(node[0], encoding='unicode'), name) astmod.body.extend(_options['ast_calls']) if 'profile' in options: @@ -344,7 +345,7 @@ class QWeb(object): except Exception as e: path = log['last_path_node'] element, document = self.get_template(template, options) - node = element.getroottree().xpath(path) + node = element.getroottree().xpath(path) if ':' not in path else None raise QWebException("Error to render compiling AST", e, path, node and etree.tostring(node[0], encoding='unicode'), name) return _compiled_fn diff --git a/odoo/addons/base/models/res_users.py b/odoo/addons/base/models/res_users.py index 92c2b9351b9..d27d01d15f6 100644 --- a/odoo/addons/base/models/res_users.py +++ b/odoo/addons/base/models/res_users.py @@ -884,6 +884,11 @@ class UsersImplied(models.Model): super(UsersImplied, self).write(vals) return res + if not view.check_access_rights('write', raise_exception=False): + # erp manager has the rights to update groups/users but not + # to modify ir.ui.view + if self.env.user.has_group('base.group_erp_manager'): + view = view.sudo() #---------------------------------------------------------- # change password wizard diff --git a/odoo/addons/base/rng/tree_view.rng b/odoo/addons/base/rng/tree_view.rng index 1dec8e9ab11..dc41ee5005c 100644 --- a/odoo/addons/base/rng/tree_view.rng +++ b/odoo/addons/base/rng/tree_view.rng @@ -17,6 +17,8 @@ <rng:optional><rng:attribute name="duplicate"/></rng:optional> <rng:optional><rng:attribute name="import"/></rng:optional> <rng:optional><rng:attribute name="class"/></rng:optional> + <!-- Allows to take a custom View widget for handling. Defined in view_manager. --> + <rng:optional><rng:attribute name="js_class"/></rng:optional> <rng:optional><rng:attribute name="colors"/></rng:optional> <rng:optional><rng:attribute name="fonts"/></rng:optional> <rng:optional><rng:attribute name="default_order"/></rng:optional> diff --git a/odoo/addons/base/security/base_security.xml b/odoo/addons/base/security/base_security.xml index 9852bb1f6fe..5e46fe20937 100644 --- a/odoo/addons/base/security/base_security.xml +++ b/odoo/addons/base/security/base_security.xml @@ -109,7 +109,7 @@ <field name="name">res.partner.rule.private.employee</field> <field name="model_id" ref="base.model_res_partner"/> <field name="domain_force"> - [('type', '!=', 'private')] + ['|', ('type', '!=', 'private'), ('type', '=', False)] </field> <field name="groups" eval="[ (4, ref('base.group_user')), diff --git a/odoo/addons/base/tests/test_qweb.py b/odoo/addons/base/tests/test_qweb.py index bea0c74cabe..310c5220897 100644 --- a/odoo/addons/base/tests/test_qweb.py +++ b/odoo/addons/base/tests/test_qweb.py @@ -5,6 +5,7 @@ import collections import json import os.path import re +import sys from lxml import etree @@ -465,6 +466,26 @@ class TestQWebNS(TransactionCase): expected_result ) + def test_render_dynamic_xml_with_code_error(self): + """ Test that, when rendering a template containing a namespaced node + that evaluates code with errors, the proper exception is raised + """ + view1 = self.env['ir.ui.view'].create({ + 'name': "dummy", + 'type': 'qweb', + 'arch': u""" + <t t-name="base.dummy"> + <Invoice xmlns:od="http://odoo.com/od"> + <od:name t-att-test="'a' + 1"/> + </Invoice> + </t> + """ + }) + error_msg = "Can't convert 'int' object to str implicitly" + if sys.version_info >= (3, 6): + error_msg = "must be str, not int" + with self.assertRaisesRegexp(QWebException, error_msg): + view1.render() from copy import deepcopy class FileSystemLoader(object): diff --git a/odoo/addons/test_new_api/tests/test_new_fields.py b/odoo/addons/test_new_api/tests/test_new_fields.py index a7d0f977968..1ce7d1a75e2 100644 --- a/odoo/addons/test_new_api/tests/test_new_fields.py +++ b/odoo/addons/test_new_api/tests/test_new_fields.py @@ -61,6 +61,19 @@ class TestFields(common.TransactionCase): self.assertTrue(field.store) self.assertTrue(field.readonly) + def test_10_computed_custom(self): + """ check definition of custom computed fields """ + self.env['ir.model.fields'].create({ + 'name': 'x_bool_false_computed', + 'model_id': self.env.ref('test_new_api.model_test_new_api_message').id, + 'field_description': 'A boolean computed to false', + 'compute': "for r in self: r['x_bool_false_computed'] = False", + 'store': False, + 'ttype': 'boolean' + }) + field = self.env['test_new_api.message']._fields['x_bool_false_computed'] + self.assertFalse(field.depends) + def test_10_non_stored(self): """ test non-stored fields """ # a field declared with store=False should not have a column diff --git a/odoo/addons/test_pylint/tests/test_pylint.py b/odoo/addons/test_pylint/tests/test_pylint.py index 2abff5781f2..dcea3ba01b1 100644 --- a/odoo/addons/test_pylint/tests/test_pylint.py +++ b/odoo/addons/test_pylint/tests/test_pylint.py @@ -10,6 +10,7 @@ import subprocess from distutils.version import LooseVersion import os from os.path import join +import sys from odoo.tests.common import TransactionCase from odoo import tools @@ -115,8 +116,11 @@ class TestPyLint(TransactionCase): def test_pylint(self): if pylint is None: self._skip_test('please install pylint') - if LooseVersion(getattr(pylint, '__version__', '0.0.1')) < LooseVersion('1.6.4'): - self._skip_test('please upgrade pylint to >= 1.6.4') + required_pylint_version = LooseVersion('1.6.4') + if sys.version_info >= (3, 6): + required_pylint_version = LooseVersion('1.7.0') + if LooseVersion(getattr(pylint, '__version__', '0.0.1')) < required_pylint_version: + self._skip_test('please upgrade pylint to >= %s' % required_pylint_version) paths = [tools.config['root_path']] for module in get_modules(): diff --git a/odoo/http.py b/odoo/http.py index c66962d16d6..73098004cc4 100644 --- a/odoo/http.py +++ b/odoo/http.py @@ -1038,7 +1038,7 @@ class OpenERPSession(werkzeug.contrib.sessions.Session): self.db = db self.uid = uid self.login = login - self.session_token = uid and security.compute_session_token(self) + self.session_token = uid and security.compute_session_token(self, request.env) request.uid = uid request.disable_db = False @@ -1053,9 +1053,11 @@ class OpenERPSession(werkzeug.contrib.sessions.Session): """ if not self.db or not self.uid: raise SessionExpiredException("Session expired") - + # We create our own environment instead of the request's one. + # to avoid creating it without the uid since request.uid isn't set yet + env = odoo.api.Environment(request.cr, self.uid, self.context) # here we check if the session is still valid - if not security.check_session(self): + if not security.check_session(self, env): raise SessionExpiredException("Session expired") def logout(self, keep_db=False): diff --git a/odoo/models.py b/odoo/models.py index 7b9d2cc9f3e..c720f1cd5d2 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -2061,7 +2061,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): for field in many2onefields: ids_set = {d[field] for d in data if d[field]} m2o_records = self.env[self._fields[field].comodel_name].browse(ids_set) - data_dict = dict(m2o_records.name_get()) + data_dict = dict(m2o_records.sudo().name_get()) for d in data: d[field] = (d[field], data_dict[d[field]]) if d[field] else False @@ -3910,7 +3910,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): vals = self.copy_data(default)[0] # To avoid to create a translation in the lang of the user, copy_translation will do it new = self.with_context(lang=None).create(vals) - self.copy_translations(new) + self.with_context(from_copy_translation=True).copy_translations(new) return new @api.multi diff --git a/odoo/modules/registry.py b/odoo/modules/registry.py index 9e180138a21..7dfead33210 100644 --- a/odoo/modules/registry.py +++ b/odoo/modules/registry.py @@ -149,9 +149,7 @@ class Registry(Mapping): """ Delete the registry linked to a given database. """ with cls._lock: if db_name in cls.registries: - registry = cls.registries.pop(db_name) - registry.clear_caches() - registry.registry_invalidated = True + cls.registries.pop(db_name) @classmethod def delete_all(cls): diff --git a/odoo/service/db.py b/odoo/service/db.py index ce868f693dd..8f3c24d7d8a 100644 --- a/odoo/service/db.py +++ b/odoo/service/db.py @@ -394,6 +394,7 @@ def list_db_incompatible(databases): incompatible_databases.append(database_name) else: incompatible_databases.append(database_name) + for database_name in incompatible_databases: # release connection odoo.sql_db.close_db(database_name) return incompatible_databases diff --git a/odoo/service/security.py b/odoo/service/security.py index 229e4b84077..54d108fb4b1 100644 --- a/odoo/service/security.py +++ b/odoo/service/security.py @@ -12,15 +12,13 @@ def check(db, uid, passwd): res_users = odoo.registry(db)['res.users'] return res_users.check(db, uid, passwd) -def compute_session_token(session): - with odoo.registry(session.db).cursor() as cr: - self = odoo.api.Environment(cr, session.uid, {})['res.users'].browse(session.uid) - return self._compute_session_token(session.sid) +def compute_session_token(session, env): + self = env['res.users'].browse(session.uid) + return self._compute_session_token(session.sid) -def check_session(session): - with odoo.registry(session.db).cursor() as cr: - self = odoo.api.Environment(cr, session.uid, {})['res.users'].browse(session.uid) - if odoo.tools.misc.consteq(self._compute_session_token(session.sid), session.session_token): - return True - self._invalidate_session_cache() - return False +def check_session(session, env): + self = env['res.users'].browse(session.uid) + if odoo.tools.misc.consteq(self._compute_session_token(session.sid), session.session_token): + return True + self._invalidate_session_cache() + return False diff --git a/odoo/service/server.py b/odoo/service/server.py index e1b036186c1..5bd735aa76f 100644 --- a/odoo/service/server.py +++ b/odoo/service/server.py @@ -364,7 +364,10 @@ class GeventServer(CommonServer): def start(self): import gevent - from gevent.wsgi import WSGIServer + try: + from gevent.pywsgi import WSGIServer + except ImportError: + from gevent.wsgi import WSGIServer if os.name == 'posix': @@ -829,7 +832,6 @@ class WorkerCron(Worker): from odoo.addons import base base.models.ir_cron.ir_cron._acquire_job(db_name) - odoo.modules.registry.Registry.delete(db_name) # dont keep cursors in multi database mode if len(db_names) > 1: diff --git a/odoo/tests/common.py b/odoo/tests/common.py index aabf179df53..6ade23927e1 100644 --- a/odoo/tests/common.py +++ b/odoo/tests/common.py @@ -367,7 +367,7 @@ class HttpCase(TransactionCase): session.db = db session.uid = uid session.login = user - session.session_token = uid and security.compute_session_token(session) + session.session_token = uid and security.compute_session_token(session, env) session.context = env['res.users'].context_get() or {} session.context['uid'] = uid session._fix_lang(session.context) diff --git a/odoo/tools/misc.py b/odoo/tools/misc.py index 42fcecd7498..8b1d7107c0d 100644 --- a/odoo/tools/misc.py +++ b/odoo/tools/misc.py @@ -1177,13 +1177,15 @@ def format_date(env, value, lang_code=False, date_format=False): ''' if not value: return '' - if isinstance(value, datetime.datetime): - value = value.date() - elif isinstance(value, pycompat.string_types): + if isinstance(value, pycompat.string_types): if len(value) < DATE_LENGTH: return '' - value = value[:DATE_LENGTH] - value = datetime.datetime.strptime(value, DEFAULT_SERVER_DATE_FORMAT).date() + if len(value) > DATE_LENGTH: + # a datetime, convert to correct timezone + value = odoo.fields.Datetime.from_string(value) + value = odoo.fields.Datetime.context_timestamp(env['res.lang'], value) + else: + value = odoo.fields.Datetime.from_string(value) lang = env['res.lang']._lang_get(lang_code or env.context.get('lang') or 'en_US') locale = babel.Locale.parse(lang.code) @@ -70,6 +70,7 @@ def py2exe_options(): 'dist_dir': 'dist', 'packages': [ 'asynchat', 'asyncore', + 'BeautifulSoup', 'commands', 'dateutil', 'decimal', |
