Skip to content
Permalink
Browse files

[MERGE] forward port branch 12.0 up to 84143a3

  • Loading branch information...
KangOl committed Feb 21, 2019
2 parents f945b1b + 84143a3 commit 1d2b6f1bef6af13245d29d56cbb5f9d61f9ca038
Showing with 4,357 additions and 1,730 deletions.
  1. +1 −1 addons/account/models/account.py
  2. +4 −1 addons/account/models/account_bank_statement.py
  3. +141 −88 addons/account/models/account_move.py
  4. +2 −0 addons/account/models/account_payment.py
  5. +1 −1 addons/account/models/chart_template.py
  6. +1 −1 addons/account/security/ir.model.access.csv
  7. +2 −2 addons/account/static/src/js/reconciliation/reconciliation_model.js
  8. +1 −1 addons/account/static/src/js/reconciliation/reconciliation_renderer.js
  9. +2 −1 addons/account/static/src/xml/account_reconciliation.xml
  10. +6 −0 addons/account/tests/account_test_no_chart.py
  11. +8 −0 addons/account/tests/test_reconciliation.py
  12. +0 −1 addons/account/views/res_config_settings_views.xml
  13. +9 −10 addons/account_facturx/models/account_invoice.py
  14. +32 −3 addons/account_voucher/models/account_voucher.py
  15. +1 −1 addons/auth_signup/models/res_partner.py
  16. +0 −3 addons/base_automation/views/base_automation_view.xml
  17. +1 −0 addons/base_import_module/views/base_import_module_view.xml
  18. +1 −0 addons/bus/static/src/js/longpolling_bus.js
  19. +1 −1 addons/crm/models/crm_lead.py
  20. +0 −2 addons/crm/views/crm_lead_views.xml
  21. +3 −2 addons/digest/data/digest_template_data.xml
  22. +1 −1 addons/digest/models/digest.py
  23. +3 −1 addons/google_calendar/models/google_calendar.py
  24. +11 −0 addons/hr/views/hr_views.xml
  25. +4 −6 addons/hr_attendance/static/src/js/kiosk_confirm.js
  26. +2 −3 addons/hr_attendance/static/src/js/my_attendances.js
  27. +4 −1 addons/hr_holidays/models/hr_leave_type.py
  28. +7 −7 addons/hr_payroll_account/models/hr_payroll_account.py
  29. +137 −334 addons/l10n_ch/i18n_extra/de.po
  30. +111 −501 addons/l10n_ch/i18n_extra/it.po
  31. +106 −477 addons/l10n_ch/i18n_extra/l10n_ch.pot
  32. +1 −1 addons/l10n_it/__manifest__.py
  33. +5 −0 addons/l10n_it_edi/__init__.py
  34. +22 −0 addons/l10n_it_edi/__manifest__.py
  35. +23 −0 addons/l10n_it_edi/data/account_invoice_demo.xml
  36. +175 −0 addons/l10n_it_edi/data/invoice_it_template.xml
  37. +8 −0 addons/l10n_it_edi/models/__init__.py
  38. +752 −0 addons/l10n_it_edi/models/account_invoice.py
  39. +21 −0 addons/l10n_it_edi/models/ddt.py
  40. +358 −0 addons/l10n_it_edi/models/ir_mail_server.py
  41. +110 −0 addons/l10n_it_edi/models/res_company.py
  42. +28 −0 addons/l10n_it_edi/models/res_partner.py
  43. +2 −0 addons/l10n_it_edi/security/ir.model.access.csv
  44. +2 −0 addons/l10n_it_edi/tests/__init__.py
  45. +32 −0 addons/l10n_it_edi/tests/test_generate.py
  46. +265 −0 addons/l10n_it_edi/views/l10n_it_view.xml
  47. +4 −0 addons/l10n_mx/data/account_data.xml
  48. +34 −0 addons/l10n_mx/data/account_tax_data.xml
  49. +3 −1 addons/mail/data/mail_data.xml
  50. +1 −1 addons/mail/models/mail_message.py
  51. +3 −1 addons/mail/models/mail_thread.py
  52. +7 −2 addons/mail/static/src/js/chatter.js
  53. +1 −0 addons/mail/static/src/js/thread_widget.js
  54. +7 −1 addons/mail/static/src/xml/chatter.xml
  55. +6 −0 addons/mass_mailing/models/mass_mailing.py
  56. +1 −1 addons/note/static/src/js/systray_activity_menu.js
  57. +0 −1 addons/note/static/tests/systray_activity_menu_tests.js
  58. +4 −6 addons/point_of_sale/models/pos_order.py
  59. +2 −0 addons/point_of_sale/models/pos_session.py
  60. +4 −2 addons/point_of_sale/static/src/js/gui.js
  61. +2 −2 addons/point_of_sale/static/src/js/screens.js
  62. +5 −1 addons/point_of_sale/views/pos_templates.xml
  63. +10 −0 addons/portal/models/portal_mixin.py
  64. +5 −5 addons/portal/wizard/portal_share.py
  65. +12 −2 addons/project/models/project.py
  66. +0 −5 addons/project/static/src/js/tour.js
  67. +2 −0 addons/purchase_requisition/data/purchase_requisition_data.xml
  68. +7 −1 addons/sale/models/sale.py
  69. +1 −1 addons/sale_crm/models/crm_lead.py
  70. +1 −1 addons/sale_margin/models/sale_order.py
  71. +6 −0 addons/sale_quotation_builder/views/sale_portal_templates.xml
  72. +1 −1 addons/sale_stock/views/sale_stock_portal_template.xml
  73. +3 −1 addons/stock/models/product.py
  74. +4 −8 addons/stock/report/report_deliveryslip.xml
  75. +2 −5 addons/stock/views/stock_picking_views.xml
  76. +1 −1 addons/test_mail/tests/test_performance.py
  77. +4 −0 addons/test_website/__init__.py
  78. +24 −0 addons/test_website/__manifest__.py
  79. +4 −0 addons/test_website/controllers/__init__.py
  80. +13 −0 addons/test_website/controllers/main.py
  81. +54 −0 addons/test_website/data/test_website_data.xml
  82. +103 −0 addons/test_website/static/src/js/reset_views.test.js
  83. +4 −0 addons/test_website/tests/__init__.py
  84. +102 −0 addons/test_website/tests/test_reset_views.py
  85. +8 −0 addons/test_website/views/templates.xml
  86. +15 −5 addons/web/static/lib/moment/locale/es.js
  87. +11 −0 addons/web/static/src/js/core/abstract_storage_service.js
  88. +11 −1 addons/web/static/src/js/core/utils.js
  89. +1 −0 addons/web/static/src/js/fields/basic_fields.js
  90. +1 −1 addons/web/static/src/js/views/control_panel/search/search_filters.js
  91. +4 −0 addons/web/static/src/js/views/graph/graph_renderer.js
  92. +5 −3 addons/web/static/src/js/views/pivot/pivot_model.js
  93. +2 −1 addons/web/static/src/js/views/pivot/pivot_renderer.js
  94. +4 −0 addons/web/static/src/scss/form_view.scss
  95. +1 −1 addons/web/static/src/xml/base.xml
  96. +1 −0 addons/web/static/tests/chrome/user_menu_tests.js
  97. +21 −1 addons/web/static/tests/core/util_tests.js
  98. +21 −3 addons/web/static/tests/core/widget_tests.js
  99. +5 −0 addons/web/static/tests/helpers/test_utils_mock.js
  100. +2 −0 addons/web/static/tests/views/abstract_controller_tests.js
  101. +107 −1 addons/web/static/tests/views/pivot_tests.js
  102. +9 −6 addons/web_editor/models/ir_ui_view.py
  103. +2 −2 addons/web_editor/static/src/scss/web_editor.ui.scss
  104. +21 −17 addons/web_editor/static/src/scss/web_editor.variables.scss
  105. +4 −4 addons/web_editor/static/src/xml/editor.xml
  106. +24 −12 addons/website/controllers/main.py
  107. +50 −18 addons/website/models/ir_http.py
  108. +19 −0 addons/website/models/ir_ui_view.py
  109. +7 −0 addons/website/models/res_partner.py
  110. +72 −3 addons/website/models/website.py
  111. +181 −0 addons/website/static/src/js/tours/website_tour_reset_password.js
  112. +6 −2 addons/website/static/src/scss/website.ui.scss
  113. +2 −2 addons/website/static/src/xml/website.pageProperties.xml
  114. +2 −0 addons/website/tests/__init__.py
  115. +114 −0 addons/website/tests/test_get_current_website.py
  116. +76 −0 addons/website/tests/test_views.py
  117. +34 −0 addons/website/tests/test_website_reset_password.py
  118. +73 −56 addons/website/views/website_templates.xml
  119. +1 −1 addons/website_crm_partner_assign/controllers/main.py
  120. +3 −3 addons/website_crm_partner_assign/views/website_crm_partner_assign_templates.xml
  121. +10 −10 addons/website_event_track/models/event.py
  122. +1 −1 addons/website_sale/data/mail_template_data.xml
  123. +8 −1 addons/website_sale/models/account_invoice.py
  124. +8 −0 addons/website_sale/models/sale_order.py
  125. +93 −0 addons/website_sale/static/src/js/website_sale_tour_shop_cart_recovery.js
  126. +94 −0 addons/website_sale/static/src/js/website_sale_tour_shop_mail.js
  127. +1 −1 addons/website_sale/static/src/scss/website_sale.scss
  128. +2 −0 addons/website_sale/tests/__init__.py
  129. +13 −0 addons/website_sale/tests/test_website_sale_cart_recovery.py
  130. +24 −0 addons/website_sale/tests/test_website_sale_mail.py
  131. +3 −1 addons/website_sale/views/templates.xml
  132. +4 −2 addons/website_sale_delivery/static/src/js/website_sale_delivery.js
  133. +1 −1 addons/website_sale_stock/views/website_sale_stock_templates.xml
  134. +2 −1 doc/cla/corporate/invitu.md
  135. +1 −0 doc/cla/corporate/vauxoo.md
  136. +11 −0 doc/cla/individual/naglis.md
  137. +32 −0 doc/reference/reports.rst
  138. +3 −1 odoo/addons/base/data/res.lang.csv
  139. +4 −1 odoo/addons/base/models/ir_actions_report.py
  140. +10 −8 odoo/addons/base/models/ir_ui_view.py
  141. +1 −1 odoo/addons/base/models/res_country.py
  142. +6 −0 odoo/addons/base/models/res_partner.py
  143. +60 −0 odoo/addons/base/tests/test_views.py
  144. +50 −0 odoo/addons/test_new_api/tests/test_new_fields.py
  145. +12 −1 odoo/addons/test_testing_utilities/menu.xml
  146. +2 −3 odoo/addons/test_testing_utilities/models.py
  147. +14 −12 odoo/addons/test_testing_utilities/tests/test_form_impl.py
  148. +7 −2 odoo/api.py
  149. +18 −4 odoo/fields.py
  150. +42 −20 odoo/models.py
  151. +46 −15 odoo/tests/common.py
@@ -481,7 +481,7 @@ def _get_bank_statements_available_sources(self):
post_at_bank_rec = fields.Boolean(string="Post At Bank Reconciliation", help="Whether or not the payments made in this journal should be generated in draft state, so that the related journal entries are only posted when performing bank reconciliation.")

# alias configuration for 'purchase' type journals
alias_id = fields.Many2one('mail.alias', string='Alias')
alias_id = fields.Many2one('mail.alias', string='Alias', copy=False)
alias_domain = fields.Char('Alias domain', compute='_compute_alias_domain', default=lambda self: self.env["ir.config_parameter"].sudo().get_param("mail.catchall.domain"))
alias_name = fields.Char('Alias Name for Vendor Bills', related='alias_id.alias_name', help="It creates draft vendor bill by sending an email.", readonly=False)

@@ -587,8 +587,11 @@ def process_reconciliation(self, counterpart_aml_dicts=None, payment_aml_rec=Non

# Fully reconciled moves are just linked to the bank statement
total = self.amount
currency = self.currency_id or statement_currency
for aml_rec in payment_aml_rec:
total -= aml_rec.debit - aml_rec.credit
balance = aml_rec.amount_currency if aml_rec.currency_id else aml_rec.balance
aml_currency = aml_rec.currency_id or aml_rec.company_currency_id
total -= aml_currency._convert(balance, currency, aml_rec.company_id, aml_rec.date)
aml_rec.with_context(check_move_validity=False).write({'statement_line_id': self.id})
counterpart_moves = (counterpart_moves | aml_rec.move_id)
if aml_rec.journal_id.post_at_bank_rec and aml_rec.payment_id and aml_rec.move_id.state == 'draft':

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -211,6 +211,8 @@ def _onchange_currency(self):
self.amount = abs(self._compute_payment_amount())

# Set by default the first liquidity journal having this currency if exists.
if self.journal_id:
return
journal = self.env['account.journal'].search(
[('type', 'in', ('bank', 'cash')), ('currency_id', '=', self.currency_id.id)], limit=1)
if journal:
@@ -173,7 +173,7 @@ def try_loading_for_current_company(self):
# (won't work well for multi-company)
company = self.env.user.company_id
# If we don't have any chart of account on this company, install this chart of account
if not self.existing_accounting(company):
if not company.chart_template_id and not self.existing_accounting(company):
self.load_for_current_company(15.0, 15.0)

def load_for_current_company(self, sale_tax_rate, purchase_tax_rate):
@@ -68,7 +68,7 @@ access_account_account_type_invoice,account.account.type invoice,model_account_a
access_account_account_tax,account.account.tag,model_account_account_tag,account.group_account_user,1,1,1,1
access_account_account_tax_user,account.account.tag,model_account_account_tag,account.group_account_invoice,1,0,0,0
access_account_reconcile_model,account.reconcile.model,model_account_reconcile_model,account.group_account_user,1,1,1,1
access_account_reconcile_model_template,account.reconcile.model.template,model_account_reconcile_model_template,account.group_account_user,1,1,1,1
access_account_reconcile_model_template,account.reconcile.model.template,model_account_reconcile_model_template,account.group_account_invoice,1,1,1,1
access_account_partial_reconcile_group_invoice,account.partial.reconcile.group.invoice,model_account_partial_reconcile,account.group_account_invoice,1,1,1,0
access_account_partial_reconcile,account.partial.reconcile,model_account_partial_reconcile,account.group_account_user,1,1,1,1
access_account_full_reconcile_group_invoice,account.full.reconcile.group.invoice,model_account_full_reconcile,account.group_account_invoice,1,1,1,0
@@ -904,11 +904,11 @@ var StatementModel = BasicModel.extend({
});
var company_currency = session.get_currency(line.st_line.currency_id);
var company_precision = company_currency && company_currency.digits[1] || 2;
total = utils.round_decimals(total*1000, company_precision)/1000 || 0;
total = utils.round_decimals(total, company_precision) || 0;
if(isOtherCurrencyId){
var other_currency = session.get_currency(isOtherCurrencyId);
var other_precision = other_currency && other_currency.digits[1] || 2;
amount_currency = utils.round_decimals(amount_currency, other_precision)
amount_currency = utils.round_decimals(amount_currency, other_precision);
}
line.balance = {
amount: total,
@@ -260,7 +260,7 @@ var LineRenderer = Widget.extend(FieldManagerMixin, {
'click .accounting_view thead td': '_onTogglePanel',
'click .accounting_view tfoot td:not(.cell_left,.cell_right)': '_onShowPanel',
'click .cell': '_onEditAmount',
'input input.filter': '_onFilterChange',
'change input.filter': '_onFilterChange',
'click .match .load-more a': '_onLoadMore',
'click .match .mv_line td': '_onSelectMoveLine',
'click .accounting_view tbody .mv_line td': '_onSelectProposition',
@@ -144,7 +144,8 @@

<div t-name="reconciliation.line.match">
<div class="match_controls">
<input class="filter" placeholder="Filter..." type="text" value=""/>
<input class="filter o_input" placeholder="Filter..." type="text" value=""/>
<button class="btn btn-secondary btn-sm fa fa-search" type="button"></button>
</div>
<table>
<tbody>
@@ -46,6 +46,12 @@ def setUpClass(cls):
'property_account_receivable_id': cls.account_receivable.id,
})

cls.sale_journal0 = cls.env['account.journal'].create({
'name': 'Sale Journal',
'type': 'sale',
'code': 'SJT0',
})

@classmethod
def setUpAdditionalAccounts(cls):
""" Set up some addionnal accounts: expenses, revenue, ... """
@@ -529,6 +529,14 @@ def test_reconcile_bank_statement_with_payment_and_writeoff(self):
self.diff_income_account.id: {'debit': 0.0, 'credit': 3.27, 'amount_currency': -5, 'currency_id': self.currency_usd_id},
self.account_rcv.id: {'debit': 0.0, 'credit': 52.33, 'amount_currency': -80, 'currency_id': self.currency_usd_id},
}

payments = bank_stmt_aml.mapped('payment_id')
# creation and reconciliation of the over-amount statement
# has created an another payment
self.assertEqual(len(payments), 2)
# Check amount of second, automatically created payment
self.assertEqual((payments - payment).amount, 5)

for aml in bank_stmt_aml:
line = lines[aml.account_id.id]
if type(line) == list:
@@ -96,7 +96,6 @@
</div>
<div class="o_setting_right_pane" name="account_taxcloud_right_pane">
<label for="module_account_taxcloud" string="TaxCloud"/>
<span class="fa fa-lg fa-building-o" title="Values set here are company-specific." aria-label="Values set here are company-specific." groups="base.group_multi_company" role="img"/>
<div class="text-muted">
Compute tax rates based on U.S. ZIP codes
</div>
@@ -64,12 +64,11 @@ def _import_facturx_invoice(self, tree):
with Form(self_ctx, view='account.invoice_supplier_form') as invoice_form:

# Partner (first step to avoid warning 'Warning! You must first select a partner.').
elements = tree.xpath('//ram:SellerTradeParty/ram:Name', namespaces=tree.nsmap)
partner_name = elements and elements[0].text

elements = tree.xpath('//ram:SellerTradeParty/ram:SpecifiedTaxRegistration/ram:ID', namespaces=tree.nsmap)
partner = elements and self.env['res.partner'].search([('vat', '=', elements[0].text)], limit=1)
if not partner:
elements = tree.xpath('//ram:SellerTradeParty/ram:Name', namespaces=tree.nsmap)
partner_name = elements and elements[0].text
partner = elements and self.env['res.partner'].search([('name', 'ilike', partner_name)], limit=1)
if not partner:
elements = tree.xpath('//ram:SellerTradeParty//ram:URIID[@schemeID=\'SMTP\']', namespaces=tree.nsmap)
@@ -161,19 +160,19 @@ def _import_facturx_invoice(self, tree):
if product:
invoice_line_form.product_id = product

# Quantity.
line_elements = element.xpath('.//ram:SpecifiedLineTradeDelivery/ram:BilledQuantity', namespaces=tree.nsmap)
if line_elements:
invoice_line_form.quantity = float(line_elements[0].text) * refund_sign

# Price Unit.
line_elements = element.xpath('.//ram:GrossPriceProductTradePrice/ram:ChargeAmount', namespaces=tree.nsmap)
if line_elements:
invoice_line_form.price_unit = float(line_elements[0].text)
invoice_line_form.price_unit = float(line_elements[0].text) / invoice_line_form.quantity
else:
line_elements = element.xpath('.//ram:NetPriceProductTradePrice/ram:ChargeAmount', namespaces=tree.nsmap)
if line_elements:
invoice_line_form.price_unit = float(line_elements[0].text)

# Quantity.
line_elements = element.xpath('.//ram:SpecifiedLineTradeDelivery/ram:BilledQuantity', namespaces=tree.nsmap)
if line_elements:
invoice_line_form.quantity = float(line_elements[0].text) * refund_sign
invoice_line_form.price_unit = float(line_elements[0].text) / invoice_line_form.quantity

# Discount.
line_elements = element.xpath('.//ram:AppliedTradeAllowanceCharge/ram:CalculationPercent', namespaces=tree.nsmap)
@@ -274,6 +274,8 @@ def voucher_move_line_create(self, line_total, move_id, company_currency, curren
:return: Tuple build as (remaining amount not allocated on voucher lines, list of account_move_line created in this method)
:rtype: tuple(float, list of int)
'''
tax_calculation_rounding_method = self.env.user.company_id.tax_calculation_rounding_method
tax_lines_vals = []
for line in self.line_ids:
#create one move line per voucher line where amount is not 0.0
if not line.price_subtotal:
@@ -331,6 +333,33 @@ def voucher_move_line_create(self, line_total, move_id, company_currency, curren
self.env['account.move.line'].create(temp)

self.env['account.move.line'].create(move_line)
# When global rounding is activated, we must wait until all tax lines are computed to
# merge them.
if tax_calculation_rounding_method == 'round_globally':
tax_lines_vals += self.env['account.move.line'].with_context(round=False)._apply_taxes(
move_line,
move_line.get('debit', 0.0) - move_line.get('credit', 0.0)
)

# When round globally is set, we merge the tax lines
if tax_calculation_rounding_method == 'round_globally':
tax_lines_vals_merged = {}
for tax_line_vals in tax_lines_vals:
key = (
tax_line_vals['tax_line_id'],
tax_line_vals['account_id'],
tax_line_vals['analytic_account_id'],
)
if key not in tax_lines_vals_merged:
tax_lines_vals_merged[key] = tax_line_vals
else:
tax_lines_vals_merged[key]['debit'] += tax_line_vals['debit']
tax_lines_vals_merged[key]['credit'] += tax_line_vals['credit']
currency = self.env['res.currency'].browse(company_currency)
for vals in tax_lines_vals_merged.values():
vals['debit'] = currency.round(vals['debit'])
vals['credit'] = currency.round(vals['credit'])
self.env['account.move.line'].create(vals)
return line_total

@api.multi
@@ -363,12 +392,12 @@ def action_move_line_create(self):
line_total = voucher.with_context(ctx).voucher_move_line_create(line_total, move.id, company_currency, current_currency)

# Create a payment to allow the reconciliation when pay_now = 'pay_now'.
if self.pay_now == 'pay_now':
payment_id = self.env['account.payment'].create(self.voucher_pay_now_payment_create())
if voucher.pay_now == 'pay_now':
payment_id = self.env['account.payment'].create(voucher.voucher_pay_now_payment_create())
payment_id.post()

# Reconcile the receipt with the payment
lines_to_reconcile = (payment_id.move_line_ids + move.line_ids).filtered(lambda l: l.account_id == self.account_id)
lines_to_reconcile = (payment_id.move_line_ids + move.line_ids).filtered(lambda l: l.account_id == voucher.account_id)
lines_to_reconcile.reconcile()

# Add tax correction to move line if any tax correction specified
@@ -53,8 +53,8 @@ def _get_signup_url_for_action(self, action=None, view_type=None, menu_id=None,
the url state components (menu_id, id, view_type) """

res = dict.fromkeys(self.ids, False)
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
for partner in self:
base_url = partner.get_base_url()
# when required, make sure the partner has a valid signup token
if self.env.context.get('signup_valid') and not partner.user_ids:
partner.sudo().signup_prepare()
@@ -11,9 +11,6 @@
<xpath expr="//button[@name='create_action']" position="replace">
</xpath>
<xpath expr="//button[@name='unlink_action']" position="replace">
<button name="unlink_action_for_menu" string="Remove Action" type="object"
attrs="{'invisible':[('binding_model_id','=',False)]}"
help="Remove the contextual action related to this server action"/>
</xpath>
<div class="oe_title" position="before">
<div class="oe_button_box" name="button_box">
@@ -8,6 +8,7 @@
<form string="Import module">
<field name="state" invisible="1"/>
<separator string="Import Module" colspan="4"/>
<p class="alert alert-warning" role="alert">Note: you can only import data modules (.xml files and static assets)</p>
<group states="init" col="4">
<label for="module_file" string="Select module package to import (.zip file):" colspan="4"/>
<field name="module_file" colspan="4"/>
@@ -57,6 +57,7 @@ var LongpollingBus = Bus.extend(ServicesMixin, {
$(window).off("click." + this._id);
$(window).off("keydown." + this._id);
$(window).off("keyup." + this._id);
this._super();
},
//--------------------------------------------------------------------------
// Public
@@ -75,7 +75,7 @@ def _default_stage_id(self):
kanban_state = fields.Selection([('grey', 'No next activity planned'), ('red', 'Next activity late'), ('green', 'Next activity is planned')],
string='Kanban State', compute='_compute_kanban_state')
email_cc = fields.Text('Global CC', help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma")
description = fields.Text('Notes', track_visibility='onchange', track_sequence=60)
description = fields.Text('Notes')
tag_ids = fields.Many2many('crm.lead.tag', 'crm_lead_tag_rel', 'lead_id', 'tag_id', string='Tags', help="Classify and analyze your lead/opportunity categories like: Training, Service")
contact_name = fields.Char('Contact Name', track_visibility='onchange', track_sequence=30)
partner_name = fields.Char("Company Name", track_visibility='onchange', track_sequence=20, index=True, help='The name of the future partner company that will be created while converting the lead into opportunity')
@@ -969,7 +969,6 @@ for rec in records:
<field name="domain">[('type','=','opportunity')]</field>
<field name="context">{
'default_type': 'opportunity',
'default_user_id': uid
}
</field>
<field name="search_view_id" ref="crm.view_crm_case_opportunities_filter"/>
@@ -1031,7 +1030,6 @@ for rec in records:
<field name="domain">[('type','=','opportunity')]</field>
<field name="context">{
'default_type': 'opportunity',
'default_user_id': uid,
'search_default_assigned_to_me': 1
}</field>
<field name="search_view_id" ref="crm.view_crm_case_opportunities_filter"/>
@@ -10,7 +10,8 @@
<table style="width: 100%; border-spacing: 0; font-family: Helvetica,Arial,Verdana,sans-serif;">
<tr>
<td align="center" valign="top" style="border-collapse: collapse; padding: 0">
% set company, user = ctx['company'], ctx['user']
% set user = ctx.get('user', user)
% set company = user.company_id
% set data = object.compute_kpis(company, user)
% set tips = object.compute_tips(company, user)
% set kpi_actions = object.compute_kpis_actions(company, user)
@@ -136,7 +137,7 @@
<table style="margin-top: 5px; border: 1px solid #e7e7e7; font-size: 15px; width: 100%; max-width: 600px;">
<tr>
<td style="border-collapse: collapse; margin: 0; padding: 10px 20px;">
% if ctx['user'].has_group('base.group_system'):
% if user.has_group('base.group_system'):
<div style="margin-top: 20px;">
Want to customize the email?
<a href="/web#view_type=form&amp;model=digest.digest&amp;id=${object.id}" target="_blank" style="color: #875A7B;">Choose the metrics you care about</a>
@@ -101,7 +101,7 @@ def action_send(self):
for digest in self:
for user in digest.user_ids:
subject = '%s: %s' % (user.company_id.name, digest.name)
digest.template_id.with_context(user=user, company=user.company_id).send_mail(digest.id, force_send=True, raise_exception=True, email_values={'email_to': user.email, 'subject': subject})
digest.template_id.with_context(user=user).send_mail(digest.id, force_send=True, raise_exception=True, email_values={'email_to': user.email, 'subject': subject})
digest.next_run_date = digest._get_next_run_date()

def compute_kpis(self, company, user):
Oops, something went wrong.

0 comments on commit 1d2b6f1

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