[MERGE] forward port branch 10.0 up to e336dc38ca

This commit is contained in:
Christophe Simonis
2018-01-02 13:56:49 +01:00
32 changed files with 368 additions and 88 deletions
+7 -4
View File
@@ -700,7 +700,7 @@ class AccountInvoice(models.Model):
total_currency = 0
for line in invoice_move_lines:
if self.currency_id != company_currency:
currency = self.currency_id.with_context(date=self.date or self.date_invoice or fields.Date.context_today(self))
currency = self.currency_id.with_context(date=self._get_currency_rate_date() or fields.Date.context_today(self))
if not (line.get('currency_id') and line.get('amount_currency')):
line['currency_id'] = currency.id
line['amount_currency'] = currency.round(line['price'])
@@ -848,7 +848,7 @@ class AccountInvoice(models.Model):
if inv.payment_term_id:
totlines = inv.with_context(ctx).payment_term_id.with_context(currency_id=company_currency.id).compute(total, inv.date_invoice)[0]
res_amount_currency = total_currency
ctx['date'] = inv.date or inv.date_invoice
ctx['date'] = inv._get_currency_rate_date()
for i, t in enumerate(totlines):
if inv.currency_id != company_currency:
amount_currency = company_currency.with_context(ctx).compute(t[1], inv.currency_id)
@@ -1035,6 +1035,9 @@ class AccountInvoice(models.Model):
copy_fields = ['company_id', 'user_id', 'fiscal_position_id']
return self._get_refund_common_fields() + self._get_refund_prepare_fields() + copy_fields
def _get_currency_rate_date(self):
return self.date or self.date_invoice
@api.model
def _prepare_refund(self, invoice, date_invoice=None, date=None, description=None, journal_id=None):
""" Prepare the dict of values to create the new refund from the invoice.
@@ -1194,7 +1197,7 @@ class AccountInvoiceLine(models.Model):
@api.one
@api.depends('price_unit', 'discount', 'invoice_line_tax_ids', 'quantity',
'product_id', 'invoice_id.partner_id', 'invoice_id.currency_id', 'invoice_id.company_id',
'invoice_id.date_invoice')
'invoice_id.date_invoice', 'invoice_id.date')
def _compute_price(self):
currency = self.invoice_id and self.invoice_id.currency_id or None
price = self.price_unit * (1 - (self.discount or 0.0) / 100.0)
@@ -1203,7 +1206,7 @@ class AccountInvoiceLine(models.Model):
taxes = self.invoice_line_tax_ids.compute_all(price, currency, self.quantity, product=self.product_id, partner=self.invoice_id.partner_id)
self.price_subtotal = price_subtotal_signed = taxes['total_excluded'] if taxes else self.quantity * price
if self.invoice_id.currency_id and self.invoice_id.company_id and self.invoice_id.currency_id != self.invoice_id.company_id.currency_id:
price_subtotal_signed = self.invoice_id.currency_id.with_context(date=self.invoice_id.date_invoice).compute(price_subtotal_signed, self.invoice_id.company_id.currency_id)
price_subtotal_signed = self.invoice_id.currency_id.with_context(date=self.invoice_id._get_currency_rate_date()).compute(price_subtotal_signed, self.invoice_id.company_id.currency_id)
sign = self.invoice_id.type in ['in_refund', 'out_refund'] and -1 or 1
self.price_subtotal_signed = price_subtotal_signed * sign
+2
View File
@@ -165,6 +165,8 @@ class AccountMove(models.Model):
if not move.journal_id.update_posted:
raise UserError(_('You cannot modify a posted entry of this journal.\nFirst you should set the journal to allow cancelling entries.'))
if self.ids:
self.check_access_rights('write')
self.check_access_rule('write')
self._check_lock_date()
self._cr.execute('UPDATE account_move '\
'SET state=%s '\
+1 -1
View File
@@ -16,7 +16,7 @@
</p>
<t t-if="Lines[o.id]">
<span t-field="res_company.overdue_msg"/>
<span t-field="res_company.with_context(lang=o.lang).overdue_msg"/>
<table class="table table-condensed" t-foreach="Lines[o.id]" t-as="currency">
<thead>
<tr>
@@ -96,7 +96,7 @@
<field name="crossovered_budget_line" context="{'default_date_from': date_from,'default_date_to': date_to}" colspan="4" nolabel="1" attrs="{'readonly':[('state','!=','draft')]}">
<tree string="Budget Lines">
<field name="general_budget_id"/>
<field name="analytic_account_id" groups="analytic.group_analytic_accounting"/>
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" required="1"/>
<field name="date_from"/>
<field name="date_to"/>
<field name="paid_date" groups="base.group_no_one"/>
@@ -110,7 +110,7 @@
<group>
<field name="general_budget_id"/>
<field name="planned_amount" widget="monetary"/>
<field name="analytic_account_id" groups="analytic.group_analytic_accounting"/>
<field name="analytic_account_id" groups="analytic.group_analytic_accounting" required="1"/>
</group>
<group>
<label for="date_from" string="Period"/>
+1 -1
View File
@@ -586,7 +586,7 @@ class Import(models.TransientModel):
# Check that currency exists
currency = self.env['res.currency'].search([('symbol', '=', split_value[currency_index].strip())])
if len(currency):
return split_value[currency_index + 1 % 2] if not negative else '-' + split_value[currency_index + 1 % 2]
return split_value[(currency_index + 1) % 2] if not negative else '-' + split_value[(currency_index + 1) % 2]
# Otherwise it is not a float with a currency symbol
return False
@@ -13,6 +13,8 @@ class AccountMoveLine(models.Model):
res = super(AccountMoveLine, self).reconcile(writeoff_acc_id=writeoff_acc_id, writeoff_journal_id=writeoff_journal_id)
account_move_ids = [l.move_id.id for l in self if float_compare(l.move_id.matched_percentage, 1, precision_digits=5) == 0]
if account_move_ids:
expense_sheets = self.env['hr.expense.sheet'].search([('account_move_id', 'in', account_move_ids)])
expense_sheets = self.env['hr.expense.sheet'].search([
('account_move_id', 'in', account_move_ids), ('state', '!=', 'done')
])
expense_sheets.set_to_paid()
return res
+10 -8
View File
@@ -417,18 +417,20 @@ class HrExpenseSheet(models.Model):
@api.multi
def check_consistency(self):
if any(sheet.employee_id != self[0].employee_id for sheet in self):
raise UserError(_("Expenses must belong to the same Employee."))
expense_lines = self.mapped('expense_line_ids')
if expense_lines and any(expense.payment_mode != expense_lines[0].payment_mode for expense in expense_lines):
raise UserError(_("Expenses must have been paid by the same entity (Company or employee)"))
for rec in self:
expense_lines = rec.expense_line_ids
if not expense_lines:
continue
if any(expense.employee_id != rec.employee_id for expense in expense_lines):
raise UserError(_("Expenses must belong to the same Employee."))
if any(expense.payment_mode != expense_lines[0].payment_mode for expense in expense_lines):
raise UserError(_("Expenses must have been paid by the same entity (Company or employee)"))
@api.model
def create(self, vals):
self._create_set_followers(vals)
sheet = super(HrExpenseSheet, self).create(vals)
self.check_consistency()
sheet.check_consistency()
return sheet
@api.multi
@@ -588,7 +590,7 @@ class HrExpenseSheet(models.Model):
@api.one
@api.constrains('expense_line_ids')
@api.constrains('expense_line_ids', 'employee_id')
def _check_employee(self):
employee_ids = self.expense_line_ids.mapped('employee_id')
if len(employee_ids) > 1 or (len(employee_ids) == 1 and employee_ids != self.employee_id):
@@ -19,6 +19,16 @@
<field name="tax_dest_id" ref="vat_O_import" />
</record>
<record id="fiscal_position_tax_template_5" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_import" />
<field name="tax_src_id" ref="vat_37_purchase" />
<field name="tax_dest_id" ref="vat_O_import" />
</record>
<record id="fiscal_position_tax_template_6" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_import" />
<field name="tax_src_id" ref="vat_37_invest" />
<field name="tax_dest_id" ref="vat_O_import" />
</record>
<record id="fiscal_position_tax_template_7" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_import" />
<field name="tax_src_id" ref="vat_38_purchase" />
@@ -29,6 +39,16 @@
<field name="tax_src_id" ref="vat_38_invest" />
<field name="tax_dest_id" ref="vat_O_import" />
</record>
<record id="fiscal_position_tax_template_9" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_import" />
<field name="tax_src_id" ref="vat_77_purchase" />
<field name="tax_dest_id" ref="vat_O_import" />
</record>
<record id="fiscal_position_tax_template_10" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_import" />
<field name="tax_src_id" ref="vat_77_invest" />
<field name="tax_dest_id" ref="vat_O_import" />
</record>
<record id="fiscal_position_tax_template_11" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_import" />
@@ -46,13 +66,21 @@
<field name="tax_src_id" ref="vat_25" />
<field name="tax_dest_id" ref="vat_XO" />
</record>
<record id="fiscal_position_tax_template_15" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_import" />
<field name="tax_src_id" ref="vat_37" />
<field name="tax_dest_id" ref="vat_XO" />
</record>
<record id="fiscal_position_tax_template_16" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_import" />
<field name="tax_src_id" ref="vat_38" />
<field name="tax_dest_id" ref="vat_XO" />
</record>
<record id="fiscal_position_tax_template_17" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_import" />
<field name="tax_src_id" ref="vat_77" />
<field name="tax_dest_id" ref="vat_XO" />
</record>
<record id="fiscal_position_tax_template_18" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fiscal_position_template_import" />
<field name="tax_src_id" ref="vat_80" />
@@ -32,6 +32,10 @@
<field name="name">Switzerland VAT Form: grid 301 base</field>
<field name="applicability">taxes</field>
</record>
<record id="vat_tag_302_a" model="account.account.tag">
<field name="name">Switzerland VAT Form: grid 302 base</field>
<field name="applicability">taxes</field>
</record>
<record id="vat_tag_311_a" model="account.account.tag">
<field name="name">Switzerland VAT Form: grid 311 base</field>
<field name="applicability">taxes</field>
@@ -40,6 +44,10 @@
<field name="name">Switzerland VAT Form: grid 341 base</field>
<field name="applicability">taxes</field>
</record>
<record id="vat_tag_342_a" model="account.account.tag">
<field name="name">Switzerland VAT Form: grid 342 base</field>
<field name="applicability">taxes</field>
</record>
<record id="vat_tag_381_a" model="account.account.tag">
<field name="name">Switzerland VAT Form: grid 381 base</field>
<field name="applicability">taxes</field>
@@ -48,6 +56,10 @@
<field name="name">Switzerland VAT Form: grid 301 tax</field>
<field name="applicability">taxes</field>
</record>
<record id="vat_tag_302_b" model="account.account.tag">
<field name="name">Switzerland VAT Form: grid 302 tax</field>
<field name="applicability">taxes</field>
</record>
<record id="vat_tag_311_b" model="account.account.tag">
<field name="name">Switzerland VAT Form: grid 311 tax</field>
<field name="applicability">taxes</field>
@@ -56,6 +68,10 @@
<field name="name">Switzerland VAT Form: grid 341 tax</field>
<field name="applicability">taxes</field>
</record>
<record id="vat_tag_342_b" model="account.account.tag">
<field name="name">Switzerland VAT Form: grid 342 tax</field>
<field name="applicability">taxes</field>
</record>
<record id="vat_tag_381_b" model="account.account.tag">
<field name="name">Switzerland VAT Form: grid 381 tax</field>
<field name="applicability">taxes</field>
@@ -160,6 +176,75 @@
<field name="tag_ids" eval="[(6,0,[ref('vat_tag_405')])]"/>
</record>
<record model="account.tax.template" id="vat_37">
<field name="name">TVA due a 3.7% (TS)</field>
<field name="description">3.7%</field>
<field name="amount" eval="3.7"/>
<field name="amount_type">percent</field>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">sale</field>
<field name="refund_account_id" ref="ch_coa_2200"/>
<field name="account_id" ref="ch_coa_2200"/>
<field name="tag_ids" eval="[(6,0,[ref('vat_tag_342_a'), ref('vat_tag_342_b')])]"/>
</record>
<record model="account.tax.template" id="vat_37_incl">
<field name="name">TVA due à 3.7% (Incl. TS)</field>
<field name="description">3.7% Incl.</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="3.7"/>
<field name="amount_type">percent</field>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">sale</field>
<field name="refund_account_id" ref="ch_coa_2200"/>
<field name="account_id" ref="ch_coa_2200"/>
<field name="tag_ids" eval="[(6,0,[ref('vat_tag_342_a'), ref('vat_tag_342_b')])]"/>
</record>
<record model="account.tax.template" id="vat_37_purchase">
<field name="name">TVA 3.7% sur achat B&amp;S (TS)</field>
<field name="description">3.7% achat</field>
<field name="amount" eval="3.7"/>
<field name="amount_type">percent</field>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="refund_account_id" ref="ch_coa_1170"/>
<field name="account_id" ref="ch_coa_1170"/>
<field name="tag_ids" eval="[(6,0,[ref('vat_tag_400')])]"/>
</record>
<record model="account.tax.template" id="vat_37_purchase_incl">
<field name="name">TVA 3.7% sur achat B&amp;S (Incl. TS)</field>
<field name="description">3.7% achat Incl.</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="3.7"/>
<field name="amount_type">percent</field>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="refund_account_id" ref="ch_coa_1170"/>
<field name="account_id" ref="ch_coa_1170"/>
<field name="tag_ids" eval="[(6,0,[ref('vat_tag_400')])]"/>
</record>
<record model="account.tax.template" id="vat_37_invest">
<field name="name">TVA 3.7% sur invest. et autres ch. (TS)</field>
<field name="description">3.7% invest</field>
<field name="amount" eval="3.7"/>
<field name="amount_type">percent</field>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="refund_account_id" ref="ch_coa_1171"/>
<field name="account_id" ref="ch_coa_1171"/>
<field name="tag_ids" eval="[(6,0,[ref('vat_tag_405')])]"/>
</record>
<record model="account.tax.template" id="vat_37_invest_incl">
<field name="name">TVA 3.7% sur invest. et autres ch. (Incl. TS)</field>
<field name="description">3.7% invest Incl.</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="3.7"/>
<field name="amount_type">percent</field>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="refund_account_id" ref="ch_coa_1171"/>
<field name="account_id" ref="ch_coa_1171"/>
<field name="tag_ids" eval="[(6,0,[ref('vat_tag_405')])]"/>
</record>
<record model="account.tax.template" id="vat_38">
<field name="name">TVA due a 3.8% (TS)</field>
<field name="description">3.8%</field>
@@ -229,6 +314,80 @@
<field name="account_id" ref="ch_coa_1171"/>
<field name="tag_ids" eval="[(6,0,[ref('vat_tag_405')])]"/>
</record>
<record model="account.tax.template" id="vat_77">
<field name="name">TVA due a 7.7% (TN)</field>
<field name="description">7.7%</field>
<field name="amount" eval="7.7"/>
<field name="sequence" eval="0"/>
<field name="amount_type">percent</field>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">sale</field>
<field name="refund_account_id" ref="ch_coa_2200"/>
<field name="account_id" ref="ch_coa_2200"/>
<field name="tag_ids" eval="[(6,0,[ref('vat_tag_302_a'), ref('vat_tag_302_b')])]"/>
</record>
<record model="account.tax.template" id="vat_77_incl">
<field name="name">TVA due à 7.7% (Incl. TN)</field>
<field name="description">7.7% Incl.</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="7.7"/>
<field name="sequence" eval="0"/>
<field name="amount_type">percent</field>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">sale</field>
<field name="refund_account_id" ref="ch_coa_2200"/>
<field name="account_id" ref="ch_coa_2200"/>
<field name="tag_ids" eval="[(6,0,[ref('vat_tag_302_a'), ref('vat_tag_302_b')])]"/>
</record>
<record model="account.tax.template" id="vat_77_purchase">
<field name="name">TVA 7.7% sur achat B&amp;S (TN)</field>
<field name="description">7.7% achat</field>
<field name="amount" eval="7.7"/>
<field name="amount_type">percent</field>
<field name="sequence" eval="0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="refund_account_id" ref="ch_coa_1170"/>
<field name="account_id" ref="ch_coa_1170"/>
<field name="tag_ids" eval="[(6,0,[ref('vat_tag_400')])]"/>
</record>
<record model="account.tax.template" id="vat_77_purchase_incl">
<field name="name">TVA 7.7% sur achat B&amp;S (Incl. TN)</field>
<field name="description">7.7% achat Incl.</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="7.7"/>
<field name="amount_type">percent</field>
<field name="sequence" eval="0"/>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="refund_account_id" ref="ch_coa_1170"/>
<field name="account_id" ref="ch_coa_1170"/>
<field name="tag_ids" eval="[(6,0,[ref('vat_tag_400')])]"/>
</record>
<record model="account.tax.template" id="vat_77_invest">
<field name="name">TVA 7.7% sur invest. et autres ch. (TN)</field>
<field name="description">7.7% invest.</field>
<field name="amount" eval="7.7"/>
<field name="amount_type">percent</field>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="refund_account_id" ref="ch_coa_1171"/>
<field name="account_id" ref="ch_coa_1171"/>
<field name="tag_ids" eval="[(6,0,[ref('vat_tag_405')])]"/>
</record>
<record model="account.tax.template" id="vat_77_invest_incl">
<field name="name">TVA 7.7% sur invest. et autres ch. (Incl. TN)</field>
<field name="description">7.7% invest. Incl.</field>
<field name="price_include" eval="1"/>
<field name="amount" eval="7.7"/>
<field name="amount_type">percent</field>
<field name="chart_template_id" ref="l10nch_chart_template"/>
<field name="type_tax_use">purchase</field>
<field name="refund_account_id" ref="ch_coa_1171"/>
<field name="account_id" ref="ch_coa_1171"/>
<field name="tag_ids" eval="[(6,0,[ref('vat_tag_405')])]"/>
</record>
<record model="account.tax.template" id="vat_80">
<field name="name">TVA due a 8.0% (TN)</field>
<field name="description">8.0%</field>
+2 -2
View File
@@ -1,4 +1,4 @@
from datetime import datetime
from datetime import datetime, timedelta
from hashlib import sha256
from json import dumps
import pytz
@@ -41,7 +41,7 @@ class pos_session(models.Model):
self.ensure_one()
date_today = datetime.utcnow()
session_start = Datetime.from_string(self.start_at)
if not date_today - datetime.timedelta(hours=24) <= session_start:
if not date_today - timedelta(hours=24) <= session_start:
raise UserError(_("This session has been opened another day. To comply with the French law, you should close sessions on a daily basis. Please close session %s and open a new one.") % self.name)
return True
@@ -160,7 +160,7 @@ or (contract.wage * 0.10))</field>
<field name="name">Arrears</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.ARS.amount</field>
<field name="amount_python_compute">result = inputs.ARS and inputs.ARS.amount</field>
<field eval="0.0" name="amount_fix"/>
<field name="sequence" eval="28"/>
<field name="note">Generally arrears are fully taxable, but employee may claim exemption u/s 89(1).
@@ -185,7 +185,7 @@ Now difference of income tax between payment year and actual year would be allow
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.LE.amount</field>
<field name="amount_python_compute">result = inputs.LE and inputs.LE.amount</field>
<field name="sequence" eval="30"/>
<field name="note">Payment by way of leave encashment received by Central and State Govt.employees at the time of retirement in respect of the period of earned leave at credit is fully exempt. In case of other employees, the exemption is to be limited to minimum of all below:
1.The actual amount received
@@ -199,7 +199,7 @@ Now difference of income tax between payment year and actual year would be allow
<field name="name">Performance Incentive</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.PERF.amount</field>
<field name="amount_python_compute">result = inputs.PERF and inputs.PERF.amount</field>
<field name="sequence" eval="31"/>
<field name="note">This would be fully taxable based on incentive.</field>
</record>
@@ -209,7 +209,7 @@ Now difference of income tax between payment year and actual year would be allow
<field name="name">Bonus</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.BNS.amount</field>
<field name="amount_python_compute">result = inputs.BNS and inputs.BNS.amount</field>
<field name="sequence" eval="41"/>
<field name="note">This would be fully taxable based on Bonus.</field>
</record>
@@ -229,7 +229,7 @@ Now difference of income tax between payment year and actual year would be allow
<field name="name">Medical Reimbursement</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.MR.amount</field>
<field name="amount_python_compute">result = inputs.MR and inputs.MR.amount</field>
<field name="sequence" eval="32"/>
<field name="note">This component is on-taxable up to 15000 per year (or Rs 1250 per month) on producing medical bills.</field>
</record>
@@ -250,7 +250,7 @@ Now difference of income tax between payment year and actual year would be allow
<field name="name">Periodical Journals</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.PJ.amount</field>
<field name="amount_python_compute">result = inputs.PJ and inputs.PJ.amount</field>
<field name="sequence" eval="34"/>
<field name="note">Some employers may provide component for buying magazines, journals and books as a part of knowledge enhancement for business growth.This part would become non taxable on providing original bills.</field>
</record>
@@ -280,7 +280,7 @@ Now difference of income tax between payment year and actual year would be allow
<field name="name">Telephone Reimbursement</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.TR.amount</field>
<field name="amount_python_compute">result = inputs.TR and inputs.TR.amount</field>
<field name="sequence" eval="36"/>
<field name="note">In some of the cases, companies may provide a component for telephone bills.Employees may provide actual phone usage bills to reimburse this component and make it non-taxable.
</field>
@@ -300,7 +300,7 @@ Now difference of income tax between payment year and actual year would be allow
<field name="name">Car Expenses Reimbursement</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.CEI.amount</field>
<field name="amount_python_compute">result = inputs.CEI and inputs.CEI.amount</field>
<field name="sequence" eval="38"/>
<field name="note">In case company provides component for this and employee use self owned car for official and personal purposes, Rs 1800 per month would be non-taxable on showing bills for fuel or can maintenance. This amount would be Rs 2400 in case car is more capacity than 1600cc.</field>
</record>
@@ -310,7 +310,7 @@ Now difference of income tax between payment year and actual year would be allow
<field name="name">Internet Expense</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.IE.amount</field>
<field name="amount_python_compute">result = inputs.IE and inputs.IE.amount</field>
<field name="sequence" eval="39"/>
<field name="note">Employer may also provide reimbursement of internet expenses and thus this would become non taxable.</field>
</record>
@@ -463,7 +463,7 @@ or - (contract.wage * contract.voluntary_provident_fund / 100))</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = - (inputs.LAI.amount)</field>
<field name="amount_python_compute">result = inputs.LAI and - (inputs.LAI.amount)</field>
<field name="register_id" ref="hr_leave_availed_register"/>
<field name="sequence" eval="180"/>
</record>
+5 -8
View File
@@ -179,20 +179,17 @@ tag_lu_177,I.B.5. Tabacs fabriqués,taxes
tag_lu_178,Base - Vente Biens Tabacs - Extracommunautaire,taxes
tag_lu_179,Base - Vente Biens Tabacs - Intracommunautaire,taxes
tag_lu_180,Base - Vente Biens Tabacs - Pays,taxes
tag_lu_181,I.B.6.a) Livraisons subséquentes à des acquisitions intracommunautaires dans
le cadre d'opérations triangulaires, lorsque le destinataire identifié à la TVA dans l'Etat membre de destination des biens y est le redevable de la taxe (4),taxes
tag_lu_181,"I.B.6.a) Livraisons subséquentes à des acquisitions intracommunautaires dans le cadre d'opérations triangulaires, lorsque le destinataire identifié à la TVA dans l'Etat membre de destination des biens y est le redevable de la taxe (4)",taxes
tag_lu_182,Base - Vente Biens – Triangulaire Intracommunautaire,taxes
tag_lu_183,I.B.6.d) Autres opérations réalisées (imposables) à l'étranger,taxes
tag_lu_184,Base - Vente Prestations - Extracommunautaire,taxes
tag_lu_185,I.B.6.c) Opérations réalisées dans le cadre du régime particulier de l'article 56sexies,taxes
tag_lu_186,I.B.7. Opérations à l'intérieur du pays pour lesquelles le preneur est le redevable,taxes
tag_lu_187,I.B.6.b)1) Prestations de services à des identifiés à la TVA dans un autre
Etat membre non exonérées dans l'Etat membre du preneur redevable (art.17/1/b) (5),taxes
tag_lu_187,I.B.6.b)1) Prestations de services à des identifiés à la TVA dans un autre Etat membre non exonérées dans l'Etat membre du preneur redevable (art.17/1/b) (5),taxes
tag_lu_188,Base - Vente Prestations - Intracommunautaire,taxes
tag_lu_189,I.B.6.b)2) Prestations de services à des identifiés à la TVA dans un autre
Etat membre exonérées dans l'Etat membre du preneur (art.17/1/b),taxes
tag_lu_189,I.B.6.b)2) Prestations de services à des identifiés à la TVA dans un autre Etat membre exonérées dans l'Etat membre du preneur (art.17/1/b),taxes
tag_lu_190,Base - Vente Prestations - Intracommunautaire exonérées dans l'état membre,taxes
tag_lu_191,I.B.1. Livraisons intracommunautaires de biens à des personnes identifiées à la TVA dans unautre Etat membre (art.43/1/d e et f) (3),taxes
tag_lu_191,I.B.1. Livraisons intracommunautaires de biens à des personnes identifiées à la TVA dans un autre Etat membre (art.43/1/d e et f) (3),taxes
tag_lu_192,Base - Vente Biens - Intracommunautaire,taxes
tag_lu_193,I.C. Chiffre d'affaires imposable,taxes
tag_lu_194,II.A. Ventilation du chiffre d'affaires imposable – base,taxes
@@ -598,4 +595,4 @@ tag_lu_594,Taxe - Investissement Prestations 17% - Intracommunautaire (-),taxes
tag_lu_595,Taxe - Investissement Prestations 3% - Intracommunautaire (-),taxes
tag_lu_596,Taxe - Investissement Prestations 6% - Intracommunautaire (-),taxes
tag_lu_597,Taxe - Investissement Prestations 8% - Intracommunautaire (-),taxes
tag_lu_598,Base - Sans Taxe,taxes
tag_lu_598,Base - Sans Taxe,taxes
1 id name applicability
179 tag_lu_178 Base - Vente Biens Tabacs - Extracommunautaire taxes
180 tag_lu_179 Base - Vente Biens Tabacs - Intracommunautaire taxes
181 tag_lu_180 Base - Vente Biens Tabacs - Pays taxes
182 tag_lu_181 I.B.6.a) Livraisons subséquentes à des acquisitions intracommunautaires dans I.B.6.a) Livraisons subséquentes à des acquisitions intracommunautaires dans le cadre d'opérations triangulaires, lorsque le destinataire identifié à la TVA dans l'Etat membre de destination des biens y est le redevable de la taxe (4) taxes
le cadre d'opérations triangulaires lorsque le destinataire identifié à la TVA dans l'Etat membre de destination des biens y est le redevable de la taxe (4) taxes
183 tag_lu_182 Base - Vente Biens – Triangulaire Intracommunautaire taxes
184 tag_lu_183 I.B.6.d) Autres opérations réalisées (imposables) à l'étranger taxes
185 tag_lu_184 Base - Vente Prestations - Extracommunautaire taxes
186 tag_lu_185 I.B.6.c) Opérations réalisées dans le cadre du régime particulier de l'article 56sexies taxes
187 tag_lu_186 I.B.7. Opérations à l'intérieur du pays pour lesquelles le preneur est le redevable taxes
188 tag_lu_187 I.B.6.b)1) Prestations de services à des identifiés à la TVA dans un autre I.B.6.b)1) Prestations de services à des identifiés à la TVA dans un autre Etat membre non exonérées dans l'Etat membre du preneur redevable (art.17/1/b) (5) taxes
Etat membre non exonérées dans l'Etat membre du preneur redevable (art.17/1/b) (5) taxes
189 tag_lu_188 Base - Vente Prestations - Intracommunautaire taxes
190 tag_lu_189 I.B.6.b)2) Prestations de services à des identifiés à la TVA dans un autre I.B.6.b)2) Prestations de services à des identifiés à la TVA dans un autre Etat membre exonérées dans l'Etat membre du preneur (art.17/1/b) taxes
Etat membre exonérées dans l'Etat membre du preneur (art.17/1/b) taxes
191 tag_lu_190 Base - Vente Prestations - Intracommunautaire exonérées dans l'état membre taxes
192 tag_lu_191 I.B.1. Livraisons intracommunautaires de biens à des personnes identifiées à la TVA dans unautre Etat membre (art.43/1/d e et f) (3) I.B.1. Livraisons intracommunautaires de biens à des personnes identifiées à la TVA dans un autre Etat membre (art.43/1/d e et f) (3) taxes
193 tag_lu_192 Base - Vente Biens - Intracommunautaire taxes
194 tag_lu_193 I.C. Chiffre d'affaires imposable taxes
195 tag_lu_194 II.A. Ventilation du chiffre d'affaires imposable – base taxes
595 tag_lu_595 Taxe - Investissement Prestations 3% - Intracommunautaire (-) taxes
596 tag_lu_596 Taxe - Investissement Prestations 6% - Intracommunautaire (-) taxes
597 tag_lu_597 Taxe - Investissement Prestations 8% - Intracommunautaire (-) taxes
598 tag_lu_598 Base - Sans Taxe taxes
+1
View File
@@ -18,4 +18,5 @@ import res_config
import update
import ir_actions
import ir_autovacuum
import ir_model
import html2text
+14
View File
@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models
class IrModel(models.Model):
_inherit = 'ir.model'
def unlink(self):
# Delete followers for models that will be unlinked.
query = "DELETE FROM mail_followers WHERE res_model IN %s"
self.env.cr.execute(query, [tuple(self.mapped('model'))])
return super(IrModel, self).unlink()
+1 -1
View File
@@ -2130,7 +2130,7 @@ class MailThread(models.AbstractModel):
# add followers coming from res.users relational fields that are tracked
user_ids = [values[name] for name in user_field_lst if values.get(name)]
user_pids = [user.partner_id.id for user in self.env['res.users'].sudo().browse(user_ids)]
user_pids = [user.partner_id.id for user in self.env['res.users'].sudo().browse(user_ids) if user.partner_id.active]
for partner_id in user_pids:
new_partners.setdefault(partner_id, None)
+4 -2
View File
@@ -103,9 +103,11 @@
<field name="name">Work Orders Performance</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">mrp.workorder</field>
<field name="domain">[('state','=','done')]</field>
<field name="domain">[]</field>
<field name="context">{'search_default_done': True}</field>
<field name="view_type">form</field>
<field name="view_mode">graph,pivot,tree,form,gantt</field>
<field name="search_view_id" ref="view_mrp_production_work_order_search"/>
</record>
<!-- Workcenter Kanban view-->
@@ -567,4 +569,4 @@
groups="group_mrp_routings"
sequence="12"/>
</data>
</odoo>
</odoo>
+2 -2
View File
@@ -201,7 +201,7 @@
<tree>
<field name="date_start"/>
<field name="date_end"/>
<field name="duration" widget="float_time"/>
<field name="duration" widget="float_time" sum="Total duration"/>
<field name="user_id"/>
<field name="loss_id" string="Efficiency"/>
</tree>
@@ -459,4 +459,4 @@
<field name="view_id" ref="view_work_center_load_graph"/>
<field name="act_window_id" ref="action_mrp_workcenter_load_report_graph"/>
</record>
</odoo>
</odoo>
+1 -1
View File
@@ -203,7 +203,7 @@ exports.PosModel = Backbone.Model.extend({
},{
model: 'account.tax',
fields: ['name','amount', 'price_include', 'include_base_amount', 'amount_type', 'children_tax_ids'],
domain: null,
domain: function(self) {return [['company_id', '=', self.company && self.company.id || false]]},
loaded: function(self, taxes){
self.taxes = taxes;
self.taxes_by_id = {};
@@ -1977,6 +1977,7 @@ var PaymentScreenWidget = ScreenWidget.extend({
}
order.initialize_validation_date();
order.finalized = true;
if (order.is_to_invoice()) {
var invoiced = this.pos.push_and_invoice_order(order);
+1 -1
View File
@@ -106,7 +106,7 @@ class Pricelist(models.Model):
"""
self.ensure_one()
if not date:
date = self._context.get('date') or fields.Date.today()
date = self._context.get('date') or fields.Date.context_today(self)
if not uom_id and self._context.get('uom'):
uom_id = self._context['uom']
if uom_id:
+1 -1
View File
@@ -112,7 +112,7 @@ class AccountInvoiceLine(models.Model):
prod_moves = [m for m in moves if m.product_id.id == product_id]
prod_qty_done = factor * qty_done
prod_quantity = factor * quantity
average_price_unit += self._compute_average_price(prod_qty_done, prod_quantity, prod_moves)
average_price_unit += factor * self._compute_average_price(prod_qty_done, prod_quantity, prod_moves)
price_unit = average_price_unit or price_unit
price_unit = self.product_id.uom_id._compute_price(price_unit, self.uom_id)
return price_unit
+16 -6
View File
@@ -35,8 +35,17 @@ class StockHistory(models.Model):
group_lines.setdefault(str(domain), self.search(domain))
stock_history |= group_lines[str(domain)]
# get data of stock_history in one shot to speed things up (the view can be very slow)
stock_history_data = {}
if stock_history:
self._cr.execute("""SELECT id, product_id, price_unit_on_quant, company_id, quantity
FROM stock_history WHERE id in %s""", (tuple(stock_history.ids),))
stock_history_data = {line['id']: line for line in self._cr.dictfetchall()}
histories_dict = {}
not_real_cost_method_products = stock_history.mapped('product_id').filtered(lambda product: product.cost_method != 'real')
not_real_cost_method_products = self.env['product.product'].browse(
record['product_id'] for record in stock_history_data.values()
).filtered(lambda product: product.cost_method != 'real')
if not_real_cost_method_products:
self._cr.execute("""SELECT DISTINCT ON (product_id, company_id) product_id, company_id, cost
FROM product_price_history
@@ -48,12 +57,13 @@ class StockHistory(models.Model):
for line in res:
inv_value = 0.0
for stock_history in group_lines.get(str(line.get('__domain', domain))):
product = stock_history.product_id
if product.cost_method == 'real':
price = stock_history.price_unit_on_quant
history_data = stock_history_data[stock_history.id]
product_id = history_data['product_id']
if self.env['product.product'].browse(product_id).cost_method == 'real':
price = history_data['price_unit_on_quant']
else:
price = histories_dict.get((product.id, stock_history.company_id.id), 0.0)
inv_value += price * stock_history.quantity
price = histories_dict.get((product_id, history_data['company_id']), 0.0)
inv_value += price * history_data['quantity']
line['inventory_value'] = inv_value
return res
+1 -1
View File
@@ -586,7 +586,7 @@ class WebClient(http.Controller):
def version_info(self):
return odoo.service.common.exp_version()
@http.route('/web/tests', type='http', auth="none")
@http.route('/web/tests', type='http', auth="user")
def index(self, mod=None, **kwargs):
return request.render('web.qunit_suite')
+6 -1
View File
@@ -385,6 +385,10 @@ var ActionManager = Widget.extend({
return this.inner_widget;
},
history_back: function() {
if (this.dialog) {
this.dialog_stop();
return;
}
var nb_views = this.inner_action.get_nb_views();
if (nb_views > 1) {
// Stay on this action, but select the previous view
@@ -861,7 +865,7 @@ var ActionManager = Widget.extend({
});
});
},
ir_actions_act_url: function (action) {
ir_actions_act_url: function (action, options) {
var url = action.url;
if (session.debug && url && url.length && url[0] === '/') {
url = $.param.querystring(url, {debug: session.debug});
@@ -872,6 +876,7 @@ var ActionManager = Widget.extend({
return $.Deferred(); // The action is finished only when the redirection is done
} else {
window.open(url, '_blank');
options.on_close();
}
return $.when();
},
+13 -2
View File
@@ -5,7 +5,18 @@ var translation = require('web.translation');
var _t = translation._t;
function QWeb(debug, default_dict) {
/**
* @param {boolean} debug
* @param {Object} default_dict
* @param {boolean} [enableTranslation=true] if true (this is the default),
* the rendering will translate all strings that are not marked with
* t-translation=off. This is useful for the kanban view, which uses a
* template which is already translated by the server
*/
function QWeb(debug, default_dict, enableTranslation) {
if (enableTranslation === undefined) {
enableTranslation = true;
}
var qweb = new QWeb2.Engine();
qweb.default_dict = _.extend({}, default_dict || {}, {
'_' : _,
@@ -16,7 +27,7 @@ function QWeb(debug, default_dict) {
'csrf_token': odoo.csrf_token,
});
qweb.debug = debug;
qweb.preprocess_node = preprocess_node;
qweb.preprocess_node = enableTranslation ? preprocess_node : function () {};
return qweb;
}
+5 -8
View File
@@ -32,14 +32,11 @@ data.dom_ready = dom_ready;
var all_ready;
data.ready = function () {
if (!all_ready) {
all_ready = $.when(dom_ready, ajax.loadXML()).then(function () {
// TODO find a better way to find if we are in the backend or not
// We don't load translation if we are in the backend since it's already done by the webclient
if (!$(document).find('.o_web_client').length) {
return load_translations();
}
});
} else if(all_ready.state() === "resolved") { // can add async template
all_ready = $.when(dom_ready, ajax.loadXML());
if (!odoo._modules) {
all_ready.then(load_translations);
}
} else { // can add async template
all_ready = $.when(dom_ready, ajax.loadXML());
}
return all_ready;
+51 -20
View File
@@ -19,6 +19,57 @@ var editor = eventHandler.modules.editor;
var renderer = $.summernote.renderer;
var options = $.summernote.options;
// Browser-unify execCommand
var oldJustify = {};
_.each(['Left', 'Right', 'Full', 'Center'], function (align) {
oldJustify[align] = editor['justify' + align];
editor['justify' + align] = function ($editable, value) {
// Before calling the standard function, check all elements which have
// an 'align' attribute and mark them with their value
var $align = $editable.find('[align]');
_.each($align, function (el) {
var $el = $(el);
$el.data('__align', $el.attr('align'));
});
// Call the standard function
oldJustify[align].apply(this, arguments);
// Then:
// Remove the text-align of elements which lost the 'align' attribute
var $newAlign = $editable.find('[align]');
$align.not($newAlign).css('text-align', '');
// Transform the 'align' attribute into the 'text-align' css
// property for elements which received the 'align' attribute or whose
// 'align' attribute changed
_.each($newAlign, function (el) {
var $el = $(el);
var oldAlignValue = $align.data('__align');
var alignValue = $el.attr('align');
if (oldAlignValue === alignValue) {
// If the element already had an 'align' attribute and that it
// did not changed, do nothing (compatibility)
return;
}
$el.removeAttr('align');
$el.css('text-align', alignValue);
// Note the first step (removing the text-align of elemnts which
// lost the 'align' attribute) is kinda the same as this one, but
// this one handles the elements which have been edited with chrome
// or with this new system
$el.find('*').css('text-align', '');
});
// Unmark the elements
$align.removeData('__align');
};
});
//////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Add method to Summernote*/
@@ -2319,26 +2370,6 @@ eventHandler.modules.popover.update = function ($popover, oStyle, isAirMode) {
}
};
// override summernote clipboard functionality
eventHandler.modules.clipboard.attach = function(layoutInfo) {
var $editable = layoutInfo.editable();
$editable.on('paste', function(e) {
var clipboardData = ((e.originalEvent || e).clipboardData || window.clipboardData);
// Change nothing if pasting html (copy from text editor / web / ...) or
// if clipboardData is not available (IE / ...)
if (clipboardData && clipboardData.types && clipboardData.types.length === 1 && clipboardData.types[0] === "text/plain") {
e.preventDefault();
$editable.data('NoteHistory').recordUndo($editable); // FIXME
var pastedText = clipboardData.getData("text/plain");
// Try removing linebreaks which are not really linebreaks (in a PDF,
// when a sentence goes over the next line, copying it considers it
// a linebreak for example).
var formattedText = pastedText.replace(/([\w-])\r?\n([\w-])/g, "$1 $2").trim();
document.execCommand("insertText", false, formattedText);
}
});
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
var fn_attach = eventHandler.attach;
@@ -60,7 +60,7 @@ var KanbanView = View.extend({
init: function () {
this._super.apply(this, arguments);
this.qweb = new QWeb(session.debug, {_s: session.origin});
this.qweb = new QWeb(session.debug, {_s: session.origin}, false);
this.limit = this.options.limit || parseInt(this.fields_view.arch.attrs.limit, 10) || 40;
this.fields = this.fields_view.fields;
@@ -67,11 +67,18 @@ var PlannerDialog = Dialog.extend({
* Fetch the planner's rendered template
*/
willStart: function() {
var context = session.user_context;
// fallback context for frontend
if(_.isEmpty(context)) {
context = {
lang: (document.documentElement.getAttribute('lang')||'').replace('-', '_'),
};
}
var def = (new Model('web.planner')).call('render', [
this.planner.view_id[0],
this.planner.planner_application
], {
context: session.user_context
context: context
}).then((function (template) {
this.$template = $(template);
}).bind(this));
@@ -168,7 +168,7 @@ odoo.define('website_sale.website_sale', function (require) {
}
else {
$q.parents('li:first').addClass("hidden");
$('a[href^="/shop/checkout"]').addClass("hidden");
$('a[href*="/shop/checkout"]').addClass("hidden");
}
$q.html(data.cart_quantity).hide().fadeIn(600);
+1
View File
@@ -12,3 +12,4 @@ List of contributors:
Laurent Destailleur ldestailleur@teclib.com https://github.com/eldy
David Halgand dhalgand@teclib.com https://github.com/halgandd
Guillaume Masson gmasson@teclib.com https://github.com/metaminux
+7
View File
@@ -280,6 +280,13 @@ class Users(models.Model):
if any(user.company_ids and user.company_id not in user.company_ids for user in self):
raise ValidationError(_('The chosen company is not in the allowed companies for this user'))
@api.multi
@api.constrains('action_id')
def _check_action_id(self):
action_open_website = self.env.ref('base.action_open_website', raise_if_not_found=False)
if action_open_website and any(user.action_id.id == action_open_website.id for user in self):
raise ValidationError(_('The "App Switcher" action cannot be selected as home action.'))
@api.multi
def read(self, fields=None, load='_classic_read'):
if fields and self == self.env.user: