diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000000..98eb36db26e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,40 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| 12.0 | :white_check_mark: | +| 11.0 | :white_check_mark: | +| 10.0 | :white_check_mark: | +| <=9.0 | :x: | + +## Reporting a Vulnerability + +Please share privately the details of your security vulnerability by contacting our Security Team: +[Contact Info](https://www.odoo.com/security-report) + +Make sure to include as much information as possible, with the detailed steps to reproduce the problem, +the versions that are affected, the expected results and actual results, and any other information that +might help us react faster and more efficiently. + +We tend to prefer _text-based descriptions_ accompanied with a proof-of-concept script/exploit, rather +than screenshots and videos. + +Our [Responsible Disclosure](https://www.odoo.com/security-report) page gives an overview of the +process, including: + + - Our Incident Response Procedure (what will happen after you report an issue) + - Our Rules (what you can and cannot do while researching security issues) + - Guidelines with **DO REPORT** and **DO NOT REPORT** issues + (what kind of issues will be accepted/rejected) + + +## Important note + +We receive a majority of security reports that have little to no impact on the security of Odoo or +the Odoo Cloud, and we ultimately have to reject them. To avoid a disappointing experience when +contacting us, please try to put together a proof-of-concept attack and take a critical look at +what's really at risk. +If the proposed attack scenario turns out unrealistic, your report will probably be rejected. +Also be sure to review our list of [non-qualifying issues](https://www.odoo.com/security-report#what). diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index c97b1d4d314..82de31b482c 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -832,7 +832,7 @@ class AccountInvoice(models.Model): domain = {} company_id = self.company_id.id p = self.partner_id if not company_id else self.partner_id.with_context(force_company=company_id) - type = self.type + type = self.type or self.env.context.get('type', 'out_invoice') if p: rec_account = p.property_account_receivable_id pay_account = p.property_account_payable_id @@ -1848,7 +1848,7 @@ class AccountInvoiceLine(models.Model): self_lang = self if part.lang: self_lang = self.with_context(lang=part.lang) - + product = self_lang.product_id account = self.get_invoice_line_account(type, product, fpos, company) if account: diff --git a/addons/account/models/account_journal_dashboard.py b/addons/account/models/account_journal_dashboard.py index 97ca3d99717..8a893a05ffb 100644 --- a/addons/account/models/account_journal_dashboard.py +++ b/addons/account/models/account_journal_dashboard.py @@ -4,6 +4,7 @@ from datetime import datetime, timedelta from babel.dates import format_datetime, format_date from odoo import models, api, _, fields +from odoo.osv import expression from odoo.release import version from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF, safe_eval from odoo.tools.misc import formatLang @@ -368,10 +369,16 @@ class account_journal(models.Model): action_name = 'action_view_bank_statement_tree' elif self.type == 'sale': action_name = 'action_invoice_tree1' - self = self.with_context(use_domain=[('journal_id', '=', self.id)]) + use_domain = expression.AND( + [self.env.context.get('use_domain', []), [('journal_id', '=', self.id)]] + ) + self = self.with_context(use_domain=use_domain) elif self.type == 'purchase': action_name = 'action_vendor_bill_template' - self = self.with_context(use_domain=[('journal_id', '=', self.id)]) + use_domain = expression.AND( + [self.env.context.get('use_domain', []), [('journal_id', '=', self.id)]] + ) + self = self.with_context(use_domain=use_domain) else: action_name = 'action_move_journal_line' diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index da30e616e85..fc844f15c71 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -936,7 +936,10 @@ class AccountMoveLine(models.Model): debit_moves = debit_moves.sorted(key=lambda a: (a.date_maturity or a.date, a.currency_id)) credit_moves = credit_moves.sorted(key=lambda a: (a.date_maturity or a.date, a.currency_id)) # Compute on which field reconciliation should be based upon: - field = self[0].account_id.currency_id and 'amount_residual_currency' or 'amount_residual' + if self[0].account_id.currency_id and self[0].account_id.currency_id != self[0].account_id.company_id.currency_id: + field = 'amount_residual_currency' + else: + field = 'amount_residual' #if all lines share the same currency, use amount_residual_currency to avoid currency rounding error if self[0].currency_id and all([x.amount_currency and x.currency_id == self[0].currency_id for x in self]): field = 'amount_residual_currency' diff --git a/addons/account/report/account_invoice_report.py b/addons/account/report/account_invoice_report.py index 7861644525a..abc17743e61 100644 --- a/addons/account/report/account_invoice_report.py +++ b/addons/account/report/account_invoice_report.py @@ -112,13 +112,13 @@ class AccountInvoiceReport(models.Model): 1 AS nbr, ai.id AS invoice_id, ai.type, ai.state, pt.categ_id, ai.date_due, ai.account_id, ail.account_id AS account_line_id, ai.partner_bank_id, - SUM ((invoice_type.sign_qty * ail.quantity) / u.factor * u2.factor) AS product_qty, + SUM ((invoice_type.sign_qty * ail.quantity) / COALESCE(u.factor,1) * COALESCE(u2.factor,1)) AS product_qty, SUM(ail.price_subtotal_signed * invoice_type.sign) AS price_total, - (ai.amount_total * invoice_type.sign) / (SELECT count(*) FROM account_invoice_line l where invoice_id = ai.id) * + ai.amount_total_signed / (SELECT count(*) FROM account_invoice_line l where invoice_id = ai.id) * count(*) * invoice_type.sign AS amount_total, SUM(ABS(ail.price_subtotal_signed)) / CASE - WHEN SUM(ail.quantity / u.factor * u2.factor) <> 0::numeric - THEN SUM(ail.quantity / u.factor * u2.factor) + WHEN SUM(ail.quantity / COALESCE(u.factor,1) * COALESCE(u2.factor,1)) <> 0::numeric + THEN SUM(ail.quantity / COALESCE(u.factor,1) * COALESCE(u2.factor,1)) ELSE 1::numeric END AS price_average, ai.residual_company_signed / (SELECT count(*) FROM account_invoice_line l where invoice_id = ai.id) * diff --git a/addons/account/static/src/js/reconciliation/reconciliation_action.js b/addons/account/static/src/js/reconciliation/reconciliation_action.js index 4690f15d801..b9e40d7f9f7 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_action.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_action.js @@ -340,9 +340,12 @@ var StatementAction = AbstractAction.extend({ 'context': self.model.getContext(), }); _.each(result.handles, function (handle) { - self._getWidget(handle).destroy(); - var index = _.findIndex(self.widgets, function (widget) {return widget.handle===handle;}); - self.widgets.splice(index, 1); + var widget = self._getWidget(handle); + if (widget) { + widget.destroy(); + var index = _.findIndex(self.widgets, function (widget) {return widget.handle===handle;}); + self.widgets.splice(index, 1); + } }); // Get number of widget and if less than constant and if there are more to laod, load until constant if (self.widgets.length < self.model.defaultDisplayQty diff --git a/addons/account/tests/test_account_customer_invoice.py b/addons/account/tests/test_account_customer_invoice.py index 03ca61aecf5..5bd6e7328d1 100644 --- a/addons/account/tests/test_account_customer_invoice.py +++ b/addons/account/tests/test_account_customer_invoice.py @@ -282,30 +282,30 @@ class TestAccountCustomerInvoice(AccountTestUsers): dashboard_data = journal.get_journal_dashboard_datas() self.assertEquals(dashboard_data['number_draft'], 2) - self.assertEquals(dashboard_data['sum_draft'], '$ 68.42') + self.assertIn('68.42', dashboard_data['sum_draft']) self.assertEquals(dashboard_data['number_waiting'], 0) - self.assertEquals(dashboard_data['sum_waiting'], '$ 0.00') + self.assertIn('0.00', dashboard_data['sum_waiting']) # Check Both invoice.action_invoice_open() dashboard_data = journal.get_journal_dashboard_datas() self.assertEquals(dashboard_data['number_draft'], 1) - self.assertEquals(dashboard_data['sum_draft'], '$ -13.30') + self.assertIn('-13.30', dashboard_data['sum_draft']) self.assertEquals(dashboard_data['number_waiting'], 1) - self.assertEquals(dashboard_data['sum_waiting'], '$ 81.72') + self.assertIn('81.72', dashboard_data['sum_waiting']) # Check waiting payment refund.action_invoice_open() dashboard_data = journal.get_journal_dashboard_datas() self.assertEquals(dashboard_data['number_draft'], 0) - self.assertEquals(dashboard_data['sum_draft'], '$ 0.00') + self.assertIn('0.00', dashboard_data['sum_draft']) self.assertEquals(dashboard_data['number_waiting'], 2) - self.assertEquals(dashboard_data['sum_waiting'], '$ 68.42') + self.assertIn('68.42', dashboard_data['sum_waiting']) # Check partial receivable_account = refund.move_id.line_ids.mapped('account_id').filtered(lambda a: a.internal_type == 'receivable') @@ -329,12 +329,12 @@ class TestAccountCustomerInvoice(AccountTestUsers): dashboard_data = journal.get_journal_dashboard_datas() self.assertEquals(dashboard_data['number_draft'], 0) - self.assertEquals(dashboard_data['sum_draft'], '$ 0.00') + self.assertIn('0.00', dashboard_data['sum_draft']) self.assertEquals(dashboard_data['number_waiting'], 2) - self.assertEquals(dashboard_data['sum_waiting'], '$ 78.42') + self.assertIn('78.42', dashboard_data['sum_waiting']) with patch('odoo.fields.Date.today', patched_today): dashboard_data = journal.get_journal_dashboard_datas() self.assertEquals(dashboard_data['number_late'], 2) - self.assertEquals(dashboard_data['sum_late'], '$ 78.42') + self.assertIn('78.42', dashboard_data['sum_late']) diff --git a/addons/account/tests/test_reconciliation.py b/addons/account/tests/test_reconciliation.py index 0fc4c2bc7dd..8ce32823042 100644 --- a/addons/account/tests/test_reconciliation.py +++ b/addons/account/tests/test_reconciliation.py @@ -91,6 +91,11 @@ class TestReconciliation(AccountingTestCase): 'code': 'CABA', 'type': 'general', }) + self.general_journal = self.env['account.journal'].create({ + 'name': 'general', + 'code': 'GENE', + 'type': 'general', + }) # Tax Cash Basis self.tax_cash_basis = self.env['account.tax'].create({ @@ -2034,3 +2039,68 @@ class TestReconciliationExec(TestReconciliation): pay_receivable_line1 = payment1.move_line_ids.filtered(lambda l: l.account_id == self.account_rcv) self.assertTrue(pay_receivable_line1.reconciled) self.assertEqual(pay_receivable_line1.matched_debit_ids, move_caba1.tax_cash_basis_rec_id) + + def test_reconciliation_with_currency(self): + #reconciliation on an account having a foreign currency being + #the same as the company one + account_rcv = self.account_rcv + account_rcv.currency_id = self.currency_euro_id + aml_obj = self.env['account.move.line'].with_context( + check_move_validity=False) + general_move1 = self.env['account.move'].create({ + 'name': 'general1', + 'journal_id': self.general_journal.id, + }) + aml_obj.create({ + 'name': 'debit1', + 'account_id': account_rcv.id, + 'debit': 11, + 'move_id': general_move1.id, + }) + aml_obj.create({ + 'name': 'credit1', + 'account_id': self.account_rsa.id, + 'credit': 11, + 'move_id': general_move1.id, + }) + general_move1.post() + general_move2 = self.env['account.move'].create({ + 'name': 'general2', + 'journal_id': self.general_journal.id, + }) + aml_obj.create({ + 'name': 'credit2', + 'account_id': account_rcv.id, + 'credit': 10, + 'move_id': general_move2.id, + }) + aml_obj.create({ + 'name': 'debit2', + 'account_id': self.account_rsa.id, + 'debit': 10, + 'move_id': general_move2.id, + }) + general_move2.post() + general_move3 = self.env['account.move'].create({ + 'name': 'general3', + 'journal_id': self.general_journal.id, + }) + aml_obj.create({ + 'name': 'credit3', + 'account_id': account_rcv.id, + 'credit': 1, + 'move_id': general_move3.id, + }) + aml_obj.create({ + 'name': 'debit3', + 'account_id': self.account_rsa.id, + 'debit': 1, + 'move_id': general_move3.id, + }) + general_move3.post() + to_reconcile = ((general_move1 + general_move2 + general_move3) + .mapped('line_ids') + .filtered(lambda l: l.account_id.id == account_rcv.id)) + to_reconcile.reconcile() + for aml in to_reconcile: + self.assertEqual(aml.amount_residual, 0.0) diff --git a/addons/account_analytic_default/models/account_analytic_default.py b/addons/account_analytic_default/models/account_analytic_default.py index 8a19f54c2a1..34052a51560 100644 --- a/addons/account_analytic_default/models/account_analytic_default.py +++ b/addons/account_analytic_default/models/account_analytic_default.py @@ -66,8 +66,13 @@ class AccountInvoiceLine(models.Model): @api.onchange('product_id') def _onchange_product_id(self): res = super(AccountInvoiceLine, self)._onchange_product_id() - rec = self.env['account.analytic.default'].account_get(self.product_id.id, self.invoice_id.commercial_partner_id.id, self.env.uid, - fields.Date.today(), company_id=self.company_id.id) + rec = self.env['account.analytic.default'].account_get( + self.product_id.id, + self.invoice_id.commercial_partner_id.id, + self.invoice_id.user_id.id or self.env.uid, + fields.Date.today(), + company_id=self.company_id.id + ) self.account_analytic_id = rec.analytic_id.id self.analytic_tag_ids = rec.analytic_tag_ids.ids return res @@ -75,8 +80,12 @@ class AccountInvoiceLine(models.Model): def _set_additional_fields(self, invoice): if not self.account_analytic_id or not self.analytic_tag_ids: rec = self.env['account.analytic.default'].account_get( - self.product_id.id, self.invoice_id.commercial_partner_id.id, self.env.uid, - fields.Date.today(), company_id=invoice.company_id.id) + self.product_id.id, + self.invoice_id.commercial_partner_id.id, + self.invoice_id.user_id.id or self.env.uid, + fields.Date.today(), + company_id=invoice.company_id.id + ) if rec: if self.account_analytic_id: self.account_analytic_id = rec.analytic_id.id diff --git a/addons/account_voucher/models/account_voucher.py b/addons/account_voucher/models/account_voucher.py index d868a1de62f..a3080952fcd 100644 --- a/addons/account_voucher/models/account_voucher.py +++ b/addons/account_voucher/models/account_voucher.py @@ -37,7 +37,7 @@ class AccountVoucher(models.Model): ('purchase', 'Purchase') ], string='Type', readonly=True, states={'draft': [('readonly', False)]}, oldname="type") name = fields.Char('Payment Memo', - readonly=True, states={'draft': [('readonly', False)]}, default='') + readonly=True, states={'draft': [('readonly', False)]}, default='',copy=False) date = fields.Date("Bill Date", readonly=True, index=True, states={'draft': [('readonly', False)]}, copy=False, default=fields.Date.context_today) diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index 7f257e3d19f..412787c7878 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -323,6 +323,12 @@ class AlarmManager(models.AbstractModel): 'rrule': rule } + # determine accessible events + events = self.env['calendar.event'].browse(result) + result = { + key: result[key] + for key in set(events._filter_access_rules('read').ids) + } return result def do_check_alarm_for_one_date(self, one_date, event, event_maxdelta, in_the_next_X_seconds, alarm_type, after=False, missing=False): diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py index dec8489a526..55b487d6340 100644 --- a/addons/crm/models/crm_lead.py +++ b/addons/crm/models/crm_lead.py @@ -312,9 +312,10 @@ class Lead(models.Model): if vals.get('user_id') and 'date_open' not in vals: vals['date_open'] = fields.Datetime.now() - if context.get('default_partner_id') and not vals.get('email_from'): - partner = self.env['res.partner'].browse(context['default_partner_id']) - vals['email_from'] = partner.email + partner_id = vals.get('partner_id') or context.get('default_partner_id') + onchange_values = self._onchange_partner_id_values(partner_id) + onchange_values.update(vals) # we don't want to overwrite any existing key + vals = onchange_values # context: no_log, because subtype already handle this return super(Lead, self.with_context(context, mail_create_nolog=True)).create(vals) @@ -324,7 +325,8 @@ class Lead(models.Model): # stage change: update date_last_stage_update if 'stage_id' in vals: vals['date_last_stage_update'] = fields.Datetime.now() - if vals.get('user_id') and 'date_open' not in vals: + # Only write the 'date_open' if no salesperson was assigned. + if vals.get('user_id') and 'date_open' not in vals and not self.mapped('user_id'): vals['date_open'] = fields.Datetime.now() # stage change with new stage: update probability and date_closed if vals.get('stage_id') and 'probability' not in vals: diff --git a/addons/event_sale/models/sale_order.py b/addons/event_sale/models/sale_order.py index 52017208adc..7ca5360166c 100644 --- a/addons/event_sale/models/sale_order.py +++ b/addons/event_sale/models/sale_order.py @@ -81,7 +81,7 @@ class SaleOrderLine(models.Model): @api.onchange('event_ticket_id') def _onchange_event_ticket_id(self): company = self.event_id.company_id or self.env.user.company_id - currency = company.currency_id + currency = company.currency_id or self.env.user.company_id.currency_id self.price_unit = currency._convert( self.event_ticket_id.price, self.order_id.currency_id, self.order_id.company_id, self.order_id.date_order or fields.Date.today()) diff --git a/addons/hr_contract/models/hr_contract.py b/addons/hr_contract/models/hr_contract.py index eef536458ad..453ec9ff076 100644 --- a/addons/hr_contract/models/hr_contract.py +++ b/addons/hr_contract/models/hr_contract.py @@ -51,7 +51,7 @@ class ContractType(models.Model): _description = 'Contract Type' _order = 'sequence, id' - name = fields.Char(string='Contract Type', required=True) + name = fields.Char(string='Contract Type', required=True, translate=True) sequence = fields.Integer(help="Gives the sequence when displaying a list of Contract.", default=10) diff --git a/addons/hr_expense/models/hr_expense.py b/addons/hr_expense/models/hr_expense.py index 13a35b10f5a..d3ecb721635 100644 --- a/addons/hr_expense/models/hr_expense.py +++ b/addons/hr_expense/models/hr_expense.py @@ -151,14 +151,14 @@ class HrExpense(models.Model): @api.model def get_empty_list_help(self, help_message): - if help_message and "oe_view_nocontent_smiling_face" not in help_message: + if help_message and "o_view_nocontent_smiling_face" not in help_message: use_mailgateway = self.env['ir.config_parameter'].sudo().get_param('hr_expense.use_mailgateway') alias_record = use_mailgateway and self.env.ref('hr_expense.mail_alias_expense') or False if alias_record and alias_record.alias_domain and alias_record.alias_name: link = "%(email)s" % { 'email': '%s@%s' % (alias_record.alias_name, alias_record.alias_domain) } - return '

%s

%s

' % ( + return '

%s

%s

' % ( _('Add a new expense,'), _('or send receipts by email to %s.') % (link),) return super(HrExpense, self).get_empty_list_help(help_message) @@ -211,6 +211,25 @@ class HrExpense(models.Model): # Business # ---------------------------------------- + @api.multi + def _prepare_move_values(self): + """ + This function prepares move values related to an expense + """ + self.ensure_one() + journal = self.sheet_id.bank_journal_id if self.payment_mode == 'company_account' else self.sheet_id.journal_id + account_date = self.sheet_id.accounting_date or self.date + move_values = { + 'journal_id': journal.id, + 'company_id': self.env.user.company_id.id, + 'date': account_date, + 'ref': self.sheet_id.name, + # force the name to the default value, to avoid an eventual 'default_name' in the context + # to set it to '' which cause no number to be given to the account.move when posted. + 'name': '/', + } + return move_values + @api.multi def _get_account_move_by_sheet(self): """ Return a mapping between the expense sheet of current expense and its account move @@ -219,18 +238,8 @@ class HrExpense(models.Model): move_grouped_by_sheet = {} for expense in self: # create the move that will contain the accounting entries - account_date = expense.sheet_id.accounting_date or expense.date if expense.sheet_id.id not in move_grouped_by_sheet: - journal = expense.sheet_id.bank_journal_id if expense.payment_mode == 'company_account' else expense.sheet_id.journal_id - move = self.env['account.move'].create({ - 'journal_id': journal.id, - 'company_id': self.env.user.company_id.id, - 'date': account_date, - 'ref': expense.sheet_id.name, - # force the name to the default value, to avoid an eventual 'default_name' in the context - # to set it to '' which cause no number to be given to the account.move when posted. - 'name': '/', - }) + move = self.env['account.move'].create(expense._prepare_move_values()) move_grouped_by_sheet[expense.sheet_id.id] = move else: move = move_grouped_by_sheet[expense.sheet_id.id] diff --git a/addons/hr_holidays/models/hr.py b/addons/hr_holidays/models/hr.py index 6a0dae5d5a2..2a8a5506217 100644 --- a/addons/hr_holidays/models/hr.py +++ b/addons/hr_holidays/models/hr.py @@ -206,8 +206,8 @@ class Employee(models.Model): hr_vals['manager_id'] = values['parent_id'] if values.get('department_id') is not None: hr_vals['department_id'] = values['department_id'] - holidays = self.env['hr.leave'].search(['|',('state', 'in', ['draft', 'confirm']),('date_from', '>', today_date), ('employee_id', 'in', self.ids)]) + holidays = self.env['hr.leave'].sudo().search(['|',('state', 'in', ['draft', 'confirm']),('date_from', '>', today_date), ('employee_id', 'in', self.ids)]) holidays.write(hr_vals) - allocations = self.env['hr.leave.allocation'].search([('state', 'in', ['draft', 'confirm']), ('employee_id', 'in', self.ids)]) + allocations = self.env['hr.leave.allocation'].sudo().search([('state', 'in', ['draft', 'confirm']), ('employee_id', 'in', self.ids)]) allocations.write(hr_vals) return res diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index 73205a5a6a3..d727b98de7d 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -359,11 +359,17 @@ class HolidaysRequest(models.Model): self.mode_company_id = False self.department_id = False + @api.multi + def _sync_employee_details(self): + for holiday in self: + holiday.manager_id = holiday.employee_id.parent_id.id + if holiday.employee_id: + holiday.department_id = holiday.employee_id.department_id + @api.onchange('employee_id') def _onchange_employee_id(self): - self.manager_id = self.employee_id.parent_id.id - if self.employee_id: - self.department_id = self.employee_id.department_id + self._sync_employee_details() + self.holiday_status_id = False @api.onchange('date_from', 'date_to', 'employee_id') def _onchange_leave_dates(self): @@ -427,7 +433,7 @@ class HolidaysRequest(models.Model): def _check_date(self): for holiday in self: domain = [ - ('date_from', '<=', holiday.date_to), + ('date_from', '<', holiday.date_to), ('date_to', '>', holiday.date_from), ('employee_id', '=', holiday.employee_id.id), ('id', '!=', holiday.id), @@ -535,7 +541,7 @@ class HolidaysRequest(models.Model): if holiday.validation_type == 'hr': holiday.message_subscribe(partner_ids=(holiday.employee_id.parent_id.user_id.partner_id | holiday.employee_id.leave_manager_id.partner_id).ids) if employee_id: - holiday._onchange_employee_id() + holiday._sync_employee_details() if 'number_of_days' not in values and ('date_from' in values or 'date_to' in values): holiday._onchange_leave_dates() if leave_type.validation_type == 'no_validation': @@ -574,7 +580,7 @@ class HolidaysRequest(models.Model): for holiday in self: if employee_id: holiday.add_follower(employee_id) - holiday._onchange_employee_id() + self._sync_employee_details() if 'number_of_days' not in values and ('date_from' in values or 'date_to' in values): holiday._onchange_leave_dates() return result diff --git a/addons/hr_holidays/models/hr_leave_allocation.py b/addons/hr_holidays/models/hr_leave_allocation.py index adaa50d7e61..ce96a2fac9b 100644 --- a/addons/hr_holidays/models/hr_leave_allocation.py +++ b/addons/hr_holidays/models/hr_leave_allocation.py @@ -207,7 +207,10 @@ class HolidaysAllocation(models.Model): @api.depends('number_of_days', 'employee_id') def _compute_number_of_hours_display(self): for allocation in self: - allocation.number_of_hours_display = allocation.number_of_days * (allocation.employee_id.resource_calendar_id.hours_per_day or HOURS_PER_DAY) + if allocation.parent_id and allocation.parent_id.type_request_unit == "hour": + allocation.number_of_hours_display = allocation.number_of_days * HOURS_PER_DAY + else: + allocation.number_of_hours_display = allocation.number_of_days * (allocation.employee_id.resource_calendar_id.hours_per_day or HOURS_PER_DAY) @api.multi @api.depends('number_of_hours_display', 'number_of_days_display') diff --git a/addons/hr_holidays/tests/test_leave_requests.py b/addons/hr_holidays/tests/test_leave_requests.py index 9f32d96e6c6..f15f9cfb9e5 100644 --- a/addons/hr_holidays/tests/test_leave_requests.py +++ b/addons/hr_holidays/tests/test_leave_requests.py @@ -158,9 +158,9 @@ class TestLeaveRequests(TestHrHolidaysBase): self.employee_hrmanager.write({'department_id': self.hr_dept.id}) self.assertFalse(self.env['hr.leave'].search([('employee_id', 'in', self.hr_dept.member_ids.ids)])) leave_form = Form(self.env['hr.leave'].sudo(self.user_hrmanager)) - leave_form.holiday_status_id = self.holidays_type_1 leave_form.holiday_type = 'department' leave_form.department_id = self.hr_dept + leave_form.holiday_status_id = self.holidays_type_1 leave = leave_form.save() leave.action_approve() member_ids = self.hr_dept.member_ids.ids diff --git a/addons/hw_scale/controllers/main.py b/addons/hw_scale/controllers/main.py index bb98a8521d0..1ebb6e39af2 100644 --- a/addons/hw_scale/controllers/main.py +++ b/addons/hw_scale/controllers/main.py @@ -8,7 +8,7 @@ import time from collections import namedtuple from os import listdir -from threading import Thread, Lock +from threading import Event, Lock, Thread from odoo import http @@ -134,6 +134,7 @@ class Scale(Thread): self.path_to_scale = '' self.protocol = None self.disabled = False + self.weight_request_event = Event() def lockedstart(self): with self.lock: @@ -261,8 +262,8 @@ class Scale(Thread): return None def get_weight(self): - self.repeats = 5 self.disabled = False + self.weight_request_event.set() self.lockedstart() return self.weight @@ -361,11 +362,13 @@ class Scale(Thread): self.device = self.get_device() if not self.device: # retry later to support "plug and play" - time.sleep(10) + self.weight_request_event.clear() + self.weight_request_event.wait(10) else: self.disabled = self.protocol.disable else: - time.sleep(10) + self.weight_request_event.clear() + self.weight_request_event.wait(10) scale_thread = None diff --git a/addons/iap/models/iap.py b/addons/iap/models/iap.py index af375d5050b..263bf86196a 100644 --- a/addons/iap/models/iap.py +++ b/addons/iap/models/iap.py @@ -162,7 +162,7 @@ class IapAccount(models.Model): @api.model def get(self, service_name, force_create=True): - account = self.search([('service_name', '=', service_name), ('company_id', 'in', [self.env.user.company_id.id, False])]) + account = self.search([('service_name', '=', service_name), ('company_id', 'in', [self.env.user.company_id.id, False])], limit=1, order='company_id desc, id desc') if not account and force_create: account = self.create({'service_name': service_name}) # Since the account did not exist yet, we will encounter a NoCreditError, diff --git a/addons/iap/security/ir.model.access.csv b/addons/iap/security/ir.model.access.csv index 7e423f3c57a..80fd4e2212f 100644 --- a/addons/iap/security/ir.model.access.csv +++ b/addons/iap/security/ir.model.access.csv @@ -1,3 +1,3 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_client_iap_account_manager,iap.account.manager,model_iap_account,base.group_system,1,1,1,0 +access_client_iap_account_manager,iap.account.manager,model_iap_account,base.group_system,1,1,1,1 access_client_iap_account_user,iap.account.user,model_iap_account,base.group_user,1,0,1,0 diff --git a/addons/l10n_ae/__manifest__.py b/addons/l10n_ae/__manifest__.py index d9542262df7..bc5da58dfe3 100644 --- a/addons/l10n_ae/__manifest__.py +++ b/addons/l10n_ae/__manifest__.py @@ -14,11 +14,14 @@ United Arab Emirates accounting chart and localization. """, 'depends': ['base', 'account'], 'data': [ + 'data/l10n_ae_data.xml', 'data/account_data.xml', 'data/l10n_ae_chart_data.xml', 'data/account.account.template.csv', 'data/l10n_ae_chart_post_data.xml', 'data/account_tax_template_data.xml', + 'data/fiscal_templates_data.xml', 'data/account_chart_template_data.xml', + 'views/report_invoice_templates.xml', ], } diff --git a/addons/l10n_ae/data/account_data.xml b/addons/l10n_ae/data/account_data.xml index 48fcd567909..df9792faae5 100644 --- a/addons/l10n_ae/data/account_data.xml +++ b/addons/l10n_ae/data/account_data.xml @@ -1,9 +1,15 @@ - + - - Tax 15% + + Tax 5% + + + Tax 0% + + + Tax Exempted diff --git a/addons/l10n_ae/data/account_tax_template_data.xml b/addons/l10n_ae/data/account_tax_template_data.xml index eb60fb97ba8..b7299572170 100644 --- a/addons/l10n_ae/data/account_tax_template_data.xml +++ b/addons/l10n_ae/data/account_tax_template_data.xml @@ -1,21 +1,339 @@ - - - Tax 10% - 10 + + Output VAT 5% (Dubai) + taxes + + + Output VAT 5% (Abu Dhabi) + taxes + + + Output VAT 5% (Sharjah) + taxes + + + Output VAT 5% (Ajman) + taxes + + + Output VAT 5% (Umm Al Quwain) + taxes + + + Output VAT 5% (Ras Al-Khaima) + taxes + + + Output VAT 5% (Fujairah) + taxes + + + Input VAT 5% + taxes + + + Exempted Output VAT + taxes + + + Exempted Input VAT + taxes + + + Output VAT 0% + taxes + + + Input VAT 0% + taxes + + + Import VAT 5% + taxes + + + Export VAT 0% + taxes + + + Reverse Charge TVA -5%(sales) + taxes + + + Reverse Charge TVA -5%(purchase) + taxes + + + Tourist Refund scheme 5% + taxes + + + + + TVA 5% (Dubai) sale + 5 + percent + TVA 5% - - - + + - Purchase Tax 10% - 10 + + + TVA 5% (Abu Dhabi) + sale + 5 + percent + TVA 5% + + + + + + + + TVA 5% (Sharjah) + sale + 5 + percent + TVA 5% + + + + + + + + TVA 5% (Ajman) + sale + 5 + percent + TVA 5% + + + + + + + + TVA 5% (Umm Al Quwain) + sale + 5 + percent + TVA 5% + + + + + + + + TVA 5% (Ras Al-Khaima) + sale + 5 + percent + TVA 5% + + + + + + + + TVA 5% (Fujairah) + sale + 5 + percent + TVA 5% + + + + + + + + Exempted Tax + sale + 0 + percent + Exempted + + + + + + + + TVA 0% + sale + 0 + percent + TVA 0% + + + + + + + + Export Tax 0% + sale + 0 + percent + Export Tax + + + + + Reverse Charge TVA -5%(Sale) + none + -5.0 + percent + + + + + + + Reverse Charge Provision (Dubai) + sale + 0.0 + group + Supplies subject to reverse charge provisions + + + + + Reverse Charge Provision (Abi Dhabi) + sale + 0.0 + group + Supplies subject to reverse charge provisions + + + + + Reverse Charge Provision (Sharjah) + sale + 0.0 + group + Supplies subject to reverse charge provisions + + + + + Reverse Charge Provision (Ajman) + sale + 0.0 + group + Supplies subject to reverse charge provisions + + + + + Reverse Charge Provision (Umm Al Quwain) + sale + 0.0 + group + Supplies subject to reverse charge provisions + + + + + Reverse Charge Provision (Ras Al-Khaima) + sale + 0.0 + group + Supplies subject to reverse charge provisions + + + + + Reverse Charge Provision (Fujairah) + sale + 0.0 + group + Supplies subject to reverse charge provisions + + + + + Tourist Refund scheme 5% + sale + 5.0 + percent + Tax Refunds provided to Tourists under the Tax Refunds for Tourists Scheme + + + + + + + + TVA 5% purchase + 5 + percent + TVA 5% - + + + + + + Exempted Tax + purchase + 0 + percent + Exempted Tax + + + + + + + + TVA 0% + purchase + 0 + percent + TVA 0% + + + + + + + + Import Tax 5% + purchase + 5 + percent + Import Tax + + + + + Reverse Charge TVA -5%(Purchase) + none + -5.0 + percent + + + + + + + Reverse Charge Provision + purchase + 0.0 + group + Supplies subject to reverse charge provisions + + diff --git a/addons/l10n_ae/data/fiscal_templates_data.xml b/addons/l10n_ae/data/fiscal_templates_data.xml new file mode 100644 index 00000000000..2579a2ad720 --- /dev/null +++ b/addons/l10n_ae/data/fiscal_templates_data.xml @@ -0,0 +1,112 @@ + + + + Dubai + + 16 + + + + + + + Abu Dhabi + + 16 + + + + + + + + + + + + Sharjah + + 16 + + + + + + + + + + + + Ajman + + 16 + + + + + + + + + + + + Umm Al Quwain + + 16 + + + + + + + + + + + + Ras Al-Khaima + + 16 + + + + + + + + + + + + Fujairah + + 16 + + + + + + + + + + + + Non-UAE + + 20 + + + + + + + + + + + + + diff --git a/addons/l10n_ae/data/l10n_ae_chart_data.xml b/addons/l10n_ae/data/l10n_ae_chart_data.xml index 0c8202a34f2..eb648164386 100644 --- a/addons/l10n_ae/data/l10n_ae_chart_data.xml +++ b/addons/l10n_ae/data/l10n_ae_chart_data.xml @@ -1,5 +1,7 @@ + + U.A.E Chart of Accounts - Standard 6 @@ -7,6 +9,6 @@ 105 100 - + diff --git a/addons/l10n_ae/data/l10n_ae_data.xml b/addons/l10n_ae/data/l10n_ae_data.xml new file mode 100644 index 00000000000..94692698ecd --- /dev/null +++ b/addons/l10n_ae/data/l10n_ae_data.xml @@ -0,0 +1,14 @@ + + + + + TRN + + + AED + + + GCC VAT implementing States + + + diff --git a/addons/l10n_ae/views/report_invoice_templates.xml b/addons/l10n_ae/views/report_invoice_templates.xml new file mode 100644 index 00000000000..681fe038284 --- /dev/null +++ b/addons/l10n_ae/views/report_invoice_templates.xml @@ -0,0 +1,35 @@ + + + + diff --git a/addons/l10n_fr_fec/wizard/account_fr_fec.py b/addons/l10n_fr_fec/wizard/account_fr_fec.py index 0a6459a0953..fd4eb978262 100644 --- a/addons/l10n_fr_fec/wizard/account_fr_fec.py +++ b/addons/l10n_fr_fec/wizard/account_fr_fec.py @@ -305,7 +305,7 @@ class AccountFrFec(models.TransientModel): END AS PieceRef, TO_CHAR(am.date, 'YYYYMMDD') AS PieceDate, - CASE WHEN aml.name IS NULL THEN '/' ELSE replace(replace(aml.name, '|', '/'), '\t', '') END AS EcritureLib, + CASE WHEN aml.name IS NULL OR aml.name = '' THEN '/' ELSE replace(replace(aml.name, '|', '/'), '\t', '') END AS EcritureLib, replace(CASE WHEN aml.debit = 0 THEN '0,00' ELSE to_char(aml.debit, '000000000000000D99') END, '.', ',') AS Debit, replace(CASE WHEN aml.credit = 0 THEN '0,00' ELSE to_char(aml.credit, '000000000000000D99') END, '.', ',') AS Credit, CASE WHEN rec.name IS NULL THEN '' ELSE rec.name END AS EcritureLet, @@ -388,7 +388,7 @@ class AccountFrFec(models.TransientModel): rows_length = len(rows) for i, row in enumerate(rows): if not i == rows_length - 1: - row.append(lineterminator) + row[-1] += lineterminator writer.writerow(row) fecvalue = fecfile.getvalue() diff --git a/addons/l10n_mn/__init__.py b/addons/l10n_mn/__init__.py new file mode 100644 index 00000000000..67dee8c60db --- /dev/null +++ b/addons/l10n_mn/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. diff --git a/addons/l10n_mn/__manifest__.py b/addons/l10n_mn/__manifest__.py new file mode 100644 index 00000000000..a99552f8ee3 --- /dev/null +++ b/addons/l10n_mn/__manifest__.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +{ + "name" : "Mongolia - Accounting", + "version" : "1.0", + 'category': 'Localization', + "description": """ +This is the module to manage the accounting chart for Mongolia. +=============================================================== + + * the Mongolia Official Chart of Accounts, + * the Tax Code Chart for Mongolia + * the main taxes used in Mongolia + +Financial requirement contributor: Baskhuu Lodoikhuu. BumanIT LLC +""", + "depends": ['account'], + 'data': [ + 'data/account_chart_template_data.xml', + 'data/account.account.tag.csv', + 'data/account.account.template.csv', + 'data/account.tax.group.csv', + 'data/account.tax.template.csv', + 'data/account_fiscal_position_template_data.xml', + 'data/account.chart.template.csv', + 'data/account_chart_template_configuration_data.xml', + ], +} diff --git a/addons/l10n_mn/data/account.account.tag.csv b/addons/l10n_mn/data/account.account.tag.csv new file mode 100644 index 00000000000..b8667ffc12d --- /dev/null +++ b/addons/l10n_mn/data/account.account.tag.csv @@ -0,0 +1,94 @@ +id,name,applicability +account.account_tag_operating,CF: Үндсэн: Бусад,accounts +account.account_tag_financing,CF: Хөрөнгө оруулалт: Бусад Урт хугацаат хөрөнгө,accounts +account.account_tag_investing,CF: Санхүү: Ногдол ашиг,accounts +account_tag_operating_product,CF: Үндсэн: Бараа үйлчилгээ,accounts +account_tag_operating_loyalty,CF: Үндсэн: Эрхийн шимтгэл хураамж,accounts +account_tag_operating_insurance,CF: Үндсэн: Нийгмийн Даатгал,accounts +account_tag_operating_insurance2,CF: Үндсэн: Бусад Даатгал,accounts +account_tag_operating_taxrefund,CF: Үндсэн: Татвар,accounts +account_tag_operating_funding,CF: Үндсэн: Татаас санхүүжилт,accounts +account_tag_operating_employee,CF: Үндсэн: Ажилчид,accounts +account_tag_operating_cost,CF: Үндсэн: Ашиглалтын зардал,accounts +account_tag_operating_transport,CF: Үндсэн: Түлш тээвэр сэлбэг,accounts +account_tag_operating_interest,CF: Үндсэн: Зээлийн хүү,accounts +account_tag_investing_fasset,CF: Хөрөнгө оруулалт: Үндсэн хөрөнгө,accounts +account_tag_investing_iasset,CF: Хөрөнгө оруулалт: Биет бус хөрөнгө,accounts +account_tag_investing_invest,CF: Хөрөнгө оруулалт: Хөрөнгө оруулалт,accounts +account_tag_investing_loan,CF: Хөрөнгө оруулалт: Зээл урьдчилгаа,accounts +account_tag_investing_interest,CF: Хөрөнгө оруулалт: Зээлийн хүү,accounts +account_tag_investing_dividends,CF: Хөрөнгө оруулалт: Ногдол ашиг,accounts +account_tag_financing_loan,"CF: Санхүү: Зээл, өрийн үнэт цаас",accounts +account_tag_financing_rental,CF: Санхүү: Санхүүгийн түрээс,accounts +account_tag_financing_stock,CF: Санхүү: Хувьцаа өмчийн бусад үнэт цаас,accounts +account_tag_financing_donation,CF: Санхүү: Хандив,accounts +account_tag_exchange,CF: Валютын ханшийн зөрүү,accounts +vat_report_tag2,ТТ3а: НӨАТ-аас чөлөөлөгдөх борлуулалтын орлого (2),taxes +vat_report_tag5,ТТ3a: Дотоодын зах зээлд борлуулсан барааны борлуулалтын орлого (5),taxes +vat_report_tag6,ТТ3a: Бусад барааны борлуулалтын орлого (6),taxes +vat_report_tag7,ТТ3a: Эрх борлуулсны орлого (7),taxes +vat_report_tag8,ТТ3a: Татан буугдах үед үлдсэн барааны орлого (8),taxes +vat_report_tag9,ТТ3a: Өрийн төлбөрт шилжүүлсэн барааны орлого (9),taxes +vat_report_tag11,ТТ3a: Наториатын үйлчилгээний орлого (11),taxes +vat_report_tag12,ТТ3a: Өрийн төлбөрт тооцсон ажил үйлчилгээний орлого (12),taxes +vat_report_tag13,"ТТ3a: Цахилгаан, дулаан, ус, шуудан, холбооны үйлчилгээ үзүүлсний орлого (13)",taxes +vat_report_tag14,"ТТ3a: Бараа түрээслүүлэх, эзэмшүүлэх, ашиглуулах үйлчилгээний орлого (14)",taxes +vat_report_tag15,"ТТ3a: Байр түрээслүүлэх, эзэмшүүлэх, ашиглуулах үйлчилгээний орлого (15)",taxes +vat_report_tag16,"ТТ3a: Үл хөдлөх, хөдлөх хөрөнгө түрээслүүлэх, эзэмшүүлэх ашиглуулах үйлчилгээий орлого (16)",taxes +vat_report_tag17,"ТТ3a: Шинэ бүтээл, загвар, зохиогчийн эрх, барааны тэмдэг худалдсаны орлого (17)",taxes +vat_report_tag18,"ТТ3a: Хонжворт сугалаа, төлбөрт таавар, бооцоот тоглоомын орлого (18)",taxes +vat_report_tag19,ТТ3a: Зуучлалын үйлчилгээний орлого (19),taxes +vat_report_tag20,"ТТ3a: Бусдаас авсан хүү, торгууль, алдангийн орлого (20)",taxes +vat_report_tag21,ТТ3a: Хөрөнгийн үнэлгээний үйлчилгээний орлого (21),taxes +vat_report_tag22,"ТТ3a: Төсвийн санхүүжилт, татаас, урамшууллын орлого (22)",taxes +vat_report_tag23,"ТТ3a: Өмгөөлөл, хууль зүйн үйлчилгээний орлого (23)",taxes +vat_report_tag24,"ТТ3a: Үсчин, гоо сайхан, засвар үйлчилгээ, угаалга, хими цэвэрлэгээний үйлчилгээний орлого (24)",taxes +vat_report_tag25,ТТ3a: Хуулийн 13-т зааснаас бусад үйлчилгээний орлого (25),taxes +vat_report_tag28,ТТ3a: Экспортонд гаргасан барааны борлуулалтын орлого (28),taxes +vat_report_tag29,ТТ3a: Экспортолсон үйлчилгээний борлуулалтын орлого (29),taxes +vat_report_tag33,"ТТ3а: Худалдан авсан нийт бараа, ажил үйлчилгээ (33)",taxes +vat_report_tag35,"ТТ3a: НӨАТ-тэй авсан Импортын бараа, ажил үйлчилгээний худалдан авалт (35)",taxes +vat_report_tag36,"ТТ3a: Дотоодын зах зээлээс НӨАТ-тэй авсан бараа, ажил, үйлчилгээ (36)",taxes +vat_report_tag37,"ТТ3a: Суутган төлөгчөөр бүртгүүлэх үед НӨАТ-тэй авсан бараа, үйлчилгээ (37)",taxes +vat_report_tag38,"ТТ3a: Мал аж ахуй, тариалан эрхлэгчээс НӨАТ-тэй авсан бараа, үйлчилгээ (38)",taxes +vat_report_tag41,"ТТ3а: Суудлын автомашин, түүний эд анги сэлбэгт төлсөн НӨАТ (41)",taxes +vat_report_tag42,"ТТ3а: Ажлын хэрэгцээнд зориулж авсан бараа, үйлчилгээнд төлсөн НӨАТ (42)",taxes +vat_report_tag43,"ТТ3а: Үндсэн хөрөнгө бэлтгэхэд зориулж импортоор авсан бараа, үйлчилгээнд төлсөн НӨАТ (43)",taxes +vat_report_tag44,"ТТ3а: Чөлөөлөгдөх үйлдвэрлэл, үйлчилгээнд зориулж авсан бараа, ажил, үйлчилгээнд төлсөн НӨАТ (44)",taxes +vat_report_tag45,"ТТ3а: Хайгуулын ажил болон ашиглалтын өмнөх үйл ажиллагаанд зориулж импортоор авсан бараа, ажил, үйлчилгээнд төлсөн НӨАТ (45)",taxes +vat_report_tag46,"ТТ3а: Импортоор оруулсан бусад хамааралгүй бараа, ажил, үйлчилгээнд төлсөн НӨАТ (46)",taxes +vat_report_tag48,ТТ3а: Cанхүүгийн түрээсээр дотоодын зах зээлд борлуулсны орлого (48),taxes +vat_report_tag49,"ТТ3а: Факторинг, форфайтинг хэлцлийн үйлчилгээний орлого (49)",taxes +vat_report_tag51,ТТ3а: Санхүүгийн түрээсийн зүйлийг худалдан авахад төлсөн түрээсийн төлбөр (51),taxes +vat_report_tag52,"ТТ3а: Факторинг, форфайтинг хэлцлийг авахад төлсөн төлбөр (52)",taxes +vat_report_tag58,"ТТ3а: Борлуулалтын орлогын буцаалт, хөнгөлөлт (58)",accounts +vat_report_tag59,"ТТ3а: Худалдан авалтын буцаалт, хөнгөлөлт (59)",accounts +tax_report_tag2,ТТ02: Татвараас чөлөөлөгдөх орлого (2),accounts +tax_report_tag5,ТТ02: Бусад орлогын дүн (5),accounts +tax_report_tag7,ТТ02: Үндсэн ажил үйлчилгээний орлого (7),accounts +tax_report_tag8,ТТ02: Туслах ажил үйлчилгээний орлого (8),accounts +tax_report_tag9,"ТТ02: Хувьцаа, үнэт цаас борлуулсны орлого (9)",accounts +tax_report_tag10,"ТТ02: Үнэ төлбөргүйгээр бусдаас авсан бараа, үйлчилгээ (10)",accounts +tax_report_tag11,ТТ02: Биет бус хөрөнгө борлуулсны орлого (11),accounts +tax_report_tag12,ТТ02: Техникийн зөвлөх үйлчилгээний орлого (12),accounts +tax_report_tag13,"ТТ02: Гэрээний хүү, торгууль, хохирлын нөхөн төлбөрийн орлого (13)",accounts +tax_report_tag14,ТТ02: Гадаад валютын ханшийн зөрүүгийн бодит орлого (14),accounts +tax_report_tag15,ТТ02: Хөдлөх болон үл хөдлөх эд хөрөнгийн түрээсийн орлого (15),accounts +tax_report_tag16,ТТ02: Хөдлөх эд хөрөнгө борлуулсны орлого (16),accounts +tax_report_tag17,ТТ02: Албан татвар ногдох бусад орлого (17),accounts +tax_report_tag22,ТТ02: Татвар ногдох орлогоос хасагдахгүй зардал (22),accounts +tax_report_tag23,ТТ02: Татвар ногдох орлогыг бууруулах (23),accounts +tax_report_tag25,ТТ02: Сайн дурын даатгалын хураамжийн хэтрэлт (25),accounts +tax_report_tag27,ТТ02: Өмнөх жилийн татварын алдагдлаас тайлант хугацаанд шилжүүлсэн дүн (27),accounts +tax_report_tag30,ТТ02: Татварын хөнгөлөлт (30),accounts +tax_report_tag32,"ТТ02: Эротик хэвлэл, бичлэг, тоглолт борлуулалтын орлого (32)",accounts +tax_report_tag34,"ТТ02: Таавар, бооцоот тоглоом, хонжворт сугалааны орлого (34)",accounts +tax_report_tag35,"ТТ02: Таавар, бооцоот тоглоом, хонжворт сугалааны орлого олоход зарцуулсан зардал (35)",accounts +tax_report_tag36,ТТ02: Хонжворт олгосон мөнгө болон барааны үнэ (36),accounts +tax_report_tag39,ТТ02: Хүүгийн орлого (39),accounts +tax_report_tag41,"ТТ02: Гадаад улсад олсон ногдол ашиг, хүүгийн орлого (41)",accounts +tax_report_tag43,ТТ02: Гадаад улсад олсон орлого (43),accounts +tax_report_tag46,ТТ02: Ногдол ашгийн орлого (46),accounts +tax_report_tag48,ТТ02: Эрхийн шимтгэлийн орлого (48),accounts +tax_report_tag50,ТТ02: Эрх борлуулсны орлого (50),accounts +tax_report_tag52,ТТ02: Үл хөдлөх хөрөнгө борлуулсны орлого (52),accounts diff --git a/addons/l10n_mn/data/account.account.template.csv b/addons/l10n_mn/data/account.account.template.csv new file mode 100644 index 00000000000..f64558c3e6b --- /dev/null +++ b/addons/l10n_mn/data/account.account.template.csv @@ -0,0 +1,285 @@ +id,code,name,user_type_id/id,tag_ids/id,reconcile,chart_template_id:id +account_template_1001_0101,10010101,Бэлэн мөнгө,account.data_account_type_liquidity,,0,mn_chart_1 +account_template_1003_0101,10030101,Жижиг мөнгөн сан,account.data_account_type_liquidity,,0,mn_chart_1 +account_template_1101_0101,11010101,Банкинд байгаа мөнгө,account.data_account_type_liquidity,,0,mn_chart_1 +account_template_1103_0101,11030101,Хугацаагүй хадгаламж,account.data_account_type_liquidity,,0,mn_chart_1 +account_template_1104_0101,11040101,Банкны төлбөрийн темринал,account.data_account_type_liquidity,,0,mn_chart_1 +account_template_1109_0101,11090101,Замд яваа мөнгө,account.data_account_type_current_assets,,1,mn_chart_1 +account_template_1110_0101,11100101,Бусад мөнгө түүнтэй адилтгах хөрөнгө,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1201_0101,12010101,Худалдааны авлага ААН,account.data_account_type_receivable,account_tag_operating_product,1,mn_chart_1 +account_template_1201_0201,12010201,Худалдааны авлага Хувь хүн,account.data_account_type_receivable,account_tag_operating_product,1,mn_chart_1 +account_template_1201_0301,12010301,Худалдааны авлага Холбоотой тал,account.data_account_type_receivable,account_tag_operating_product,1,mn_chart_1 +account_template_1202_0101,12020101,Авлагын бичиг,account.data_account_type_current_assets,account_tag_operating_product,0,mn_chart_1 +account_template_1203_0101,12030101,Найдваргүй авлагын хасагдуулга,account.data_account_type_current_assets,account_tag_operating_product,0,mn_chart_1 +account_template_1204_0101,12040101,Урьдчилж төлсөн ААНОАТатвар,account.data_account_type_current_assets,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_1204_0201,12040201,Урьдчилж төлсөн ХХОАТатвар,account.data_account_type_current_assets,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_1204_0301,12040301,Урьдчилж төлсөн НӨАТатвар,account.data_account_type_current_assets,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_1204_0401,12040401,Урьдчилж төлсөн Гаалийн албан татвар,account.data_account_type_current_assets,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_1204_0501,12040501,Урьдчилж төлсөн Үл хөдлөх хөрөнгийн албан татвар,account.data_account_type_current_assets,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_1204_0601,12040601,Урьдчилж төлсөн Газрын төлбөр,account.data_account_type_current_assets,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_1204_0701,12040701,Урьдчилж төлсөн АТӨЯХАТатвар,account.data_account_type_current_assets,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_1204_0801,12040801,Урьдчилж төлсөн Агаарын бохирдлын татвар,account.data_account_type_current_assets,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_1204_0901,12040901,Урьдчилж төлсөн Онцгой албан татвар,account.data_account_type_current_assets,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_1204_1001,12041001,Урьдчилж төлсөн Байгалийн нөөц ашиглалтын төлбөр,account.data_account_type_current_assets,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_1204_9901,12049901,Урьдчилж төлсөн Бусад татвар,account.data_account_type_current_assets,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_1205_0101,12050101,"Урьдчилж төлсөн ЭМ, НДШ",account.data_account_type_current_assets,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_1205_0201,12050201,Урьдчилж төлсөн Сайн дурын даатгалын хураамж,account.data_account_type_current_assets,account_tag_operating_insurance2,0,mn_chart_1 +account_template_1206_0101,12060101,"Цалингийн урьдчилгаа, богино хугацаат зээл",account.data_account_type_receivable,account_tag_operating_employee,1,mn_chart_1 +account_template_1206_0201,12060201,"Төлбөр, дутагдал",account.data_account_type_receivable,account_tag_operating_employee,1,mn_chart_1 +account_template_1206_0301,12060301,Худалдааны бус авлага ААН,account.data_account_type_receivable,account.account_tag_operating,1,mn_chart_1 +account_template_1206_0401,12060401,Худалдааны бус авлага Хувь хүн,account.data_account_type_receivable,account.account_tag_operating,1,mn_chart_1 +account_template_1206_0501,12060501,Худалдааны бус авлага Холбоотой тал,account.data_account_type_receivable,account.account_tag_operating,1,mn_chart_1 +account_template_1206_0601,12060601,Богино хугацаат зээлийн авлага ААН,account.data_account_type_receivable,account.account_tag_operating,1,mn_chart_1 +account_template_1206_0701,12060701,Богино хугацаат зээлийн авлага Хувь хүн,account.data_account_type_receivable,account.account_tag_operating,1,mn_chart_1 +account_template_1206_0801,12060801,Богино хугацаат зээлийн авлага Холбоотой тал,account.data_account_type_receivable,account.account_tag_operating,1,mn_chart_1 +account_template_1206_0901,12060901,Ногдол ашгийн авлага,account.data_account_type_receivable,account_tag_investing_dividends,1,mn_chart_1 +account_template_1206_1001,12061001,Барьцаалсан авлага,account.data_account_type_receivable,account.account_tag_operating,1,mn_chart_1 +account_template_1206_1101,12061101,Хүүний авлага,account.data_account_type_receivable,account_tag_operating_interest,1,mn_chart_1 +account_template_1206_1201,12061201,Үндсэн хөрөнгө худалдааны авлага,account.data_account_type_receivable,account_tag_investing_fasset,1,mn_chart_1 +account_template_1206_1301,12061301,Биет бус хөрөнгө худалдааны авлага,account.data_account_type_receivable,account_tag_investing_iasset,1,mn_chart_1 +account_template_1206_1401,12061401,Хөрөнгө оруулалт худалдааны авлага,account.data_account_type_receivable,account_tag_investing_invest,1,mn_chart_1 +account_template_1206_9901,12069901,Бусад худалдааны бус авлага,account.data_account_type_receivable,account.account_tag_operating,1,mn_chart_1 +account_template_1301_0101,13010101,Түргэн борлогдох үнэт цаас,account.data_account_type_current_assets,account.account_tag_financing,0,mn_chart_1 +account_template_1301_0201,13010201,Хугацаат хадгаламж,account.data_account_type_current_assets,account.account_tag_financing,0,mn_chart_1 +account_template_1302_0101,13020101,Бусад дэлгэрэнгүй орлого болох бодит үнэ цэнээр илэрхийлэх санхүүгийн хөрөнгө,account.data_account_type_current_assets,account.account_tag_operating,0,mn_chart_1 +account_template_1303_0101,13030101,Хорогдуулсан өртөгөөр илэрхийлэгдэх санхүүгийн өртөг,account.data_account_type_current_assets,account.account_tag_operating,0,mn_chart_1 +account_template_1401_0101,14010101,Агуулахад байгаа бараа материал,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1401_0401,14010401,Татан авалтын өртөгийн зөрүү,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1401_0701,14010701,Амьтан,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1401_0801,14010801,Мал,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1401_0901,14010901,Ургамал,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1402_0101,14020101,Агуулахад байгаа түүхий эд материал,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1403_0301,14030301,Агуулахад байгаа үндсэн хөрөнгийн хэсэг,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1403_0401,14030401,Агуулахад байгаа хангамжийн материал,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1403_0501,14030501,Ашиглалтанд байгаа хангамжийн материал,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1403_0502,14030502,Ашиглалтанд байгаа хангамжийн материалын элэгдэл,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1404_0101,14040101,Дуусаагүй үйлдвэрлэл - Шууд материал,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1404_0201,14040201,Дуусаагүй үйлдвэрлэл - Шууд хөдөлмөр,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1404_0301,14040301,Дуусаагүй үйлдвэрлэл - НЗ,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1404_0401,14040401,Хагас боловсруулсан бүтээгдэхүүн,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1405_0101,14050101,Агентад байгаа бараа,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1406_0101,14060101,Замд яваа бараа,account.data_account_type_current_assets,,0,mn_chart_1 +account_template_1407_0101,14070101,Ирж буй барааны өртөгийн түр данс,account.data_account_type_current_assets,,1,mn_chart_1 +account_template_1408_0101,14080101,Гарч буй барааны өртөгийн түр данс,account.data_account_type_current_assets,,1,mn_chart_1 +account_template_1501_0101,15010101,Урьдчилж төлсөн түрээс,account.data_account_type_prepayments,account_tag_operating_cost,0,mn_chart_1 +account_template_1501_0201,15010201,Урьдчилж төлсөн хураамж,account.data_account_type_prepayments,account_tag_operating_loyalty,0,mn_chart_1 +account_template_1501_0301,15010301,Урьдчилж төлсөн цалин,account.data_account_type_prepayments,account_tag_operating_employee,0,mn_chart_1 +account_template_1501_0901,15010901,Урьдчилж төлсөн бусад зардал,account.data_account_type_prepayments,account.account_tag_operating,0,mn_chart_1 +account_template_1502_0101,15020101,Бэлтгэн нийлүүлэгчид төлсөн урьдчилгаа,account.data_account_type_prepayments,account_tag_operating_product,0,mn_chart_1 +account_template_1502_0201,15020201,"Дараа тайлангийн урьдчилгаа, томилолт",account.data_account_type_prepayments,account_tag_operating_employee,0,mn_chart_1 +account_template_1502_0301,15020301,Үндсэн хөрөнгө худалдан авахад төлсөн урьдчилгаа,account.data_account_type_prepayments,account_tag_investing_fasset,0,mn_chart_1 +account_template_1502_0401,15020401,Биет бус хөрөнгө худалдан авахад төлсөн урьдчилгаа,account.data_account_type_prepayments,account_tag_investing_iasset,0,mn_chart_1 +account_template_1502_0501,15020501,Хөрөнгө оруулалт худалдан авахад төлсөн урьдчилгаа,account.data_account_type_prepayments,account_tag_investing_invest,0,mn_chart_1 +account_template_1502_0601,15020601,Хангамжийн зүйлс худалдан авахад төлсөн урьдчилгаа,account.data_account_type_prepayments,account_tag_operating_product,0,mn_chart_1 +account_template_1502_0901,15020901,Бусад худалдааны бус урьдчилгаа,account.data_account_type_prepayments,account.account_tag_operating,0,mn_chart_1 +account_template_1601_0101,16010101,Бусад эргэлтийн хөрөнгө,account.data_account_type_current_assets,account.account_tag_operating,0,mn_chart_1 +account_template_1701_0101,17010101,Борлуулах зорилгоор эзэмшиж буй эргэлтийн бус хөрөнгө,account.data_account_type_current_assets,account.account_tag_operating,0,mn_chart_1 +account_template_2001_0101,20010101,Биет хөрөнгө - Газрын сайржуулалт,account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2001_0201,20010201,Биет хөрөнгө - Газрын сайжруулалтын элэгдэл,account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2002_0101,20020101,"Биет хөрөнгө - Барилга, байгууламж",account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2002_0201,20020201,"Биет хөрөнгө - Барилга, байгууламжын элэгдэл",account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2003_0101,20030101,Биет хөрөнгө - Машин тоног төхөөрөмж,account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2003_0201,20030201,Биет хөрөнгө - Машин тоног төхөөрөмжийн элэгдэл,account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2004_0101,20040101,Биет хөрөнгө - Тээврийн хэрэгсэл,account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2004_0201,20040201,Биет хөрөнгө - Тээврийн хэрэгслийн элэгдэл,account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2005_0101,20050101,Биет хөрөнгө - Тавилга эд хогшил,account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2005_0201,20050201,Биет хөрөнгө - Тавилга эд хогшлын элэгдэл,account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2006_0101,20060101,"Биет хөрөнгө - Компьютер, дагалдах хэрэгсэл",account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2006_0201,20060201,"Биет хөрөнгө - Компьютер, дагалдах хэрэгслийн элэгдэл",account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2008_0101,20080101,Биет хөрөнгө - Дуусаагүй барилга,account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2008_0201,20080201,Биет хөрөнгө - Дуусаагүй барилгын элэгдэл,account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2009_0101,20090101,Биет хөрөнгө - Бусад хөрөнгө,account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2009_0201,20090201,Биет хөрөнгө - Бусад хөрөнгийн элэгдэл,account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2101_0101,21010101,Биет бус хөрөнгө - Зохиогчийн эрх,account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2101_0201,21010201,Биет бус хөрөнгө - Зохиогчийн эрхийн хорогдол,account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2102_0101,21020101,Биет бус хөрөнгө - Програм хангамж,account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2102_0201,21020201,Биет бус хөрөнгө - Програм хангамжын хорогдол,account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2103_0101,21030101,Биет бус хөрөнгө - Патент,account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2103_0201,21030201,Биет бус хөрөнгө - Патентын хорогдол,account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2104_0101,21040101,Биет бус хөрөнгө - Барааны тэмдэг,account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2104_0201,21040201,Биет бус хөрөнгө - Барааны тэмдэгийн хорогдол,account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2105_0101,21050101,Биет бус хөрөнгө - Тусгай зөвшөөрөл,account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2105_0201,21050201,Биет бус хөрөнгө - Тусгай зөвшөөрлийн хорогдол,account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2109_0101,21090101,Биет бус хөрөнгө - Бусад хөрөнгө,account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2109_0201,21090201,Биет бус хөрөнгө - Бусад хөрөнгийн элэгдэл,account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2401_0101,24010101,Биологийн хөрөнгө - Мал амьтад,account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2401_0201,24010201,Биологийн хөрөнгө - Мал амьтадын хорогдол,account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2402_0101,24020101,Биологийн хөрөнгө - Ургамал,account.data_account_type_fixed_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2402_0201,24020201,Биологийн хөрөнгө - Ургамалын хорогдол,account.data_account_type_fixed_assets,,0,mn_chart_1 +account_template_2201_0101,22010101,Ашиг алдагдлаарх бодит үнэ цэнээр илэрхийлэх санхүүгийн хөрөнгө,account.data_account_type_non_current_assets,account_tag_investing_invest,0,mn_chart_1 +account_template_2204_0101,22040101,"Хараат компани, хамтарсан үйлдвэрт оруулсан хөрөнгө оруулалт",account.data_account_type_non_current_assets,account_tag_investing_invest,0,mn_chart_1 +account_template_2205_0101,22050101,Охин компанид оруулсан хөрөнгө оруулалт,account.data_account_type_non_current_assets,account_tag_investing_invest,0,mn_chart_1 +account_template_2301_0101,23010101,Хайгуул ба үнэлгээний хөрөнгө,account.data_account_type_non_current_assets,account_tag_investing_invest,0,mn_chart_1 +account_template_2501_0101,25010101,Хойшлогдсон татварын хөрөнгө,account.data_account_type_non_current_assets,account.account_tag_financing,0,mn_chart_1 +account_template_2601_0101,26010101,Хөрөнгө оруулалтын зориулалттай үндсэн хөрөнгө,account.data_account_type_non_current_assets,account_tag_investing_invest,0,mn_chart_1 +account_template_2601_0201,26010201,Үндсэн хөрөнгийн үнэ цэнийн бууралт,account.data_account_type_non_current_assets,account_tag_investing_fasset,0,mn_chart_1 +account_template_2701_0101,27010101,Урт хугацаат зээлийн авлага ААН,account.data_account_type_non_current_assets,account_tag_investing_loan,0,mn_chart_1 +account_template_2701_0201,27010201,Урт хугацаат зээлийн авлага Хувь хүн,account.data_account_type_non_current_assets,account_tag_investing_loan,0,mn_chart_1 +account_template_2701_0301,27010301,Урт хугацаат зээлийн авлага Холбоотой тал,account.data_account_type_non_current_assets,account_tag_investing_loan,0,mn_chart_1 +account_template_2709_0101,27090101,Бусад эргэлтийн бус хөрөнгө,account.data_account_type_non_current_assets,account.account_tag_financing,0,mn_chart_1 +account_template_3101_0101,31010101,Худалдааны БН-д өгөх өглөг ААН,account.data_account_type_payable,account_tag_operating_product,1,mn_chart_1 +account_template_3101_0201,31010201,Худалдааны БН-д өгөх өглөг Хувь хүн,account.data_account_type_payable,account_tag_operating_product,1,mn_chart_1 +account_template_3101_0301,31010301,Худалдааны БН-д өгөх өглөг Холбоотой тал,account.data_account_type_payable,account_tag_operating_product,1,mn_chart_1 +account_template_3201_0101,32010101,Урьдчилж орсон худалдааны орлого,account.data_account_type_current_liabilities,account_tag_operating_product,1,mn_chart_1 +account_template_3202_0101,32020101,Урьдчилж орсон түрээсийн орлого,account.data_account_type_current_liabilities,account_tag_operating_product,1,mn_chart_1 +account_template_3203_0101,32030101,Урьдчилж орсон зээлийн хүүгийн орлого,account.data_account_type_current_liabilities,account_tag_operating_interest,1,mn_chart_1 +account_template_3301_0101,33010101,Цалингийн өглөг,account.data_account_type_payable,account_tag_operating_employee,1,mn_chart_1 +account_template_3401_0101,34010101,Татварын өглөг - ААНОАТатвар,account.data_account_type_current_liabilities,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_3401_0201,34010201,Татварын өглөг - НӨАТатвар,account.data_account_type_current_liabilities,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_3401_0301,34010301,Татварын өглөг - ХХОАТатвар,account.data_account_type_current_liabilities,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_3401_0401,34010401,Татварын өглөг - Гаалийн албан татвар,account.data_account_type_current_liabilities,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_3401_0501,34010501,Татварын өглөг - Үл хөдлөх хөрөнгийн албан татвар,account.data_account_type_current_liabilities,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_3401_0601,34010601,Татварын өглөг - Газрын албан татвар,account.data_account_type_current_liabilities,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_3401_0701,34010701,Татварын өглөг - АТӨЯХАТатвар,account.data_account_type_current_liabilities,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_3401_0801,34010801,Татварын өглөг - Агаарын бохирдлын татвар,account.data_account_type_current_liabilities,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_3401_0901,34010901,Татварын өглөг - Онцгой албан татвар,account.data_account_type_current_liabilities,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_3401_1001,34011001,Татварын өглөг - Байгалийн нөөц ашиглалтын татвар,account.data_account_type_current_liabilities,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_3401_1101,34011101,Татварын өглөг – НХАТатвар,account.data_account_type_current_liabilities,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_3401_9901,34019901,Татварын өглөг - Бусад татвар,account.data_account_type_current_liabilities,account_tag_operating_taxrefund,0,mn_chart_1 +account_template_3402_0101,34020101,"ЭМ, НДШ-ийн өглөг",account.data_account_type_current_liabilities,account_tag_operating_insurance,0,mn_chart_1 +account_template_3402_0201,34020201,Сайн дурын даатгалын өглөг,account.data_account_type_current_liabilities,account_tag_operating_insurance2,0,mn_chart_1 +account_template_3501_0101,35010101,Банкны богино хугацаат зээлийн өглөг,account.data_account_type_payable,account_tag_operating_interest,1,mn_chart_1 +account_template_3501_0201,35010201,ББСБ-ын богино хугацаат зээлийн өглөг,account.data_account_type_payable,account_tag_operating_interest,1,mn_chart_1 +account_template_3501_0301,35010301,Хувь хүний богино хугацаат зээлийн өглөг,account.data_account_type_payable,account_tag_operating_interest,1,mn_chart_1 +account_template_3502_0101,35020101,Банкны богино хугацаат зээлийн хүү,account.data_account_type_payable,account_tag_operating_interest,1,mn_chart_1 +account_template_3502_0201,35020201,ББСБ-ын богино хугацаат зээлийн хүү,account.data_account_type_payable,account_tag_operating_interest,1,mn_chart_1 +account_template_3502_0301,35020301,Хувь хүний богино хугацаат зээлийн хүү,account.data_account_type_payable,account_tag_operating_interest,1,mn_chart_1 +account_template_3601_0101,36010101,Ногдол ашгийн өглөг,account.data_account_type_current_liabilities,account_tag_investing_dividends,0,mn_chart_1 +account_template_3701_0101,37010101,Нөөц өр төлбөр,account.data_account_type_current_liabilities,account_tag_exchange,0,mn_chart_1 +account_template_3801_0101,38010101,Даатгалын өглөг,account.data_account_type_payable,account_tag_operating_insurance2,1,mn_chart_1 +account_template_3802_0101,38020101,Гишүүнчлэлийн өглөг,account.data_account_type_payable,account_tag_operating_loyalty,1,mn_chart_1 +account_template_3803_0101,38030101,Ажилчдад өгөх өглөг,account.data_account_type_payable,account_tag_operating_employee,1,mn_chart_1 +account_template_3804_0101,38040101,Хувь хүмүүст өгөх өглөг,account.data_account_type_payable,account.account_tag_operating,1,mn_chart_1 +account_template_3805_0101,38050101,"Баталгаа, барьцааны өглөг",account.data_account_type_payable,account.account_tag_operating,1,mn_chart_1 +account_template_3806_0101,38060101,Худалдааны бус бэлтгэн нийлүүлэгчид өгөх өглөг - ААН,account.data_account_type_payable,account.account_tag_operating,1,mn_chart_1 +account_template_3806_0201,38060201,Худалдааны бус бэлтгэн нийлүүлэгчид өгөх өглөг - Хувь хүн,account.data_account_type_payable,account.account_tag_operating,1,mn_chart_1 +account_template_3806_0301,38060301,Худалдааны бус бэлтгэн нийлүүлэгчид өгөх өглөг - Холбоотой тал,account.data_account_type_payable,account.account_tag_operating,1,mn_chart_1 +account_template_3806_0401,38060401,Худалдан авсан үндсэн хөрөнгийн өглөг,account.data_account_type_payable,account_tag_investing_fasset,1,mn_chart_1 +account_template_3806_0501,38060501,Худалдан авсан хөрөнгө оруулалтын өглөг,account.data_account_type_payable,account_tag_investing_fasset,1,mn_chart_1 +account_template_3809_0101,38090101,Бусад богино хугацаат өр төлбөр,account.data_account_type_current_liabilities,account.account_tag_operating,0,mn_chart_1 +account_template_3901_0101,39010101,Борлуулах зорилгоор эзэмшиж буй эргэлтийн бус хөрөнгөнд хамаарах өр,account.data_account_type_current_liabilities,account_tag_exchange,0,mn_chart_1 +account_template_4001_0101,40010101,Банкны урт хугацаат зээл,account.data_account_type_non_current_liabilities,account_tag_investing_loan,0,mn_chart_1 +account_template_4001_0201,40010201,ББСБ-ын урт хугацаат зээл,account.data_account_type_non_current_liabilities,account_tag_investing_loan,0,mn_chart_1 +account_template_4001_0301,40010301,Хувь хүнээс авсан урт хугацаат зээл,account.data_account_type_non_current_liabilities,account_tag_investing_loan,0,mn_chart_1 +account_template_4001_0401,40010401,Холбоотой талын урт хугацаат зээл,account.data_account_type_non_current_liabilities,account_tag_investing_loan,0,mn_chart_1 +account_template_4002_0101,40020101,Урт хугацаат нөөц өр төлбөр,account.data_account_type_non_current_liabilities,account_tag_investing_loan,0,mn_chart_1 +account_template_4003_0101,40030101,Хойшлогдсон татварын өр,account.data_account_type_non_current_liabilities,account_tag_investing_loan,0,mn_chart_1 +account_template_4009_0101,40090101,Бусад урт хугацаат өр төлбөр,account.data_account_type_non_current_liabilities,account_tag_investing_loan,0,mn_chart_1 +account_template_4101_0101,41010101,Эздийн өмч - төрийн,account.data_account_type_equity,,0,mn_chart_1 +account_template_4102_0101,41020101,Эздийн өмч - хувийн,account.data_account_type_equity,,0,mn_chart_1 +account_template_4103_0101,41030101,Эздийн өмч - хувьцаат,account.data_account_type_equity,,0,mn_chart_1 +account_template_4201_0101,42010101,Халаасны хувьцаа,account.data_account_type_equity,,0,mn_chart_1 +account_template_4301_0101,43010101,Нэмж төлөгдсөн капитал,account.data_account_type_equity,,0,mn_chart_1 +account_template_4401_0101,44010101,Хөрөнгийн дахин үнэлгээний нэмэгдэл,account.data_account_type_equity,,0,mn_chart_1 +account_template_4501_0101,45010101,Гадаад валютын хөрвүүлэлтийн нөөц,account.data_account_type_equity,,0,mn_chart_1 +account_template_4509_0101,45090101,Эздийн өмчийн бусад хэсэг,account.data_account_type_equity,,0,mn_chart_1 +account_template_4601_0101,46010101,Тайлант үеийн хуримтлагдсан ашиг,account.data_account_type_equity,,0,mn_chart_1 +account_template_4601_0201,46010201,Өмнөх үеийн хуримтлагдсан ашиг,account.data_account_type_equity,,0,mn_chart_1 +account_template_5101_0101,51010101,Борлуулалтын орлого,account.data_account_type_revenue,"account_tag_operating_product,tax_report_tag7",0,mn_chart_1 +account_template_5101_0201,51010201,Борлуулалтын орлого (НӨАТ-с чөлөөлөгдөх),account.data_account_type_revenue,"account_tag_operating_product,tax_report_tag2",0,mn_chart_1 +account_template_5102_0101,51020101,Түрээсийн орлого,account.data_account_type_other_income,"account_tag_operating_product,tax_report_tag5",0,mn_chart_1 +account_template_5103_0101,51030101,Хүүний орлого,account.data_account_type_other_income,"account_tag_operating_interest,tax_report_tag39",0,mn_chart_1 +account_template_5104_0101,51040101,Ногдол ашгийн орлого,account.data_account_type_other_income,"account_tag_investing_dividends,tax_report_tag46",0,mn_chart_1 +account_template_5105_0101,51050101,Эрхийн шимтгэлийн орлого,account.data_account_type_other_income,"account_tag_operating_loyalty,tax_report_tag48",0,mn_chart_1 +account_template_5201_0101,52010101,Тооллогын зөрүүний олз,account.data_account_type_other_income,,0,mn_chart_1 +account_template_5201_0201,52010201,Тооллогын зөрүүний алдагдал,account.data_account_type_other_income,,0,mn_chart_1 +account_template_5201_0901,52010901,Бусад дэлгэрэнгүй орлого,account.data_account_type_other_income,"account.account_tag_operating,tax_report_tag8",0,mn_chart_1 +account_template_5301_0101,53010101,Валютын ханшийн зөрүүний хэрэгжсэн олз,account.data_account_type_other_income,,0,mn_chart_1 +account_template_5301_0201,53010201,Валютын ханшийн зөрүүний хэрэгжээгүй олз,account.data_account_type_other_income,,0,mn_chart_1 +account_template_5302_0101,53020101,Валютын ханшийн зөрүүний хэрэгжсэн гарз,account.data_account_type_other_income,,0,mn_chart_1 +account_template_5302_0201,53020201,Валютын ханшийн зөрүүний хэрэгжээгүй гарз,account.data_account_type_other_income,,0,mn_chart_1 +account_template_5401_0101,54010101,Үндсэн хөрөнгө борлуулсны олз,account.data_account_type_other_income,,0,mn_chart_1 +account_template_5401_0201,54010201,Үндсэн хөрөнгө борлуулсны гарз,account.data_account_type_other_income,,0,mn_chart_1 +account_template_5501_0101,55010101,Биет бус хөрөнгө борлуулсны олз,account.data_account_type_other_income,,0,mn_chart_1 +account_template_5501_0201,55010201,Биет бус хөрөнгө борлуулсны гарз,account.data_account_type_other_income,,0,mn_chart_1 +account_template_5601_0101,56010101,Хөрөнгө оруулалт борлуулсны олз,account.data_account_type_other_income,,0,mn_chart_1 +account_template_5601_0201,56010201,Хөрөнгө оруулалт борлуулсны гарз,account.data_account_type_other_income,,0,mn_chart_1 +account_template_5701_0101,57010101,Үндсэн бус үйл ажиллагааны бусад олз,account.data_account_type_other_income,,0,mn_chart_1 +account_template_5701_0201,57010201,Үндсэн бус үйл ажиллагааны бусад гарз,account.data_account_type_other_income,,0,mn_chart_1 +account_template_6001_0101,60010101,Борлуулалтын хөнгөлөлт,account.data_account_type_revenue,,0,mn_chart_1 +account_template_6002_0101,60020101,Борлуулалтын урамшуулал,account.data_account_type_revenue,,0,mn_chart_1 +account_template_6003_0101,60030101,Борлуулалтын буцаалт,account.data_account_type_revenue,,0,mn_chart_1 +account_template_6004_0101,60040101,Бэлнээр төлсөний хөнгөлөлт,account.data_account_type_revenue,,0,mn_chart_1 +account_template_6005_0101,60050101,Хугацаанаас өмнө төлсний хөнгөлөлт,account.data_account_type_revenue,,0,mn_chart_1 +account_template_6006_0101,60060101,Борлуулалтын үнийн бууралт,account.data_account_type_revenue,,0,mn_chart_1 +account_template_6101_0101,61010101,"Борлуулсан бараа, бүтээгдэхүүний өртөг",account.data_account_type_direct_costs,,0,mn_chart_1 +account_template_6102_0101,61020101,Борлуулсан үйлчилгээний өртөг,account.data_account_type_direct_costs,,0,mn_chart_1 +account_template_7001_0101,70010101,Удирд - Үндсэн цалингийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7001_0201,70010201,Удирд - Нэмэгдэл цалингийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_0101,70020101,Удирд - ЭМД-ийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_0201,70020201,Удирд - НДШ-ийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_0301,70020301,Удирд - Банкны шимтгэл хураамжын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_0401,70020401,Удирд - Гадаад томилолтын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_0402,70020402,Удирд - Дотоод томилолтын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_0501,70020501,Удирд - Бичиг хэргийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_0601,70020601,Удирд - Шуудан холбооны зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_0602,70020602,Удирд - Суурин утасны зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_0603,70020603,Удирд - Үүрэн утасны зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_0604,70020604,Удирд - Интернетийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_0701,70020701,Удирд - Мэргэжлийн үйлчилгээний зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_0801,70020801,Удирд - Хүний нөөцийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_0901,70020901,Удирд - Сонин сэтгүүл захиалгын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_1001,70021001,Удирд - Даатгалын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_1101,70021101,Удирд - Ашиглалтын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_1201,70021201,Удирд - Засварын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_1301,70021301,Удирд - Элэгдэл хорогдлын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_1401,70021401,Удирд - Түрээсийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_1501,70021501,Удирд - Харуул хамгаалалтын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_1601,70021601,Удирд - Цэвэрлэгээ үйлчилгээний зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_1701,70021701,Удирд - Тээврийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_1801,70021801,Удирд - Шатахууны зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_1901,70021901,Удирд - Хүлээн авалтын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_2001,70022001,Удирд - Зар сурталчилгааны зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_2101,70022101,Удирд - Төсөл хөгжлийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_2201,70022201,"Удирд - Судалгаа, туршилтын зардал",account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_2301,70022301,"Удирд - Хүргэлт, түгээлтийн зардал",account.data_account_type_expenses,,0,mn_chart_1 +account_template_7002_9901,70029901,Удирд - Үйл ажиллагааны бусад зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7101_0101,71010101,Борл - Үндсэн цалингийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7101_0201,71010201,Борл - Нэмэгдэл цалингийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_0101,71020101,Борл - ЭМД-ийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_0201,71020201,Борл - НДШ-ийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_0301,71020301,Борл - Банкны шимтгэл хураамжын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_0401,71020401,Борл - Гадаад томилолтын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_0402,71020402,Борл - Дотоод томилолтын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_0501,71020501,Борл - Бичиг хэргийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_0601,71020601,Борл - Шуудан холбооны зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_0602,71020602,Борл - Суурин утасны зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_0603,71020603,Борл - Үүрэн утасны зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_0604,71020604,Борл - Интернетийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_0701,71020701,Борл - Мэргэжлийн үйлчилгээний зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_0801,71020801,Борл - Хүний нөөцийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_0901,71020901,Борл - Сонин сэтгүүл захиалгын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_1001,71021001,Борл - Даатгалын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_1101,71021101,Борл - Ашиглалтын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_1201,71021201,Борл - Засварын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_1301,71021301,Борл - Элэгдэл хорогдлын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_1401,71021401,Борл - Түрээсийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_1501,71021501,Борл - Харуул хамгаалалтын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_1601,71021601,Борл - Цэвэрлэгээ үйлчилгээний зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_1701,71021701,Борл - Тээврийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_1801,71021801,Борл - Шатахууны зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_1901,71021901,Борл - Хүлээн авалтын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_2001,71022001,Борл - Зар сурталчилгааны зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_2101,71022101,Борл - Төсөл хөгжлийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_2201,71022201,"Борл - Судалгаа, туршилтын зардал",account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_2301,71022301,"Борл - Хүргэлт, түгээлтийн зардал",account.data_account_type_expenses,,0,mn_chart_1 +account_template_7102_9901,71029901,Борл - Үйл ажиллагааны бусад зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7201_0101,72010101,Эргэлтийн хөрөнгө санхүүжүүлэх зээлийн хүүгийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7202_0101,72020101,Үндсэн хөрөнгө санхүүжүүлэх зээлийн хүүгийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7203_0101,72030101,Төсөл санхүүжүүлэх зээлийн хүүгийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7301_0101,73010101,"Хайгуул, үнэлгээний зардал",account.data_account_type_expenses,,0,mn_chart_1 +account_template_7401_0101,74010101,"Алданги, торгуулийн зардал",account.data_account_type_expenses,,0,mn_chart_1 +account_template_7402_0101,74020101,"Хандив, тусламжийн зардал",account.data_account_type_expenses,,0,mn_chart_1 +account_template_7403_0101,74030101,Найдваргүй авлагын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7404_0101,74040101,Болзошгүй алдагдлын санд төвлөрүүлсэн хөрөнгийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7405_0101,74050101,Франчайзын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7406_0101,74060101,Банкны үйлчилгээний шимтгэлийн зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7407_0101,74070101,Хөрөнгө акталж устгасны зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7408_0101,74080101,Үйлдвэрийн ослын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7409_0101,74090101,"Туслах үйлдвэрлэл, үйлчилгээний зардал",account.data_account_type_expenses,,0,mn_chart_1 +account_template_7410_0101,74100101,Үндсэн хөрөнгийн үнэ цэнийн бууралтын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_7499_0101,74990101,Бусад ерөнхий зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_9101_0101,91010101,Тайлант үеийн орлогын албан татварын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_9102_0101,91020101,Хойшлогдсон татварын зардал,account.data_account_type_expenses,,0,mn_chart_1 +account_template_9103_0101,91030101,Татвар ногдохгүй бусад дэлгэрэнгүй орлого,account.data_account_type_expenses,,0,mn_chart_1 +account_template_9301_0101,93010101,Эхний үлдэгдлийн эх үүсвэр,account.data_unaffected_earnings,,0,mn_chart_1 diff --git a/addons/l10n_mn/data/account.chart.template.csv b/addons/l10n_mn/data/account.chart.template.csv new file mode 100644 index 00000000000..3c63ba77781 --- /dev/null +++ b/addons/l10n_mn/data/account.chart.template.csv @@ -0,0 +1,2 @@ +id,property_account_receivable_id/id,property_account_payable_id/id,property_account_expense_categ_id/id,property_account_income_categ_id/id,income_currency_exchange_account_id/id,expense_currency_exchange_account_id/id +mn_chart_1,account_template_1201_0201,account_template_3101_0201,account_template_7002_1101,account_template_5101_0201,account_template_5301_0201,account_template_5302_0201 diff --git a/addons/l10n_mn/data/account.tax.group.csv b/addons/l10n_mn/data/account.tax.group.csv new file mode 100644 index 00000000000..9e2a71ba648 --- /dev/null +++ b/addons/l10n_mn/data/account.tax.group.csv @@ -0,0 +1,7 @@ +id,name,sequence +account_tax_group1,НӨАТ ногдох бараа,10 +account_tax_group2,НӨАТ ногдох үйлчилгээ,10 +account_tax_group3,Экспортын борлуулалт,11 +account_tax_group4,"Худалдан авсан бараа, үйлчилгээ",12 +account_tax_group5,Санхүүгийн түрээсийн зүйл,13 +account_tax_group6,НӨАТ-с чөлөөлөгдөх,14 diff --git a/addons/l10n_mn/data/account.tax.template.csv b/addons/l10n_mn/data/account.tax.template.csv new file mode 100644 index 00000000000..e691ee773fb --- /dev/null +++ b/addons/l10n_mn/data/account.tax.template.csv @@ -0,0 +1,40 @@ +"id","name","amount","price_include","sequence","account_id/id","refund_account_id/id","amount_type","type_tax_use","description","tax_group_id/id","tag_ids/id","chart_template_id/id" +"account_tax_sale_vat1","НӨАТ бараа","10.0","True","1","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group1","vat_report_tag5","mn_chart_1" +"account_tax_purchase_vat1","НӨАТ-тэй худалдан авалт","10.0","True","1","account_template_1204_0301","account_template_1204_0301","Percentage of Price","Purchases","10%","account_tax_group4","vat_report_tag33,vat_report_tag36","mn_chart_1" +"account_tax_purchase_vat2","НӨАТ-гүй худалдан авалт","0.0","True","10","account_template_1204_0301","account_template_1204_0301","Percentage of Price","Purchases","0%","account_tax_group4","vat_report_tag33","mn_chart_1" +"account_tax_sale_vat2","НӨАТ 0% борлуулалт","0.0","True","10","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","0%","account_tax_group6","vat_report_tag2","mn_chart_1" +"account_tax_sale_vat3","НӨАТ чөлөөлөх борлуулалт","0.0","True","10","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","0%","account_tax_group6","vat_report_tag2","mn_chart_1" +"account_tax_sale_vat4","НӨАТ бусад барааны борлуулалт","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group1","vat_report_tag6","mn_chart_1" +"account_tax_sale_vat5","НӨАТ эрх борлуулалт","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group1","vat_report_tag7","mn_chart_1" +"account_tax_sale_vat6","НӨАТ татан буугдах үеийн борлуулалт","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group1","vat_report_tag8","mn_chart_1" +"account_tax_sale_vat7","НӨАТ өрийн төлбөрт өгсөн бараа","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group1","vat_report_tag9","mn_chart_1" +"account_tax_sale_vat8","НӨАТ нотариат үйлчилгээ","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group2","vat_report_tag11","mn_chart_1" +"account_tax_sale_vat9","НӨАТ өрийн төлбөрт өгсөн үйлчилгээ","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group2","vat_report_tag12","mn_chart_1" +"account_tax_sale_vat10","НӨАТ цахилгаан, дулаан, ус, шуудан, холбоо","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group2","vat_report_tag13","mn_chart_1" +"account_tax_sale_vat11","НӨАТ бараа түрээслүүлэх, эзэмшүүлэх","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group2","vat_report_tag14","mn_chart_1" +"account_tax_sale_vat12","НӨАТ байр түрээслүүлэх, эзэмшүүлэх","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group2","vat_report_tag15","mn_chart_1" +"account_tax_sale_vat13","НӨАТ хөрөнгө түрээслүүлэх, эзэмшүүлэх","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group2","vat_report_tag16","mn_chart_1" +"account_tax_sale_vat14","НӨАТ бүтээл, загвар, зохиогчийн эрх","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group2","vat_report_tag17","mn_chart_1" +"account_tax_sale_vat15","НӨАТ хонжворт сугалаа, таавар, бооцоо","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group2","vat_report_tag18","mn_chart_1" +"account_tax_sale_vat16","НӨАТ зуучлалын үйлчилгээ","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group2","vat_report_tag19","mn_chart_1" +"account_tax_sale_vat17","НӨАТ авсан хүү торгууль, алданги","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group2","vat_report_tag20","mn_chart_1" +"account_tax_sale_vat18","НӨАТ хөрөнгийн үнэлгээний үйлчилгээ","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group2","vat_report_tag21","mn_chart_1" +"account_tax_sale_vat19","НӨАТ төсвийн санхүүжилт, татаас","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group2","vat_report_tag22","mn_chart_1" +"account_tax_sale_vat20","НӨАТ хууль зүйн үйлчилгээ","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group2","vat_report_tag23","mn_chart_1" +"account_tax_sale_vat21","НӨАТ үсчин, гоо сайхан, угаалга, цэвэрлэгээ","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group2","vat_report_tag24","mn_chart_1" +"account_tax_sale_vat22","НӨАТ бусад үйлчилгээ","10.0","True","20","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group2","vat_report_tag25","mn_chart_1" +"account_tax_sale_vat23","НӨАТ 0% экспорт бараа","0.0","True","30","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","0%","account_tax_group3","vat_report_tag28","mn_chart_1" +"account_tax_sale_vat24","НӨАТ 0% экспорт үйлчилгээ","0.0","True","30","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","0%","account_tax_group3","vat_report_tag29","mn_chart_1" +"account_tax_purchase_vat3","НӨАТ импортоор авсан бараа, үйлчилгээ","10.0","True","40","account_template_1204_0301","account_template_1204_0301","Percentage of Price","Purchases","10%","account_tax_group4","vat_report_tag33,vat_report_tag35","mn_chart_1" +"account_tax_purchase_vat4","НӨАТ төлөгчөөр бүртгүүлэх үед худалдан авсан","10.0","True","40","account_template_1204_0301","account_template_1204_0301","Percentage of Price","Purchases","10%","account_tax_group4","vat_report_tag33,vat_report_tag37","mn_chart_1" +"account_tax_purchase_vat5","НӨАТ мал аж ахуй эрхлэгчээс худалдан авсан","10.0","True","40","account_template_1204_0301","account_template_1204_0301","Percentage of Price","Purchases","10%","account_tax_group4","vat_report_tag33,vat_report_tag38","mn_chart_1" +"account_tax_purchase_vat6","НӨАТ автомашин, эд анги худалдан авалт","10.0","True","40","account_template_1204_0301","account_template_1204_0301","Percentage of Price","Purchases","10%","account_tax_group4","vat_report_tag33,vat_report_tag41","mn_chart_1" +"account_tax_purchase_vat7","НӨАТ ажлын хэрэгцээнд авсан бараа","10.0","True","40","account_template_1204_0301","account_template_1204_0301","Percentage of Price","Purchases","10%","account_tax_group4","vat_report_tag33,vat_report_tag42","mn_chart_1" +"account_tax_purchase_vat8","НӨАТ импортоор авсан үндсэн хөрөнгө","10.0","True","40","account_template_1204_0301","account_template_1204_0301","Percentage of Price","Purchases","10%","account_tax_group4","vat_report_tag33,vat_report_tag43","mn_chart_1" +"account_tax_purchase_vat9","НӨАТ чөлөөлөгдөх үйлдвэрлэлд зориулсан бараа, үйлчилгээ","10.0","True","40","account_template_1204_0301","account_template_1204_0301","Percentage of Price","Purchases","10%","account_tax_group4","vat_report_tag33,vat_report_tag44","mn_chart_1" +"account_tax_purchase_vat10","НӨАТ хайгуулд зориулсан импортын бараа, үйлчилгээ","10.0","True","40","account_template_1204_0301","account_template_1204_0301","Percentage of Price","Purchases","10%","account_tax_group4","vat_report_tag33,vat_report_tag45","mn_chart_1" +"account_tax_purchase_vat11","НӨАТ импортын бусад хамааралгүй бараа, үйлчилгээ","10.0","True","40","account_template_1204_0301","account_template_1204_0301","Percentage of Price","Purchases","10%","account_tax_group4","vat_report_tag33,vat_report_tag46","mn_chart_1" +"account_tax_sale_vat25","НӨАТ дотоодод зарсан санхүүгийн түрээс","10.0","True","50","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group5","vat_report_tag48","mn_chart_1" +"account_tax_sale_vat26","НӨАТ Факторинг, форфайтинг хэлцлийн үйлчилгээ","10.0","True","50","account_template_3401_0201","account_template_3401_0201","Percentage of Price","Sales","10%","account_tax_group5","vat_report_tag49","mn_chart_1" +"account_tax_purchase_vat12","НӨАТ Санхүүгийн түрээсийн худалдан авалт","10.0","True","50","account_template_1204_0301","account_template_1204_0301","Percentage of Price","Purchases","10%","account_tax_group5","vat_report_tag51","mn_chart_1" +"account_tax_purchase_vat13","НӨАТ Факторинг, форфайтинг худалдан авалт","10.0","True","50","account_template_1204_0301","account_template_1204_0301","Percentage of Price","Purchases","10%","account_tax_group5","vat_report_tag52","mn_chart_1" diff --git a/addons/l10n_mn/data/account_chart_template_configuration_data.xml b/addons/l10n_mn/data/account_chart_template_configuration_data.xml new file mode 100644 index 00000000000..2de735fa360 --- /dev/null +++ b/addons/l10n_mn/data/account_chart_template_configuration_data.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/addons/l10n_mn/data/account_chart_template_data.xml b/addons/l10n_mn/data/account_chart_template_data.xml new file mode 100644 index 00000000000..bb64e86c95e --- /dev/null +++ b/addons/l10n_mn/data/account_chart_template_data.xml @@ -0,0 +1,15 @@ + + + + + + + Mongolia + 11 + 10 + 1109 + 8 + + + + diff --git a/addons/l10n_mn/data/account_fiscal_position_template_data.xml b/addons/l10n_mn/data/account_fiscal_position_template_data.xml new file mode 100644 index 00000000000..94780439b51 --- /dev/null +++ b/addons/l10n_mn/data/account_fiscal_position_template_data.xml @@ -0,0 +1,399 @@ + + + + + + + Дотоодын борлуулалт - Худалдан авалт + + + + + + + НӨАТ 0% (3000000) + + + + + НӨАТ-гүй (2000000) + + + + + Гадаад борлуулалт - Худалдан авалт + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/addons/l10n_mn/static/description/icon.png b/addons/l10n_mn/static/description/icon.png new file mode 100644 index 00000000000..dae4b68b81e Binary files /dev/null and b/addons/l10n_mn/static/description/icon.png differ diff --git a/addons/l10n_za/__init__.py b/addons/l10n_za/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/addons/l10n_za/__manifest__.py b/addons/l10n_za/__manifest__.py new file mode 100644 index 00000000000..9389b0fdd93 --- /dev/null +++ b/addons/l10n_za/__manifest__.py @@ -0,0 +1,26 @@ +# -*- encoding: utf-8 -*- + +# Copyright (C) 2017 Paradigm Digital (). + +{ + 'name': 'South Africa - Accounting', + 'version': '1.0', + 'category': 'Localization', + 'description': """ +This is the latest basic South African localisation necessary to run Odoo in ZA: +================================================================================ + - a generic chart of accounts + - SARS VAT Ready Structure""", + 'author': 'Paradigm Digital', + 'website': 'https://www.paradigmdigital.co.za', + 'depends': ['account', 'base_vat'], + 'data': [ + 'data/account.account.tag.csv', + 'data/account.tax.group.csv', + 'data/account_chart_template_data.xml', + 'data/account.account.template.csv', + 'data/account_tax_template_data.xml', + 'data/account_chart_template_post_data.xml', + 'data/account_chart_template_configure_data.xml', + ], +} diff --git a/addons/l10n_za/data/account.account.tag.csv b/addons/l10n_za/data/account.account.tag.csv new file mode 100644 index 00000000000..27d71d89298 --- /dev/null +++ b/addons/l10n_za/data/account.account.tag.csv @@ -0,0 +1,17 @@ +id,name,applicability +tag_ST1,ST1,taxes +tag_ST1A,ST1A,taxes +tag_ST2,ST2,taxes +tag_ST2A,ST2A,taxes +tag_ST3,ST3,taxes +tag_ST5,ST5,taxes +tag_ST7,ST7,taxes +tag_ST10,ST10,taxes +tag_ST12,ST12,taxes +tag_PT14,PT14,taxes +tag_PT14A,PT14A,taxes +tag_PT15,PT15,taxes +tag_PT15A,PT15A,taxes +tag_PT16,PT16,taxes +tag_PT17,PT17,taxes +tag_PT18,PT18,taxes diff --git a/addons/l10n_za/data/account.account.template.csv b/addons/l10n_za/data/account.account.template.csv new file mode 100644 index 00000000000..51d0f219092 --- /dev/null +++ b/addons/l10n_za/data/account.account.template.csv @@ -0,0 +1,111 @@ +id,code,name,user_type_id/id,reconcile,chart_template_id/id +100020,100020,Stock Valuation Account,account.data_account_type_current_assets,True,default_chart_template +100030,100030,Stock Work In Progress,account.data_account_type_current_assets,False,default_chart_template +100040,100040,Stock Finished Goods,account.data_account_type_current_assets,False,default_chart_template +100050,100050,Stock Delivered Control Account,account.data_account_type_current_assets,True,default_chart_template +100060,100060,Purchase Tax Control Account,account.data_account_type_current_assets,False,default_chart_template +100070,100070,Other Current Assets,account.data_account_type_current_assets,False,default_chart_template +110010,110010,Debtors Control Account,account.data_account_type_receivable,True,default_chart_template +110020,110020,Sundry Debtors,account.data_account_type_receivable,True,default_chart_template +124010,124010,Credit Card Merchant Account,account.data_account_type_liquidity,False,default_chart_template +126010,126010,Cash In Hand,account.data_account_type_liquidity,False,default_chart_template +130010,130010,Prepayments,account.data_account_type_prepayments,False,default_chart_template +140010,140010,Software,account.data_account_type_fixed_assets,False,default_chart_template +140020,140020,Patents & Trademarks,account.data_account_type_fixed_assets,False,default_chart_template +140030,140030,Fixtures & Fittings,account.data_account_type_fixed_assets,False,default_chart_template +140040,140040,Land & Buildings,account.data_account_type_fixed_assets,False,default_chart_template +140050,140050,Motor Vehicles,account.data_account_type_fixed_assets,False,default_chart_template +140060,140060,Office Equipment (incl computer equipment),account.data_account_type_fixed_assets,False,default_chart_template +140070,140070,Plant & Machinery,account.data_account_type_fixed_assets,False,default_chart_template +150010,150010,Non-current assets,account.data_account_type_non_current_assets,False,default_chart_template +200010,200010,Stock Received Control Account,account.data_account_type_current_liabilities,True,default_chart_template +200020,200020,Sundry Creditors,account.data_account_type_current_liabilities,False,default_chart_template +200030,200030,Other Creditors,account.data_account_type_current_liabilities,False,default_chart_template +200040,200040,Accruals,account.data_account_type_current_liabilities,False,default_chart_template +200050,200050,Bad debt provision,account.data_account_type_current_liabilities,False,default_chart_template +200060,200060,Sales Tax Control Account,account.data_account_type_current_liabilities,False,default_chart_template +200070,200070,Manual Adjustments & VAT,account.data_account_type_current_liabilities,False,default_chart_template +200080,200080,Loans,account.data_account_type_current_liabilities,False,default_chart_template +200090,200090,Hire Purchase,account.data_account_type_current_liabilities,False,default_chart_template +200100,200100,Mortgages,account.data_account_type_current_liabilities,False,default_chart_template +210010,210010,Company Credit Card,account.data_account_type_credit_card,False,default_chart_template +220010,220010,Creditors Control Account,account.data_account_type_payable,True,default_chart_template +220020,220020,SARS - VAT Account,account.data_account_type_payable,True,default_chart_template +220030,220030,P.A.Y.E. & UIF,account.data_account_type_payable,True,default_chart_template +220040,220040,Net Wages,account.data_account_type_payable,True,default_chart_template +220050,220050,Pension Fund,account.data_account_type_payable,True,default_chart_template +220060,220060,Corporation Tax,account.data_account_type_payable,True,default_chart_template +300010,300010,Called up share capital,account.data_account_type_equity,False,default_chart_template +300020,300020,Share premium account,account.data_account_type_equity,False,default_chart_template +300030,300030,Revaluation reserve,account.data_account_type_equity,False,default_chart_template +300040,300040,Other reserves,account.data_account_type_equity,False,default_chart_template +300050,300050,Capital,account.data_account_type_equity,False,default_chart_template +300060,300060,Dividends,account.data_account_type_equity,False,default_chart_template +300070,300070,Drawings,account.data_account_type_equity,False,default_chart_template +400010,400010,Undistributed Profits/Losses,account.data_unaffected_earnings,False,default_chart_template +500010,500010,Sales category 1,account.data_account_type_revenue,False,default_chart_template +500020,500020,Sales category 2,account.data_account_type_revenue,False,default_chart_template +500030,500030,Sales category 3,account.data_account_type_revenue,False,default_chart_template +500040,500040,Sales category 4,account.data_account_type_revenue,False,default_chart_template +500050,500050,Bank Interest received,account.data_account_type_revenue,False,default_chart_template +500060,500060,Investment Interest received,account.data_account_type_revenue,False,default_chart_template +500070,500070,Profits/Losses on disposals of assets,account.data_account_type_revenue,False,default_chart_template +500080,500080,Rental Income,account.data_account_type_revenue,False,default_chart_template +510010,510010,Other Income,account.data_account_type_other_income,False,default_chart_template +600010,600010,Cost of sales 1,account.data_account_type_direct_costs,False,default_chart_template +600020,600020,Cost of sales 2,account.data_account_type_direct_costs,False,default_chart_template +600030,600030,Cost of sales 3,account.data_account_type_direct_costs,False,default_chart_template +600040,600040,Cost of sales 4,account.data_account_type_direct_costs,False,default_chart_template +610010,610010,Marketing,account.data_account_type_expenses,False,default_chart_template +610020,610020,Exhibitions and events,account.data_account_type_expenses,False,default_chart_template +610030,610030,PR,account.data_account_type_expenses,False,default_chart_template +610040,610040,Distribution vehicles,account.data_account_type_expenses,False,default_chart_template +610050,610050,Distribution salaries and wages,account.data_account_type_expenses,False,default_chart_template +610060,610060,Shipping,account.data_account_type_expenses,False,default_chart_template +610070,610070,Directors pension,account.data_account_type_expenses,False,default_chart_template +610080,610080,Directors remuneration,account.data_account_type_expenses,False,default_chart_template +610090,610090,Gross Salaries,account.data_account_type_expenses,False,default_chart_template +610100,610100,Employers SDL & UIF,account.data_account_type_expenses,False,default_chart_template +610110,610110,Subcontractors payments,account.data_account_type_expenses,False,default_chart_template +610120,610120,Rent and rates,account.data_account_type_expenses,False,default_chart_template +610130,610130,Light / heat and power,account.data_account_type_expenses,False,default_chart_template +610140,610140,Repairs and maintenance,account.data_account_type_expenses,False,default_chart_template +610150,610150,Car hire,account.data_account_type_expenses,False,default_chart_template +610160,610160,Car fuel,account.data_account_type_expenses,False,default_chart_template +610170,610170,Car maintenance,account.data_account_type_expenses,False,default_chart_template +610180,610180,Telephone,account.data_account_type_expenses,False,default_chart_template +610190,610190,Internet & hosting,account.data_account_type_expenses,False,default_chart_template +610200,610200,Mobiles,account.data_account_type_expenses,False,default_chart_template +610210,610210,Stationery,account.data_account_type_expenses,False,default_chart_template +610220,610220,Office consumables,account.data_account_type_expenses,False,default_chart_template +610230,610230,Postage and Carriage,account.data_account_type_expenses,False,default_chart_template +610240,610240,Books,account.data_account_type_expenses,False,default_chart_template +610250,610250,Network costs,account.data_account_type_expenses,False,default_chart_template +610260,610260,Software expenses,account.data_account_type_expenses,False,default_chart_template +610270,610270,Other computer costs,account.data_account_type_expenses,False,default_chart_template +610280,610280,Recruitment fees,account.data_account_type_expenses,False,default_chart_template +610290,610290,Other admin expenses,account.data_account_type_expenses,False,default_chart_template +610300,610300,Accounting,account.data_account_type_expenses,False,default_chart_template +610310,610310,Auditing,account.data_account_type_expenses,False,default_chart_template +610320,610320,Consultancy,account.data_account_type_expenses,False,default_chart_template +610330,610330,Legal and professional charges,account.data_account_type_expenses,False,default_chart_template +610340,610340,Exchange gains/losses,account.data_account_type_expenses,False,default_chart_template +610350,610350,Other sundry expenses,account.data_account_type_expenses,False,default_chart_template +610360,610360,Bad debts,account.data_account_type_expenses,False,default_chart_template +610370,610370,Interest paid,account.data_account_type_expenses,False,default_chart_template +610380,610380,Bank Charges,account.data_account_type_expenses,False,default_chart_template +610390,610390,Donations,account.data_account_type_expenses,False,default_chart_template +610400,610400,Entertaining,account.data_account_type_expenses,False,default_chart_template +610410,610410,Insurance,account.data_account_type_expenses,False,default_chart_template +610420,610420,Travel and subsistence,account.data_account_type_expenses,False,default_chart_template +610430,610430,Corporation tax expense,account.data_account_type_expenses,False,default_chart_template +610440,610440,Foreign Exchange Gains/Losses,account.data_account_type_expenses,False,default_chart_template +610450,610450,Price Differences Control Account,account.data_account_type_expenses,False,default_chart_template +610460,610460,Cash Register Gains/Losses,account.data_account_type_expenses,False,default_chart_template +620010,620010,Software Depreciation,account.data_account_type_depreciation,False,default_chart_template +620020,620020,Patents & Trademarks Depreciation,account.data_account_type_depreciation,False,default_chart_template +620030,620030,Fixtures and fittings Depreciation,account.data_account_type_depreciation,False,default_chart_template +620040,620040,Land and buildings Depreciation,account.data_account_type_depreciation,False,default_chart_template +620050,620050,Motor vehicles Depreciation,account.data_account_type_depreciation,False,default_chart_template +620060,620060,Office equipment (inc computer equipment) Depreciation,account.data_account_type_depreciation,False,default_chart_template +620070,620070,Plant and machinery Depreciation,account.data_account_type_depreciation,False,default_chart_template diff --git a/addons/l10n_za/data/account.tax.group.csv b/addons/l10n_za/data/account.tax.group.csv new file mode 100644 index 00000000000..ec35d11456c --- /dev/null +++ b/addons/l10n_za/data/account.tax.group.csv @@ -0,0 +1,3 @@ +id,name +tax_group_0,VAT 0% +tax_group_1,VAT 15% diff --git a/addons/l10n_za/data/account_chart_template_configure_data.xml b/addons/l10n_za/data/account_chart_template_configure_data.xml new file mode 100644 index 00000000000..6a3db99a6d5 --- /dev/null +++ b/addons/l10n_za/data/account_chart_template_configure_data.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/addons/l10n_za/data/account_chart_template_data.xml b/addons/l10n_za/data/account_chart_template_data.xml new file mode 100644 index 00000000000..652646a5d18 --- /dev/null +++ b/addons/l10n_za/data/account_chart_template_data.xml @@ -0,0 +1,15 @@ + + + + + + + South African Tax and Account Chart Template (by Paradigm Digital) + 1200 + 1250 + 1010 + 6 + + + + diff --git a/addons/l10n_za/data/account_chart_template_post_data.xml b/addons/l10n_za/data/account_chart_template_post_data.xml new file mode 100644 index 00000000000..1d1fa398173 --- /dev/null +++ b/addons/l10n_za/data/account_chart_template_post_data.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/addons/l10n_za/data/account_tax_template_data.xml b/addons/l10n_za/data/account_tax_template_data.xml new file mode 100644 index 00000000000..1c588eaa16c --- /dev/null +++ b/addons/l10n_za/data/account_tax_template_data.xml @@ -0,0 +1,212 @@ + + + + + 15% + + sale + Standard Rate + percent + 15 + + + + + + + + 15% + + sale + Standard Rate (Capital Goods) + percent + 15 + + + + + + + + 0% + + sale + Zero Rate + percent + 0 + + + + + + + + 0% + + sale + Zero Rate Exports + percent + 0 + + + + + + + + 0% + + sale + Exempt and Non-Supplies + percent + 0 + + + + + + + + 15% + + sale + Accommodation (28+ days) + percent + 15 + + + + + + + + 15% + + sale + Accommodation (Under 28 days) + percent + 15 + + + + + + + + 15% + + sale + Export of Second-hand Goods/ Change in Use + percent + 15 + + + + + + + + 15% + + sale + VAT Adjustments and Manual VAT + percent + 15 + + + + + + + + 15% + + purchase + Standard Rate + percent + 15 + + + + + + + + 15% + + purchase + Standard Rate (Capital Goods) + percent + 15 + + + + + + + + 15% + + purchase + Capital Goods Imported + percent + 15 + + + + + + + + 15% + + purchase + Goods and Services Imported + percent + 15 + + + + + + + + 15% + + purchase + Change in Use + percent + 15 + + + + + + + + 15% + + purchase + Bad Debts + percent + 15 + + + + + + + + 15% + + purchase + Other Adjustments + percent + 15 + + + + + + + diff --git a/addons/l10n_za/static/description/icon.png b/addons/l10n_za/static/description/icon.png new file mode 100644 index 00000000000..1f82ab5459c Binary files /dev/null and b/addons/l10n_za/static/description/icon.png differ diff --git a/addons/mail/models/mail_activity.py b/addons/mail/models/mail_activity.py index 4acce13d381..bf0b0141604 100644 --- a/addons/mail/models/mail_activity.py +++ b/addons/mail/models/mail_activity.py @@ -298,7 +298,7 @@ class MailActivity(models.Model): target_record = self.env[activity.res_model].browse(activity.res_id) if hasattr(target_record, 'company_id') and ( target_record.company_id != target_user.company_id and ( - len(target_user.company_ids) > 1)): + len(target_user.sudo().company_ids) > 1)): return # in that case we skip the check, assuming it would fail because of the company model.browse(activity.res_id).check_access_rule('read') except exceptions.AccessError: diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py index e2ebb16c69e..39510206641 100644 --- a/addons/mail/models/mail_message.py +++ b/addons/mail/models/mail_message.py @@ -4,6 +4,7 @@ import logging import re +from binascii import Error as binascii_error from operator import itemgetter from email.utils import formataddr from openerp.http import request @@ -933,7 +934,7 @@ class Message(models.Model): def _invalidate_documents(self): """ Invalidate the cache of the documents followed by ``self``. """ for record in self: - if record.model and record.res_id and 'message_ids' in self.env[record.model]: + if record.model and record.res_id and issubclass(self.pool[record.model], self.pool['mail.thread']): self.env[record.model].invalidate_cache(fnames=[ 'message_ids', 'message_unread', @@ -968,16 +969,21 @@ class Message(models.Model): key = match.group(2) if not data_to_url.get(key): name = match.group(4) if match.group(4) else 'image%s' % len(data_to_url) - attachment = Attachments.create({ - 'name': name, - 'datas': match.group(2), - 'datas_fname': name, - 'res_model': values.get('model'), - 'res_id': values.get('res_id'), - }) - attachment.generate_access_token() - values['attachment_ids'].append((4, attachment.id)) - data_to_url[key] = ['/web/image/%s?access_token=%s' % (attachment.id, attachment.access_token), name] + try: + attachment = Attachments.create({ + 'name': name, + 'datas': match.group(2), + 'datas_fname': name, + 'res_model': values.get('model'), + 'res_id': values.get('res_id'), + }) + except binascii_error: + _logger.warning("Impossible to create an attachment out of badly formated base64 embedded image. Image has been removed.") + return match.group(3) # group(3) is the url ending single/double quote matched by the regexp + else: + attachment.generate_access_token() + values['attachment_ids'].append((4, attachment.id)) + data_to_url[key] = ['/web/image/%s?access_token=%s' % (attachment.id, attachment.access_token), name] return '%s%s alt="%s"' % (data_to_url[key][0], match.group(3), data_to_url[key][1]) values['body'] = _image_dataurl.sub(base64_to_boundary, tools.ustr(values['body'])) diff --git a/addons/mail/static/src/js/chatter.js b/addons/mail/static/src/js/chatter.js index dc23354fe7b..635d261bf3f 100644 --- a/addons/mail/static/src/js/chatter.js +++ b/addons/mail/static/src/js/chatter.js @@ -139,7 +139,7 @@ var Chatter = Widget.extend({ if (this.fields.activity) { this.fields.activity.$el.detach(); } - if (this.fields.thread) { + if (this.fields.thread && this.fields.thread.$el ) { this.fields.thread.$el.detach(); } @@ -398,7 +398,7 @@ var Chatter = Widget.extend({ self.fields.followers.$el.insertBefore(self.$('.o_chatter_button_attachment')); } } - if (self.fields.thread) { + if (self.fields.thread && self.fields.thread.$el) { self.fields.thread.$el.appendTo(self.$el); } }).always(function () { diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 75b867d3ad5..95ae6372c41 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -372,7 +372,6 @@ class MailComposer(models.TransientModel): - normal mode: return rendered values /!\ for x2many field, this onchange return command instead of ids """ - attachment_ids = [] if template_id and composition_mode == 'mass_mail': template = self.env['mail.template'].browse(template_id) fields = ['subject', 'body_html', 'email_from', 'reply_to', 'mail_server_id'] @@ -388,6 +387,7 @@ class MailComposer(models.TransientModel): values = self.generate_email_for_composer(template_id, [res_id])[res_id] # transform attachments into attachment_ids; not attached to the document because this will # be done further in the posting process, allowing to clean database if email not send + attachment_ids = [] Attachment = self.env['ir.attachment'] for attach_fname, attach_datas in values.pop('attachments', []): data_attach = { @@ -399,6 +399,8 @@ class MailComposer(models.TransientModel): 'type': 'binary', # override default_type from context, possibly meant for another model! } attachment_ids.append(Attachment.create(data_attach).id) + if values.get('attachment_ids', []) or attachment_ids: + values['attachment_ids'] = [(5,)] + values.get('attachment_ids', []) + attachment_ids else: default_values = self.with_context(default_composition_mode=composition_mode, default_model=model, default_res_id=res_id).default_get(['composition_mode', 'model', 'res_id', 'parent_id', 'partner_ids', 'subject', 'body', 'email_from', 'reply_to', 'attachment_ids', 'mail_server_id']) values = dict((key, default_values[key]) for key in ['subject', 'body', 'partner_ids', 'email_from', 'reply_to', 'attachment_ids', 'mail_server_id'] if key in default_values) @@ -411,8 +413,6 @@ class MailComposer(models.TransientModel): # this force the complete replacement of x2many field with # command and is compatible with onchange api.v7 values = self._convert_to_write(values) - if attachment_ids: - values.update(attachment_ids=[(6, 0, attachment_ids)]) return {'value': values} diff --git a/addons/mrp/models/stock_warehouse.py b/addons/mrp/models/stock_warehouse.py index bd4de62bdb4..788157476d0 100644 --- a/addons/mrp/models/stock_warehouse.py +++ b/addons/mrp/models/stock_warehouse.py @@ -249,7 +249,7 @@ class StockWarehouse(models.Model): @api.multi def _get_all_routes(self): - routes = super(StockWarehouse, self).get_all_routes_for_wh() + routes = super(StockWarehouse, self)._get_all_routes() routes |= self.filtered(lambda self: self.manufacture_to_resupply and self.manufacture_pull_id and self.manufacture_pull_id.route_id).mapped('manufacture_pull_id').mapped('route_id') return routes diff --git a/addons/payment/controllers/portal.py b/addons/payment/controllers/portal.py index 55a4d08e4b9..8b4585b9393 100644 --- a/addons/payment/controllers/portal.py +++ b/addons/payment/controllers/portal.py @@ -2,6 +2,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. import logging +import psycopg2 from odoo import http, _ from odoo.http import request @@ -40,7 +41,7 @@ class PaymentProcessing(http.Controller): # I prefer to let the controller chose when to access to payment.transaction using sudo return request.session.get("__payment_tx_ids__", []) - @http.route(['/payment/process'], type="http", auth="public", website=True) + @http.route(['/payment/process'], type="http", auth="public", website=True, sitemap=False) def payment_status_page(self, **kwargs): # When the customer is redirect to this website page, # we retrieve the payment transaction list from his session @@ -93,11 +94,15 @@ class PaymentProcessing(http.Controller): tx_to_process = payment_transaction_ids.filtered(lambda x: x.state == 'done' and x.is_processed is False) try: tx_to_process._post_process_after_done() + except psycopg2.OperationalError as e: + request.env.cr.rollback() + result['success'] = False + result['error'] = "tx_process_retry" except Exception as e: request.env.cr.rollback() result['success'] = False result['error'] = str(e) - _logger.error("Error while processing transaction(s) %s, exception \"%s\"", tx_to_process.ids, str(e)) + _logger.exception("Error while processing transaction(s) %s, exception \"%s\"", tx_to_process.ids, str(e)) return result @@ -122,7 +127,7 @@ class WebsitePayment(http.Controller): } return request.render("payment.pay_methods", values) - @http.route(['/website_payment/pay'], type='http', auth='public', website=True) + @http.route(['/website_payment/pay'], type='http', auth='public', website=True, sitemap=False) def pay(self, reference='', order_id=None, amount=False, currency_id=None, acquirer_id=None, **kw): env = request.env user = env.user.sudo() @@ -262,7 +267,7 @@ class WebsitePayment(http.Controller): except Exception as e: return request.redirect('/payment/process') - @http.route(['/website_payment/confirm'], type='http', auth='public', website=True) + @http.route(['/website_payment/confirm'], type='http', auth='public', website=True, sitemap=False) def confirm(self, **kw): tx_id = int(kw.get('tx_id', 0)) if tx_id: diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py index 0f2ce5d222a..6847cb76461 100644 --- a/addons/payment/models/payment_acquirer.py +++ b/addons/payment/models/payment_acquirer.py @@ -899,7 +899,7 @@ class PaymentTransaction(models.Model): # custom create custom_method_name = '%s_create' % acquirer.provider - if hasattr(acquirer, custom_method_name): + if hasattr(self, custom_method_name): values.update(getattr(self, custom_method_name)(values)) if not values.get('reference'): diff --git a/addons/payment/static/src/js/payment_processing.js b/addons/payment/static/src/js/payment_processing.js index 4397bf134f1..5409b915526 100644 --- a/addons/payment/static/src/js/payment_processing.js +++ b/addons/payment/static/src/js/payment_processing.js @@ -54,6 +54,8 @@ odoo.define('payment.processing', function (require) { } else { switch(data.error) { + case "tx_process_retry": + break; case "no_tx_found": self.displayContent("payment.no_tx_found", {}); break; @@ -63,11 +65,7 @@ odoo.define('payment.processing', function (require) { } } self.startPolling(); - }).always(function(){ - if ($.blockUI) { - $.unblockUI(); - } - }).fail(function(e) { + }).fail(function(e) { self.displayContent("payment.rpc_error", {}); self.startPolling(); }); @@ -117,6 +115,7 @@ odoo.define('payment.processing', function (require) { }, displayContent: function (xmlid, render_values) { var html = Qweb.render(xmlid, render_values); + $.unblockUI(); this.$el.find('.o_payment_processing_content').html(html); }, displayLoading: function () { diff --git a/addons/payment_authorize/models/authorize_request.py b/addons/payment_authorize/models/authorize_request.py index 79d0a7589c5..922d9df1bf1 100644 --- a/addons/payment_authorize/models/authorize_request.py +++ b/addons/payment_authorize/models/authorize_request.py @@ -226,6 +226,12 @@ class AuthorizeAPI(): etree.SubElement(customer, "email").text = partner.email or '' response = self._authorize_request(root) res = dict() + if not response.find('customerProfileId'): + _logger.warning( + 'Unable to create customer payment profile, data missing from transaction. Transaction_id: %s - Partner_id: %s' + % (transaction_id, partner) + ) + return res res['profile_id'] = response.find('customerProfileId').text res['payment_profile_id'] = response.find('customerPaymentProfileIdList/numericString').text root_profile = self._base_tree('getCustomerPaymentProfileRequest') diff --git a/addons/payment_authorize/models/payment.py b/addons/payment_authorize/models/payment.py index 5a6ed0bf8e1..946f031484d 100644 --- a/addons/payment_authorize/models/payment.py +++ b/addons/payment_authorize/models/payment.py @@ -228,17 +228,18 @@ class TxAuthorize(models.Model): (self.type == 'form_save' or self.acquirer_id.save_token == 'always'): transaction = AuthorizeAPI(self.acquirer_id) res = transaction.create_customer_profile_from_tx(self.partner_id, self.acquirer_reference) - token_id = self.env['payment.token'].create({ - 'authorize_profile': res.get('profile_id'), - 'name': res.get('name'), - 'acquirer_ref': res.get('payment_profile_id'), - 'acquirer_id': self.acquirer_id.id, - 'partner_id': self.partner_id.id, - }) - self.payment_token_id = token_id + if res: + token_id = self.env['payment.token'].create({ + 'authorize_profile': res.get('profile_id'), + 'name': res.get('name'), + 'acquirer_ref': res.get('payment_profile_id'), + 'acquirer_id': self.acquirer_id.id, + 'partner_id': self.partner_id.id, + }) + self.payment_token_id = token_id - if self.payment_token_id: - self.payment_token_id.verified = True + if self.payment_token_id: + self.payment_token_id.verified = True return True elif status_code == self._authorize_pending_tx_status: self.write({'acquirer_reference': data.get('x_trans_id')}) diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py index 43eb5e433b1..edae32282db 100644 --- a/addons/point_of_sale/models/pos_order.py +++ b/addons/point_of_sale/models/pos_order.py @@ -878,7 +878,7 @@ class PosOrder(models.Model): # a serialnumber always has a quantity of 1 product, a lot number takes the full quantity of the order line qty = 1.0 if stock_production_lot.product_id.tracking == 'lot': - qty = pos_pack_lot.pos_order_line_id.qty + qty = abs(pos_pack_lot.pos_order_line_id.qty) qty_done += qty pack_lots.append({'lot_id': stock_production_lot.id, 'qty': qty}) else: diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 41952ae6cff..1fe17d449a5 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -1457,7 +1457,7 @@ exports.Orderline = Backbone.Model.extend({ var lots_required = 1; if (this.product.tracking == 'serial') { - lots_required = this.quantity; + lots_required = Math.abs(this.quantity); } return lots_required; @@ -1913,8 +1913,11 @@ var PacklotlineCollection = Backbone.Collection.extend({ set_quantity_by_lot: function() { if (this.order_line.product.tracking == 'serial') { - var valid_lots = this.get_valid_lots(); - this.order_line.set_quantity(valid_lots.length); + var valid_lots_quantity = this.get_valid_lots().length; + if (this.order_line.quantity < 0){ + valid_lots_quantity = -valid_lots_quantity; + } + this.order_line.set_quantity(valid_lots_quantity); } } }); diff --git a/addons/pos_sale/report/sale_report.py b/addons/pos_sale/report/sale_report.py index 735aaf56169..a340d0b7c4d 100644 --- a/addons/pos_sale/report/sale_report.py +++ b/addons/pos_sale/report/sale_report.py @@ -14,11 +14,6 @@ class SaleReport(models.Model): ('invoiced', 'Invoiced')], string='Status', readonly=True) def _query(self, with_clause='', fields={}, groupby='', from_clause=''): - with_clause += '''pol_tax AS (SELECT line_tax.pos_order_line_id AS pol_id,sum(tax.amount/100) AS amount - FROM account_tax_pos_order_line_rel line_tax - JOIN account_tax tax ON line_tax.account_tax_id = tax.id - GROUP BY line_tax.pos_order_line_id)''' - res = super(SaleReport, self)._query(with_clause, fields, groupby, from_clause) select_ = ''' @@ -29,10 +24,10 @@ class SaleReport(models.Model): sum(l.qty * u.factor) AS qty_delivered, CASE WHEN pos.state = 'invoiced' THEN sum(qty) ELSE 0 END AS qty_invoiced, CASE WHEN pos.state != 'invoiced' THEN sum(qty) ELSE 0 END AS qty_to_invoice, - (COALESCE(COALESCE((l.price_unit * l.qty * u.factor * ((1 - COALESCE(l.discount / 100, 0)) )) + (l.price_unit * l.qty * u.factor * ((1 - COALESCE(l.discount / 100, 0)) ) * pol_tax.amount), (l.price_unit * l.qty * u.factor * ((1 - COALESCE(l.discount / 100, 0)) ))), 1.0)) / MIN(CASE COALESCE(pos.currency_rate, 0) WHEN 0 THEN 1.0 ELSE pos.currency_rate END) AS price_total, - (COALESCE((l.qty * u.factor * l.price_unit * ((1 - COALESCE(l.discount / 100, 0)) )), 1.0)) / MIN(CASE COALESCE(pos.currency_rate, 0) WHEN 0 THEN 1.0 ELSE pos.currency_rate END) AS price_subtotal, - (CASE WHEN pos.state != 'invoiced' THEN ((l.price_unit * l.qty * u.factor * ((1 - COALESCE(l.discount / 100, 0)))) + (l.price_unit * l.qty * u.factor * (1 - COALESCE(l.discount / 100, 0)) * pol_tax.amount)) ELSE 0 END) / MIN(CASE COALESCE(pos.currency_rate, 0) WHEN 0 THEN 1.0 ELSE pos.currency_rate END) AS amount_to_invoice, - (CASE WHEN pos.state = 'invoiced' THEN ((l.price_unit * l.qty * u.factor * ((1 - COALESCE(l.discount / 100, 0)) )) + (l.price_unit * l.qty * u.factor * (1 - COALESCE(l.discount / 100, 0)) * pol_tax.amount)) ELSE 0 END) / MIN(CASE COALESCE(pos.currency_rate, 0) WHEN 0 THEN 1.0 ELSE pos.currency_rate END) AS amount_invoiced, + SUM(l.price_subtotal_incl) / MIN(CASE COALESCE(pos.currency_rate, 0) WHEN 0 THEN 1.0 ELSE pos.currency_rate END) AS price_total, + SUM(l.price_subtotal) / MIN(CASE COALESCE(pos.currency_rate, 0) WHEN 0 THEN 1.0 ELSE pos.currency_rate END) AS price_subtotal, + (CASE WHEN pos.state != 'invoiced' THEN SUM(l.price_subtotal_incl) ELSE 0 END) / MIN(CASE COALESCE(pos.currency_rate, 0) WHEN 0 THEN 1.0 ELSE pos.currency_rate END) AS amount_to_invoice, + (CASE WHEN pos.state = 'invoiced' THEN SUM(l.price_subtotal_incl) ELSE 0 END) / MIN(CASE COALESCE(pos.currency_rate, 0) WHEN 0 THEN 1.0 ELSE pos.currency_rate END) AS amount_invoiced, count(*) AS nbr, pos.name AS name, pos.date_order AS date, @@ -70,7 +65,6 @@ class SaleReport(models.Model): pos_order_line l join pos_order pos on (l.order_id=pos.id) left join res_partner partner ON (pos.partner_id = partner.id OR pos.partner_id = NULL) - left join pol_tax pol_tax on pol_tax.pol_id=l.id left join product_product p on (l.product_id=p.id) left join product_template t on (p.product_tmpl_id=t.id) LEFT JOIN uom_uom u ON (u.id=t.uom_id) @@ -98,7 +92,6 @@ class SaleReport(models.Model): partner.country_id, partner.industry_id, partner.commercial_partner_id, - pol_tax.amount, u.factor, config.crm_team_id ''' diff --git a/addons/product/models/product.py b/addons/product/models/product.py index 4ac541f526b..7b4c3bb2c9b 100644 --- a/addons/product/models/product.py +++ b/addons/product/models/product.py @@ -335,6 +335,7 @@ class ProductProduct(models.Model): else: self.partner_ref = self.display_name + self.image_variant = False @api.depends('product_tmpl_id', 'attribute_value_ids') def _compute_product_template_attribute_value_ids(self): # Fetch and pre-map the values first for performance. It assumes there @@ -391,6 +392,16 @@ class ProductProduct(models.Model): product._set_standard_price(vals.get('standard_price') or 0.0) # `_get_variant_id_for_combination` depends on existing variants self.clear_caches() + self.env['product.template'].invalidate_cache( + fnames=[ + 'valid_archived_variant_ids', + 'valid_existing_variant_ids', + 'product_variant_ids', + 'product_variant_id', + 'product_variant_count' + ], + ids=products.mapped('product_tmpl_id').ids + ) return products @api.multi diff --git a/addons/product/models/product_template.py b/addons/product/models/product_template.py index c6c8eb92325..4d20b5afbeb 100644 --- a/addons/product/models/product_template.py +++ b/addons/product/models/product_template.py @@ -135,8 +135,10 @@ class ProductTemplate(models.Model): compute="_compute_valid_attributes", string='Valid Product Attribute Values Without No Variant Attributes', help="Technical compute") valid_product_attribute_wnva_ids = fields.Many2many('product.attribute', compute="_compute_valid_attributes", string='Valid Product Attributes Without No Variant Attributes', help="Technical compute") + # valid_archived_variant_ids deprecated valid_archived_variant_ids = fields.Many2many('product.product', - compute="_compute_valid_attributes", string='Valid Archived Variants', help="Technical compute") + compute="_compute_valid_archived_variant_ids", string='Valid Archived Variants', help="Technical compute") + # valid_existing_variant_ids deprecated valid_existing_variant_ids = fields.Many2many('product.product', compute="_compute_valid_existing_variant_ids", string='Valid Existing Variants', help="Technical compute") @@ -601,8 +603,6 @@ class ProductTemplate(models.Model): For what is considered an archived variant, see `_has_valid_attributes`. """ - archived_variants = self.env['product.product'].search([('product_tmpl_id', 'in', self.ids), ('active', '=', False)]) - # prefetch self.mapped('attribute_line_ids.value_ids.id') self.mapped('attribute_line_ids.attribute_id.create_variant') @@ -617,6 +617,12 @@ class ProductTemplate(models.Model): record.valid_product_attribute_ids = record.valid_product_template_attribute_line_ids.mapped('attribute_id') record.valid_product_attribute_wnva_ids = record.valid_product_template_attribute_line_wnva_ids.mapped('attribute_id') + @api.multi + def _compute_valid_archived_variant_ids(self): + """This compute is done outside of `_compute_valid_attributes` because + it is often not needed, and it can be very bad on performance.""" + archived_variants = self.env['product.product'].search([('product_tmpl_id', 'in', self.ids), ('active', '=', False)]) + for record in self: valid_value_ids = record.valid_product_attribute_value_wnva_ids valid_attribute_ids = record.valid_product_attribute_wnva_ids @@ -708,23 +714,23 @@ class ProductTemplate(models.Model): :return: dict of exclusions - exclusions: from this product itself + - parent_combination: ids of the given parent_combination - parent_exclusions: from the parent_combination - - archived_combinations: variants that are archived - - existing_combinations: variants that are existing (as opposed to - deleted, because deleted need to be considered impossible if - there are no dynamic attributes). - - has_dynamic_attributes: whether there is a dynamic attribute - - no_variant_product_template_attribute_value_ids: values that are - no_variant + - archived_combinations: deprecated + - existing_combinations: deprecated + - has_dynamic_attributes: deprecated + - no_variant_product_template_attribute_value_ids: deprecated """ self.ensure_one() + parent_combination = parent_combination or self.env['product.template.attribute.value'] return { 'exclusions': self._get_own_attribute_exclusions(), 'parent_exclusions': self._get_parent_attribute_exclusions(parent_combination), - 'archived_combinations': self._get_archived_combinations(), + 'parent_combination': parent_combination.ids, + 'archived_combinations': [], 'has_dynamic_attributes': self.has_dynamic_attributes(), - 'existing_combinations': self._get_existing_combinations(), - 'no_variant_product_template_attribute_value_ids': self._get_no_variant_product_template_attribute_values(), + 'existing_combinations': [], + 'no_variant_product_template_attribute_value_ids': [], } @api.multi @@ -777,29 +783,21 @@ class ProductTemplate(models.Model): @api.multi def _get_archived_combinations(self): + """Deprecated""" self.ensure_one() - """Get archived combinations. - - Array, each element is an array with ids of an archived combination. - """ return [archived_variant.product_template_attribute_value_ids.ids for archived_variant in self.valid_archived_variant_ids] @api.multi def _get_existing_combinations(self): + """Deprecated""" self.ensure_one() - """Get existing combinations. - - Needed because when not using dynamic attributes, the combination is - not ok if it doesn't exist (= if the variant has been deleted). - - Array, each element is an array with ids of an existing combination. - """ return [variant.product_template_attribute_value_ids.ids for variant in self.valid_existing_variant_ids] @api.multi def _get_no_variant_product_template_attribute_values(self): + """Deprecated""" self.ensure_one() product_template_attribute_values = self._get_valid_product_template_attribute_lines().mapped('product_template_value_ids') return product_template_attribute_values.filtered( @@ -845,9 +843,16 @@ class ProductTemplate(models.Model): # combination has different values than the ones configured on the template return False - if not self.has_dynamic_attributes() and not self._get_variant_for_combination(combination): - # the variant has been deleted - return False + variant = self._get_variant_for_combination(combination) + + if self.has_dynamic_attributes(): + if variant and not variant.active: + # dynamic and the variant has been archived + return False + else: + if not variant or not variant.active: + # not dynamic, the variant has been archived or deleted + return False exclusions = self._get_own_attribute_exclusions() if exclusions: @@ -864,11 +869,6 @@ class ProductTemplate(models.Model): if exclusion in combination.ids: return False - filtered_combination = combination._without_no_variant_attributes() - archived_combinations = self._get_archived_combinations() - if archived_combinations and filtered_combination.ids in archived_combinations: - return False - return True @api.multi @@ -902,7 +902,7 @@ class ProductTemplate(models.Model): for pav in attribute_values: domain = expression.AND([[('attribute_value_ids', 'in', pav.id)], domain]) - res = self.env['product.product'].with_context(active_test=False).search(domain) + res = self.env['product.product'].with_context(active_test=False).search(domain, order='active DESC') # The domain above is checking for the `product.attribute.value`, but we # need to make sure it's the same `product.template.attribute.value`. diff --git a/addons/product/tests/test_product_attribute_value_config.py b/addons/product/tests/test_product_attribute_value_config.py index e966adbdbdc..497f6fbeba3 100644 --- a/addons/product/tests/test_product_attribute_value_config.py +++ b/addons/product/tests/test_product_attribute_value_config.py @@ -312,6 +312,21 @@ class TestProductAttributeValueConfig(TestProductAttributeValueSetup): variant.unlink() self.assertFalse(self.computer._is_combination_possible(computer_ssd_256 + computer_ram_8 + computer_hdd_1)) + # CASE: if multiple variants exist for the same combination and at least + # one of them is not archived, the combination is possible + values = self.ssd_256 + self.ram_8 + self.hdd_1 + self.env['product.product'].create({ + 'product_tmpl_id': self.computer.id, + 'attribute_value_ids': [(6, 0, values.ids)], + 'active': False, + }) + self.env['product.product'].create({ + 'product_tmpl_id': self.computer.id, + 'attribute_value_ids': [(6, 0, values.ids)], + 'active': True, + }) + self.assertTrue(self.computer._is_combination_possible(computer_ssd_256 + computer_ram_8 + computer_hdd_1)) + def test_get_first_possible_combination(self): computer_ssd_256 = self._get_product_template_attribute_value(self.ssd_256) computer_ssd_512 = self._get_product_template_attribute_value(self.ssd_512) diff --git a/addons/product/tests/test_variants.py b/addons/product/tests/test_variants.py index 9381868b623..cc929171aef 100644 --- a/addons/product/tests/test_variants.py +++ b/addons/product/tests/test_variants.py @@ -1,6 +1,10 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +import base64 +import io +from PIL import Image + from . import common from odoo.exceptions import UserError from odoo.tests.common import TransactionCase @@ -461,3 +465,72 @@ class TestVariantsManyAttributes(common.TestAttributesCommon): self.assertEqual(len(toto.attribute_line_ids.mapped('attribute_id')), 10) self.assertEqual(len(toto.attribute_line_ids.mapped('value_ids')), 100) self.assertEqual(len(toto.product_variant_ids), 0) + +class TestVariantsImages(common.TestProductCommon): + + def setUp(self): + res = super(TestVariantsImages, self).setUp() + + self.colors = {'red': '#FF0000', 'green': '#00FF00', 'blue': '#0000FF'} + self.images = {} + + product_attribute = self.env['product.attribute'].create({'name': 'Color'}) + + self.template = self.env['product.template'].create({ + 'name': 'template', + }) + + for color in self.colors: + attr = self.env['product.attribute.value'].create({ + 'name': color, + 'attribute_id': product_attribute.id, + }) + + f = io.BytesIO() + Image.new('RGB', (800, 500), self.colors[color]).save(f, 'PNG') + f.seek(0) + self.images.update({color: base64.b64encode(f.read())}) + + self.env['product.product'].create({ + 'image_variant': self.images[color], + 'attribute_value_ids': [(6, 0, [attr.id])], + 'product_tmpl_id': self.template.id, + }) + # the first one has no image, no color + self.variants = self.template.product_variant_ids.sorted('id') + + return res + + def test_variant_images(self): + """Check that on variant, the image used is the image_variant if set, + and defaults to the template image otherwise. + """ + f = io.BytesIO() + Image.new('RGB', (800, 500), '#000000').save(f, 'PNG') + f.seek(0) + image_black = base64.b64encode(f.read()) + + images = self.variants.mapped('image_variant') + self.assertEqual(len(set(images)), 4) + + variant_no_image = self.variants[0] + self.assertFalse(variant_no_image.image) + self.template.image = image_black + + # the first has no image variant, all the others do + self.assertFalse(variant_no_image.image_variant) + self.assertTrue(all(images[1:])) + + # template image is the same as this one, since it has no image variant + self.assertEqual(variant_no_image.image, self.template.image) + # having changed the template image should not have changed these + self.assertEqual(images[1:], self.variants.mapped('image')[1:]) + + + def test_update_images_with_archived_variants(self): + """Update images after variants have been archived""" + self.variants[1:].write({'active': False}) + self.variants[0].image = self.images['red'] + self.assertEqual(self.template.image, self.images['red']) + self.assertEqual(self.variants[0].image_variant, False) + self.assertEqual(self.variants[0].image, self.images['red']) diff --git a/addons/product_email_template/models/product.py b/addons/product_email_template/models/product.py index 9ef844e8f46..e043717e6e8 100644 --- a/addons/product_email_template/models/product.py +++ b/addons/product_email_template/models/product.py @@ -11,4 +11,6 @@ class ProductTemplate(models.Model): _inherit = "product.template" email_template_id = fields.Many2one('mail.template', string='Product Email Template', - help='Send a product-specific email once the invoice is paid.') + help='When validating an invoice, an email will be sent to the customer ' + 'based on this template. The customer will receive an email for each ' + 'product linked to an email template.') diff --git a/addons/product_email_template/views/product_views.xml b/addons/product_email_template/views/product_views.xml index 393ab6d3ec9..9afb300f64f 100644 --- a/addons/product_email_template/views/product_views.xml +++ b/addons/product_email_template/views/product_views.xml @@ -10,7 +10,7 @@ 0 - 0: + if (discount > 0 and new_list_price > 0) or (discount < 0 and new_list_price < 0): self.discount = discount def _is_delivery(self): diff --git a/addons/sale/static/src/js/product_configurator_mixin.js b/addons/sale/static/src/js/product_configurator_mixin.js index 0d49a4f245e..bb72b4b428a 100644 --- a/addons/sale/static/src/js/product_configurator_mixin.js +++ b/addons/sale/static/src/js/product_configurator_mixin.js @@ -1,6 +1,7 @@ odoo.define('sale.ProductConfiguratorMixin', function (require) { 'use strict'; +var concurrency = require('web.concurrency'); var core = require('web.core'); var utils = require('web.utils'); var ajax = require('web.ajax'); @@ -8,11 +9,11 @@ var _t = core._t; var ProductConfiguratorMixin = { events: { - 'click .css_attribute_color input': '_onChangeColorAttribute', + 'change .css_attribute_color input': '_onChangeColorAttribute', 'change .main_product:not(.in_cart) input.js_quantity': 'onChangeAddQuantity', - 'click button.js_add_cart_json': 'onClickAddCartJSON', 'change [data-attribute_exclusions]': 'onChangeVariant' }, + // isSelectedVariantAllowed deprecated isSelectedVariantAllowed: true, //-------------------------------------------------------------------------- @@ -20,23 +21,11 @@ var ProductConfiguratorMixin = { //-------------------------------------------------------------------------- /** - * When a product is added or when the quantity is changed, - * we need to refresh the total price row - * TODO awa: add a container context to avoid global selectors ? + * This method is only useful in the configurator modal. + * + * @deprecated */ - computePriceTotal: function () { - if ($('.js_price_total').length){ - var price = 0; - $('.js_product.in_cart').each(function (){ - var quantity = parseInt($('input[name="add_qty"]').first().val()); - price += parseFloat($(this).find('.js_raw_price').html()) * quantity; - }); - - $('.js_price_total .oe_currency_value').html( - this._priceToStr(parseFloat(price)) - ); - } - }, + computePriceTotal: function () {}, /** * When a variant is changed, this will check: @@ -49,6 +38,20 @@ var ProductConfiguratorMixin = { * @param {MouseEvent} ev */ onChangeVariant: function (ev) { + var $parent = $(ev.target).closest('.js_product'); + if (!$parent.data('uniqueId')) { + $parent.data('uniqueId', _.uniqueId()); + } + this._throttledGetCombinationInfo($parent.data('uniqueId'))(ev); + }, + /** + * @see onChangeVariant + * + * @private + * @param {Event} ev + * @returns {Deferred} + */ + _getCombinationInfo: function (ev) { var self = this; var $component; @@ -64,16 +67,21 @@ var ProductConfiguratorMixin = { var qty = $component.find('input[name="add_qty"]').val(); var $parent = $(ev.target).closest('.js_product'); + var combination = this.getSelectedVariantValues($parent); + var parentCombination = $parent.find('ul[data-attribute_exclusions]').data('attribute_exclusions').parent_combination; + + var productTemplateId = parseInt($parent.find('.product_template_id').val()); self._checkExclusions($parent, combination); - ajax.jsonRpc(this._getUri('/product_configurator/get_combination_info'), 'call', { - product_template_id: parseInt($parent.find('.product_template_id').val()), - product_id: this._getProductId($parent), - combination: combination, - add_qty: parseInt(qty), - pricelist_id: this.pricelistId || false, + return ajax.jsonRpc(this._getUri('/product_configurator/get_combination_info'), 'call', { + 'product_template_id': productTemplateId, + 'product_id': this._getProductId($parent), + 'combination': combination, + 'add_qty': parseInt(qty), + 'pricelist_id': this.pricelistId || false, + 'parent_combination': parentCombination, }).then(function (combinationData) { self._onChangeCombination(ev, $parent, combinationData); }); @@ -149,10 +157,13 @@ var ProductConfiguratorMixin = { var $input = $link.closest('.input-group').find("input"); var min = parseFloat($input.data("min") || 0); var max = parseFloat($input.data("max") || Infinity); - var quantity = ($link.has(".fa-minus").length ? -1 : 1) + parseFloat($input.val() || 0, 10); + var previousQty = parseFloat($input.val() || 0, 10); + var quantity = ($link.has(".fa-minus").length ? -1 : 1) + previousQty; var newQty = quantity > min ? (quantity < max ? quantity : max) : min; - $input.val(newQty).trigger('change'); + if (newQty !== previousQty) { + $input.val(newQty).trigger('change'); + } return false; }, @@ -343,23 +354,6 @@ var ProductConfiguratorMixin = { * @param {Array} combination the selected combination of product attribute values */ _checkExclusions: function ($parent, combination) { - - function areCombinationsEqual(c1, c2) { - return c1.length === c2.length && _.every(c1, function (ptav) { - return c2.indexOf(ptav) > -1; - }); - } - - function isCombinationInList(c1, list) { - return _.some(list, function (c2) { - return areCombinationsEqual(c1, c2); - }); - } - - function isPtavInCombination(ptav, combination) { - return combination.indexOf(ptav) > -1; - } - var self = this; var combinationData = $parent .find('ul[data-attribute_exclusions]') @@ -367,17 +361,6 @@ var ProductConfiguratorMixin = { $parent.find('option, input, label').removeClass('css_not_available'); - var disable = false; - - // compatibility 12.0 - var filteredCombination = combination; - if (combinationData.no_variant_product_template_attribute_value_ids !== undefined) { - var no_variants = combinationData.no_variant_product_template_attribute_value_ids; - filteredCombination = _.filter(combination, function (ptav) { - return !isPtavInCombination(ptav, no_variants); - }); - } - // exclusion rules: array of ptav // for each of them, contains array with the other ptav they exclude if (combinationData.exclusions) { @@ -386,11 +369,6 @@ var ProductConfiguratorMixin = { if (combinationData.exclusions.hasOwnProperty(current_ptav)) { // for each exclusion of the current attribute: _.each(combinationData.exclusions[current_ptav], function (excluded_ptav) { - // disable if it excludes any other attribute already in the combination - if (isPtavInCombination(excluded_ptav, combination)) { - disable = true; - } - // disable the excluded input (even when not already selected) // to give a visual feedback before click self._disableInput($parent, excluded_ptav); @@ -401,37 +379,11 @@ var ProductConfiguratorMixin = { // parent exclusions (tell which attributes are excluded from parent) _.each(combinationData.parent_exclusions, function (ptav) { - if (isPtavInCombination(ptav, combination)) { - disable = true; - } // disable the excluded input (even when not already selected) // to give a visual feedback before click self._disableInput($parent, ptav); }); - - // archived variants - if (isCombinationInList(filteredCombination, combinationData.archived_combinations)) { - disable = true; - } - - // if not using dynamic attributes, exclude variants that are deleted - if (filteredCombination.length && // compatibility 12.0 list view of variants - combinationData.has_dynamic_attributes === false && - combinationData.existing_combinations !== undefined && - !isCombinationInList(filteredCombination, combinationData.existing_combinations) - ) { - disable = true; - } - - this.isSelectedVariantAllowed = !disable; - $parent.toggleClass('css_not_available', disable); - $parent.find("#add_to_cart").toggleClass('disabled', disable); - $parent - .parents('.modal') - .find('.o_sale_product_configurator_add') - .toggleClass('disabled', disable); }, - /** * Extracted to a method to be extendable by other modules * @@ -440,7 +392,6 @@ var ProductConfiguratorMixin = { _getProductId: function ($parent) { return parseInt($parent.find('.product_id').val()); }, - /** * Will disable the input/option that refers to the passed attributeValueId. * This is used for showing the user that some combinations are not available. @@ -455,7 +406,6 @@ var ProductConfiguratorMixin = { $input.addClass('css_not_available'); $input.closest('label').addClass('css_not_available'); }, - /** * @see onChangeVariant * @@ -469,6 +419,15 @@ var ProductConfiguratorMixin = { var $price = $parent.find(".oe_price:first .oe_currency_value"); var $default_price = $parent.find(".oe_default_price:first .oe_currency_value"); var $optional_price = $parent.find(".oe_optional:first .oe_currency_value"); + + var isCombinationPossible = this.isSelectedVariantAllowed; + + if (combination.is_combination_possible !== undefined) { + isCombinationPossible = combination.is_combination_possible; + } + + this._toggleDisable($parent, isCombinationPossible); + $price.html(self._priceToStr(combination.price)); $default_price.html(self._priceToStr(combination.list_price)); @@ -505,7 +464,8 @@ var ProductConfiguratorMixin = { $parent.closest(rootComponentSelectors.join(', ')), combination.product_id, combination.product_template_id, - combination.carousel + combination.carousel, + isCombinationPossible ); } @@ -525,7 +485,6 @@ var ProductConfiguratorMixin = { .first() .html(combination.price); - this.computePriceTotal(); this.handleCustomValues($(ev.target)); }, @@ -546,7 +505,46 @@ var ProductConfiguratorMixin = { formatted[0] = utils.insert_thousand_seps(formatted[0]); return formatted.join(l10n.decimal_point); }, - + /** + * Returns a throttled `_getCombinationInfo` with a leading and a trailing + * call, which is memoized per `uniqueId`, and for which previous results + * are dropped. + * + * The uniqueId is needed because on the configurator modal there might be + * multiple elements triggering the rpc at the same time, and we need each + * individual product rpc to be executed, but only once per individual + * product. + * + * The leading execution is to keep good reactivity on the first call, for + * a better user experience. The trailing is because ultimately only the + * information about the last selected combination is useful. All + * intermediary rpc can be ignored and are therefore best not done at all. + * + * The DropMisordered is to make sure slower rpc are ignored if the result + * of a newer rpc has already been received. + * + * @private + * @param {string} uniqueId + * @returns {function} + */ + _throttledGetCombinationInfo: _.memoize(function (uniqueId) { + var dropMisordered = new concurrency.DropMisordered(); + var _getCombinationInfo = _.throttle(this._getCombinationInfo.bind(this), 500); + return function (ev) { + return dropMisordered.add(_getCombinationInfo(ev)); + }; + }), + /** + * Toggles the disabled class depending on the $parent element + * and the possibility of the current combination. + * + * @private + * @param {$.Element} $parent + * @param {boolean} isCombinationPossible + */ + _toggleDisable: function ($parent, isCombinationPossible) { + $parent.toggleClass('css_not_available', !isCombinationPossible); + }, /** * Updates the product image. * This will use the productId if available or will fallback to the productTemplateId. diff --git a/addons/sale/static/src/js/product_configurator_modal.js b/addons/sale/static/src/js/product_configurator_modal.js index 7cd61d6baec..0d6908a807b 100644 --- a/addons/sale/static/src/js/product_configurator_modal.js +++ b/addons/sale/static/src/js/product_configurator_modal.js @@ -12,20 +12,12 @@ var optionalProductsMap = {}; var OptionalProductsModal = Dialog.extend(ServicesMixin, ProductConfiguratorMixin, { events: _.extend({}, Dialog.prototype.events, ProductConfiguratorMixin.events, { 'click a.js_add, a.js_remove': '_onAddOrRemoveOption', - 'change .in_cart.main_product input.js_quantity': '_onChangeQuantity' + 'click button.js_add_cart_json': 'onClickAddCartJSON', + 'change .in_cart.main_product input.js_quantity': '_onChangeQuantity', }), /** * Initializes the optional products modal * - * If the "isWebsite" param is true, will also disable the following events: - * - change [data-attribute_exclusions] - * - click button.js_add_cart_json - * - * This has to be done because those events are already registered at the "website_sale" - * component level. - * This modal is part of the form that has these events registered and we - * want to avoid duplicates. - * * @override * @param {$.Element} parent The parent container * @param {Object} params @@ -67,10 +59,6 @@ var OptionalProductsModal = Dialog.extend(ServicesMixin, ProductConfiguratorMixi this.pricelistId = params.pricelistId; this.isWebsite = params.isWebsite; this.dialogClass = 'oe_optional_products_modal' + (params.isWebsite ? ' oe_website_sale' : ''); - - if (this.isWebsite) { - delete this.events['click button.js_add_cart_json']; - } this._productImageField = 'image_medium'; }, /** @@ -156,6 +144,25 @@ var OptionalProductsModal = Dialog.extend(ServicesMixin, ProductConfiguratorMixi // Public //-------------------------------------------------------------------------- + /** + * Computes and updates the total price, useful when a product is added or + * when the quantity is changed. + * TODO awa: add a container context to avoid global selectors ? + */ + computePriceTotal: function () { + if ($('.js_price_total').length) { + var price = 0; + $('.js_product.in_cart').each(function () { + var quantity = parseInt($('input[name="add_qty"]').first().val()); + price += parseFloat($(this).find('.js_raw_price').html()) * quantity; + }); + + $('.js_price_total .oe_currency_value').html( + this._priceToStr(parseFloat(price)) + ); + } + ProductConfiguratorMixin.computePriceTotal.apply(this, arguments); + }, /** * Returns the list of selected products. * The root product is added on top of the list. @@ -450,6 +457,8 @@ var OptionalProductsModal = Dialog.extend(ServicesMixin, ProductConfiguratorMixi .text(combination.display_name); ProductConfiguratorMixin._onChangeCombination.apply(this, arguments); + + this.computePriceTotal(); }, /** * When the quantity of the root product is updated, we need to update diff --git a/addons/sale/static/src/js/product_configurator_renderer.js b/addons/sale/static/src/js/product_configurator_renderer.js index 899656c8065..d2cebf8794e 100644 --- a/addons/sale/static/src/js/product_configurator_renderer.js +++ b/addons/sale/static/src/js/product_configurator_renderer.js @@ -5,6 +5,10 @@ var FormRenderer = require('web.FormRenderer'); var ProductConfiguratorMixin = require('sale.ProductConfiguratorMixin'); var ProductConfiguratorFormRenderer = FormRenderer.extend(ProductConfiguratorMixin ,{ + + events: _.extend({}, FormRenderer.prototype.events, ProductConfiguratorMixin.events, { + 'click button.js_add_cart_json': 'onClickAddCartJSON', + }), /** * @override */ @@ -44,7 +48,22 @@ var ProductConfiguratorFormRenderer = FormRenderer.extend(ProductConfiguratorMix $configuratorHtml.appendTo($configuratorContainer); this.triggerVariantChange($configuratorContainer); - } + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * Toggles the add button depending on the possibility of the current + * combination. + * + * @override + */ + _toggleDisable: function ($parent, isCombinationPossible) { + ProductConfiguratorMixin._toggleDisable.apply(this, arguments); + $parent.parents('.modal').find('.o_sale_product_configurator_add').toggleClass('disabled', !isCombinationPossible); + }, }); return ProductConfiguratorFormRenderer; diff --git a/addons/sale/views/res_config_settings_views.xml b/addons/sale/views/res_config_settings_views.xml index bc1366e5d5c..f7c2fd973fa 100644 --- a/addons/sale/views/res_config_settings_views.xml +++ b/addons/sale/views/res_config_settings_views.xml @@ -50,7 +50,7 @@
diff --git a/addons/sale/views/sale_views.xml b/addons/sale/views/sale_views.xml index d6313076e6c..62fd461d080 100644 --- a/addons/sale/views/sale_views.xml +++ b/addons/sale/views/sale_views.xml @@ -491,6 +491,7 @@ +
diff --git a/addons/sale_management/static/tests/product_configurator_test_ui.js b/addons/sale_management/static/tests/product_configurator_test_ui.js index 03f5a0a8bbc..0c98a46c166 100644 --- a/addons/sale_management/static/tests/product_configurator_test_ui.js +++ b/addons/sale_management/static/tests/product_configurator_test_ui.js @@ -30,16 +30,7 @@ tour.register('sale_product_configurator_tour', { run: 'click' }, { trigger: '.configurator_container span:contains("Steel")', - run: function () { - $('input.product_id').change(function () { - var request_count = 0; - if ($('.o_sale_product_configurator_add').attr('request_count')) { - request_count = parseInt($('.o_sale_product_configurator_add').attr('request_count')); - } - request_count++; - $('.o_sale_product_configurator_add').attr('request_count', request_count); - }); - } + run: function () {}, }, { trigger: '.configurator_container span:contains("Aluminium")', run: 'click' @@ -49,10 +40,9 @@ tour.register('sale_product_configurator_tour', { }, { trigger: 'input[data-value_name="Black"]' }, { - trigger: 'input[data-value_name="White"]' + trigger: '.o_sale_product_configurator_add.disabled' }, { - trigger: '.o_sale_product_configurator_add[request_count="3"]', - run: function (){} // used to sync with "get_combination_info" completion + trigger: 'input[data-value_name="White"]' }, { trigger: '.o_sale_product_configurator_add:not(.disabled)' }, { diff --git a/addons/sale_stock/models/sale_order.py b/addons/sale_stock/models/sale_order.py index ec068f21a5b..a01080ef7b1 100644 --- a/addons/sale_stock/models/sale_order.py +++ b/addons/sale_stock/models/sale_order.py @@ -96,6 +96,21 @@ class SaleOrder(models.Model): if self.warehouse_id.company_id: self.company_id = self.warehouse_id.company_id.id + @api.onchange('partner_shipping_id') + def _onchange_partner_shipping_id(self): + res = {} + pickings = self.picking_ids.filtered( + lambda p: p.state not in ['done', 'cancel'] and p.partner_id != self.partner_shipping_id + ) + if pickings: + res['warning'] = { + 'title': _('Warning!'), + 'message': _( + 'Do not forget to change the partner on the following delivery orders: %s' + ) % (','.join(pickings.mapped('name'))) + } + return res + @api.multi def action_view_delivery(self): ''' diff --git a/addons/sms/models/mail_thread.py b/addons/sms/models/mail_thread.py index 1fb62a72de4..a439487e4e9 100644 --- a/addons/sms/models/mail_thread.py +++ b/addons/sms/models/mail_thread.py @@ -39,8 +39,8 @@ class MailThread(models.AbstractModel): if not partners: partners = self._get_default_sms_recipients() - # Collect numbers, we will consider the message to be sent if at least one number can be found - numbers = list(set([i.mobile for i in partners if i.mobile])) + # Collect numbers, we will consider the message to be sent if at least one number can be found + numbers = list(set([i.mobile for i in partners if i.mobile])) if numbers: try: diff --git a/addons/sms/wizard/send_sms.py b/addons/sms/wizard/send_sms.py index 786a5e2af76..986fd1c9239 100644 --- a/addons/sms/wizard/send_sms.py +++ b/addons/sms/wizard/send_sms.py @@ -45,8 +45,8 @@ class SendSMS(models.TransientModel): return number if not phonenumbers.is_possible_number(phone_nbr) or not phonenumbers.is_valid_number(phone_nbr): return number - phone_fmt = phonenumbers.PhoneNumberFormat.INTERNATIONAL - return phonenumbers.format_number(phone_nbr, phone_fmt).replace(' ', '') + phone_fmt = phonenumbers.PhoneNumberFormat.E164 + return phonenumbers.format_number(phone_nbr, phone_fmt) else: return number @@ -62,12 +62,11 @@ class SendSMS(models.TransientModel): @api.model def default_get(self, fields): result = super(SendSMS, self).default_get(fields) - active_model = self.env.context.get('active_model') - model = self.env[active_model] - records = self._get_records(model) - if getattr(records, '_get_default_sms_recipients') and not self.env.context.get('default_recipients'): + if not self.env.context.get('default_recipients') and active_model and hasattr(self.env[active_model], '_get_default_sms_recipients'): + model = self.env[active_model] + records = self._get_records(model) partners = records._get_default_sms_recipients() phone_numbers = [] no_phone_partners = [] @@ -84,12 +83,12 @@ class SendSMS(models.TransientModel): return result def action_send_sms(self): - numbers = self.recipients.split(',') + numbers = [number.strip() for number in self.recipients.split(',') if number.strip()] active_model = self.env.context.get('active_model') - model = self.env[active_model] - records = self._get_records(model) - if getattr(records, 'message_post_send_sms'): + if active_model and hasattr(self.env[active_model], 'message_post_send_sms'): + model = self.env[active_model] + records = self._get_records(model) records.message_post_send_sms(self.message, numbers=numbers) else: self.env['sms.api']._send_sms(numbers, self.message) diff --git a/addons/stock/models/product.py b/addons/stock/models/product.py index 099d04d982e..6e31e58f3d0 100644 --- a/addons/stock/models/product.py +++ b/addons/stock/models/product.py @@ -487,6 +487,10 @@ class ProductTemplate(models.Model): def _is_cost_method_standard(self): return True + @api.depends( + 'product_variant_ids', + 'product_variant_ids.stock_quant_ids', + ) def _compute_quantities(self): res = self._compute_quantities_dict() for template in self: diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index 1224a5f63b5..975dee846bd 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -468,6 +468,7 @@ class StockMove(models.Model): else: view = self.env.ref('stock.view_stock_move_nosuggest_operations') + picking_type_id = self.picking_type_id or self.picking_id.picking_type_id return { 'name': _('Detailed Operations'), 'type': 'ir.actions.act_window', @@ -480,8 +481,8 @@ class StockMove(models.Model): 'res_id': self.id, 'context': dict( self.env.context, - show_lots_m2o=self.has_tracking != 'none' and (self.picking_type_id.use_existing_lots or self.state == 'done' or self.origin_returned_move_id.id), # able to create lots, whatever the value of ` use_create_lots`. - show_lots_text=self.has_tracking != 'none' and self.picking_type_id.use_create_lots and not self.picking_type_id.use_existing_lots and self.state != 'done' and not self.origin_returned_move_id.id, + show_lots_m2o=self.has_tracking != 'none' and (picking_type_id.use_existing_lots or self.state == 'done' or self.origin_returned_move_id.id), # able to create lots, whatever the value of ` use_create_lots`. + show_lots_text=self.has_tracking != 'none' and picking_type_id.use_create_lots and not picking_type_id.use_existing_lots and self.state != 'done' and not self.origin_returned_move_id.id, show_source_location=self.location_id.child_ids and self.picking_type_id.code != 'incoming', show_destination_location=self.location_dest_id.child_ids and self.picking_type_id.code != 'outgoing', show_package=not self.location_id.usage == 'supplier', diff --git a/addons/stock/models/stock_warehouse.py b/addons/stock/models/stock_warehouse.py index cf1dd8e031e..c80f9efe6e6 100644 --- a/addons/stock/models/stock_warehouse.py +++ b/addons/stock/models/stock_warehouse.py @@ -892,7 +892,6 @@ class Warehouse(models.Model): @api.returns('self') def _get_all_routes(self): - # TDE FIXME: check overrides routes = self.mapped('route_ids') | self.mapped('mto_pull_id').mapped('route_id') routes |= self.env["stock.location.route"].search([('supplied_wh_id', 'in', self.ids)]) return routes diff --git a/addons/stock/wizard/stock_picking_return_views.xml b/addons/stock/wizard/stock_picking_return_views.xml index 3bbba44a176..37b8af9a1e9 100644 --- a/addons/stock/wizard/stock_picking_return_views.xml +++ b/addons/stock/wizard/stock_picking_return_views.xml @@ -27,7 +27,7 @@ - +
'+ '
'+ - '