[MERGE] forward port branch 11.0 up to 20e4cd5bcd

This commit is contained in:
Christophe Simonis
2018-02-09 16:13:08 +01:00
59 changed files with 877 additions and 268 deletions
+1 -1
View File
@@ -770,7 +770,7 @@ class WizardMultiChartsAccounts(models.TransientModel):
if company_id:
company = self.env['res.company'].browse(company_id)
currency_id = company.on_change_country(company.country_id.id)['value']['currency_id']
res.update({'currency_id': currency_id.id})
res.update({'currency_id': currency_id})
chart_templates = account_chart_template.search([('visible', '=', True)])
if chart_templates:
@@ -613,7 +613,7 @@ var LineRenderer = Widget.extend(FieldManagerMixin, {
/**
* @private
*/
_onFilterChange: function () {
_onFilterChange: function (event) {
this.trigger_up('change_filter', {'data': _.str.strip($(event.target).val())});
},
/**
@@ -30,16 +30,23 @@ class ResPartner(models.Model):
city = lines.pop()
return (cp, city)
else:
result = re.match('((?:L-|AT-)?[0-9\-]+) (.+)', lines[-1])
result = re.match('((?:L-|AT-)?[0-9\-]+[A-Z]{,2}) (.+)', lines[-1])
if result:
lines.pop()
return (result.group(1), result.group(2))
return False
def _set_address_field(partner, field, value):
partner[field] = value
non_set_address_fields.remove(field)
if stdnum_vat is None:
return {}
for partner in self:
# If a field is non set in this algorithm
# wipe it anyway
non_set_address_fields = set(['street', 'street2', 'city', 'zip', 'state_id', 'country_id'])
if not partner.vat:
return {}
if len(partner.vat) > 5 and partner.vat[:2].lower() in stdnum_vat.country_codes:
@@ -68,14 +75,20 @@ class ResPartner(models.Model):
lines = [x.strip() for x in lines[0].split(',') if x]
if len(lines) == 1:
lines = [x.strip() for x in lines[0].split(' ') if x]
partner.street = lines.pop(0)
_set_address_field(partner, 'street', lines.pop(0))
if len(lines) > 0:
res = _check_city(lines, result['countryCode'])
if res:
partner.zip = res[0]
partner.city = res[1]
_set_address_field(partner, 'zip', res[0])
_set_address_field(partner, 'city', res[1])
if len(lines) > 0:
partner.street2 = lines.pop(0)
_set_address_field(partner, 'street2', lines.pop(0))
country = self.env['res.country'].search([('code', '=', result['countryCode'])], limit=1)
partner.country_id = country and country.id or False
_set_address_field(partner, 'country_id', country and country.id or False)
for field in non_set_address_fields:
if partner[field]:
partner[field] = False
+7 -7
View File
@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 11.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-11-30 13:12+0000\n"
"PO-Revision-Date: 2017-11-30 13:12+0000\n"
"POT-Creation-Date: 2018-02-07 10:30+0000\n"
"PO-Revision-Date: 2018-02-07 10:30+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -272,11 +272,6 @@ msgid "\n"
"</div>"
msgstr ""
#. module: calendar
#: model:ir.model.fields,field_description:calendar.field_calendar_event_is_highlighted
msgid "# Meetings Highlight"
msgstr ""
#. module: calendar
#: model:mail.template,subject:calendar.calendar_template_meeting_reminder
msgid "${object.event_id.name} - Reminder"
@@ -805,6 +800,11 @@ msgstr ""
msgid "Invite wizard"
msgstr ""
#. module: calendar
#: model:ir.model.fields,field_description:calendar.field_calendar_event_is_highlighted
msgid "Is the Event Highlighted"
msgstr ""
#. module: calendar
#: selection:calendar.event,byday:0
msgid "Last"
+2 -2
View File
@@ -823,7 +823,7 @@ class Meeting(models.Model):
attendee_ids = fields.One2many('calendar.attendee', 'event_id', 'Participant', ondelete='cascade')
partner_ids = fields.Many2many('res.partner', 'calendar_event_res_partner_rel', string='Attendees', states={'done': [('readonly', True)]}, default=_default_partners)
alarm_ids = fields.Many2many('calendar.alarm', 'calendar_alarm_calendar_event_rel', string='Reminders', ondelete="restrict", copy=False)
is_highlighted = fields.Boolean(compute='_compute_is_highlighted', string='# Meetings Highlight')
is_highlighted = fields.Boolean(compute='_compute_is_highlighted', string='Is the Event Highlighted')
@api.multi
def _compute_attendee(self):
@@ -1478,7 +1478,7 @@ class Meeting(models.Model):
partners_to_notify = meeting.partner_ids.ids
event_attendees_changes = attendees_create and real_ids and attendees_create[real_ids[0]]
if event_attendees_changes:
partners_to_notify.append(event_attendees_changes['removed_partners'].ids)
partners_to_notify.extend(event_attendees_changes['removed_partners'].ids)
self.env['calendar.alarm_manager'].notify_next_alarm(partners_to_notify)
if (values.get('start_date') or values.get('start_datetime') or
@@ -13,6 +13,7 @@ CRM Phone Numbers Validation
This module allows for validate and format phone numbers for leads and contacts.""",
'data': [
'views/res_config_settings_views.xml',
'views/crm_lead_views.xml'
],
'depends': [
'phone_validation',
@@ -8,13 +8,12 @@ class Lead(models.Model):
_name = 'crm.lead'
_inherit = ['crm.lead', 'phone.validation.mixin']
@api.onchange('phone', 'country_id')
@api.onchange('phone', 'country_id', 'company_id')
def _onchange_phone_validation(self):
if self.phone:
self.phone = self.phone_format(self.phone)
@api.onchange('mobile', 'country_id')
@api.onchange('mobile', 'country_id', 'company_id')
def _onchange_mobile_validation(self):
if self.mobile:
self.mobile = self.phone_format(self.mobile)
@@ -8,12 +8,12 @@ class Contact(models.Model):
_name = 'res.partner'
_inherit = ['res.partner', 'phone.validation.mixin']
@api.onchange('phone', 'country_id')
@api.onchange('phone', 'country_id', 'company_id')
def _onchange_phone_validation(self):
if self.phone:
self.phone = self.phone_format(self.phone)
@api.onchange('mobile', 'country_id')
@api.onchange('mobile', 'country_id', 'company_id')
def _onchange_mobile_validation(self):
if self.mobile:
self.mobile = self.phone_format(self.mobile)
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="crm_lead_opportunity_view_form" model="ir.ui.view">
<field name="name">crm.lead.form.opportunity.inherit.crm.phone.validation</field>
<field name="model">crm.lead</field>
<field name="inherit_id" ref="crm.crm_case_form_view_oppor" />
<field name="arch" type="xml">
<xpath expr="//group[@name='Misc']" position="inside">
<field name="company_id" invisible="1"/>
</xpath>
</field>
</record>
</odoo>
+1 -1
View File
@@ -14,5 +14,5 @@
],
'demo': [],
'installable': True,
'auto-install': True,
'auto_install': True,
}
+2 -2
View File
@@ -147,7 +147,7 @@ msgstr "12% Diverse goederen"
#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-12-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-12-CC
msgid "12% Cocont. - Biens d'investissement"
msgstr "0% Medecont. - Investeringsgoederen"
msgstr "12% Medecont. - Investeringsgoederen"
#. module: l10n_be
#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-12-CC-C1
@@ -389,7 +389,7 @@ msgstr "21% Medecont. G."
#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-21-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-21-CC-C2
msgid "21% Cocont. Récupérable - Biens d'investissement"
msgstr "12% Medecont. Verhaalbaar - Investeringsgoederen"
msgstr "21% Medecont. Verhaalbaar - Investeringsgoederen"
#. module: l10n_be
#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-21-CC-C2
@@ -58,6 +58,34 @@ co_puc_235510,235510,Socios,TRUE,account.data_account_type_payable,l10n_co_chart
co_puc_236005,236005,Dividendos,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_236505,236505,Salarios y Pagos Laborales,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_236510,236510,Dividendos y/o Participaciones,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23651505,23651505,Retencion en la fuente por honorarios persona natural 10%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23651510,23651510,Retencion en la fuente por honorarios persona Juridica 11%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23651515,23651515,Retencion en la fuente por servicios de licencias software 3.5%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23651520,23651520,Retencion en la fuente por servicios de diseño web y consultorí informática 3.5%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23652005,23652005,Retencion en la fuente por comisiones persona natural 10%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23652010,23652010,Retencion en la fuente por comisiones persona juridica 11%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23652505,23652505,Retencion en la fuente por servicios en general 4%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23652510,23652510,Retencion en la fuente por servicios en general personas naturales no declarantes Renta 6%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23652515,23652515,Retencion en la fuente por servicio transporte nacional carga 1%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23652520,23652520,Retencion en la fuente por servicio transporte terrestre nacional pasajeros 3.5%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23652525,23652525,Retencion en la fuente por servicio transporte aereo y maritimo nacional pasajeros 1%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23652530,23652530,Retencion en la fuente por servicio temporales de empleo (sobre AIU) 1%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23652535,23652535,Retencion en la fuente por servicio de vigilancia y aseo (sobre AIU) 2%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23652540,23652540,Retencion en la fuente por servicio integrales de salud 2%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23652545,23652545,Retencion en la fuente por servicio de hoteles y restaurantes 3.5%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23652550,23652550,Retencion en la fuente por contratos de obra inmuebles 2%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23653005,23653005,Retencion en la fuente por arrendamientos Bienes Muebles 4%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23653010,23653010,Retencion en la fuente por arrendamientos Bienes Inmuebles 3.5%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23653510,23653510,Retencion en la fuente por rendimientos financieros generales 7%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23654005,23654005,Retencion en la fuente por compras declarantes 2.5%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23654010,23654010,Retencion en la fuente por compras no declarantes 3.5%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23654015,23654015,Retencion en la fuente por compras bienes agricolas 1.5%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23654020,23654020,Retencion en la fuente por compra cafe 0.5%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23654025,23654025,Retencion en la fuente por compra combustibles 0.1%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23654030,23654030,Retencion en la fuente por adquisicion de vehiculos 1%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23654035,23654035,Retencion en la fuente por adquisicion de bienes raices comerciales 2.5%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23654040,23654040,Retencion en la fuente por ventas de activos fijos 1%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_23655005,23655005,Retencion en la fuente por consultorias servicios tecnicos y asistencia tecnica pagos al exterior 10%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_236575,236575,Autorretenciones,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_236705,236705,Impuesto a Las Ventas Retenido,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_236805,236805,Impuesto de Industria y Comercio Retenido,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
@@ -81,6 +109,7 @@ co_puc_2408101005,2408101005,Compra Anulada Iva 19%,FALSE,account.data_account_t
co_puc_2408101010,2408101010,Compra Anulada Iva 5%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_2408101015,2408101015,Compra Anulada Iva 16%,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_240820,240820,Iva Descontable a Regimen Simplificado (Commun/Proporcional) - Solo Esta la DIAN lo Interpreta Utilizable,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_24082005,24082005,Iva retenido a regimen simplificado,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_241205,241205,Vigencia Fiscal Corriente,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_245605,245605,a Las Importaciones,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
co_puc_249505,249505,Otros,FALSE,account.data_account_type_current_liabilities,l10n_co_chart_template_generic
@@ -107,8 +136,45 @@ co_puc_340515,340515,de Reservas,FALSE,account.data_account_type_equity,l10n_co_
co_puc_340520,340520,de Resultados de Ejercicios Anteriores,FALSE,account.data_account_type_equity,l10n_co_chart_template_generic
co_puc_360505,360505,Utilidad Del Ejercicio,FALSE,account.data_account_type_equity,l10n_co_chart_template_generic
co_puc_370505,370505,Utilidades Acumuladas,FALSE,account.data_account_type_equity,l10n_co_chart_template_generic
co_puc_415505,415505,Arrendamientos de Bienes Inmuebles,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413502,413502,Venta de vehículos automotores,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413504,413504,"Mantenimiento, reparación y lavado de vehículos automotores",FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413506,413506,"Venta de partes, piezas y accesorios de vehículos automotores",FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413508,413508,"Venta de combustibles sólidos, líquidos, gaseosos",FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413510,413510,"Venta de lubricantes, aditivos, llantas y lujos para automotores",FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413512,413512,Venta a cambio de retribución o por contrata,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413514,413514,"Venta de insumos, materias primas agropecuarias y flores",FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413516,413516,Venta de otros insumos y materias primas no agropecuarias,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413518,413518,Venta de animales vivos y cueros,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413520,413520,Venta de productos en almacenes no especializados,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413522,413522,Venta de productos agropecuarios,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413524,413524,"Venta de productos textiles, de vestir, de cuero y calzado",FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413526,413526,Venta de papel y cartón,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413528,413528,"Venta de libros, revistas, elementos de papelería, útiles y textos escolares",FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413530,413530,"Venta de juegos, juguetes y artículos deportivos",FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413532,413532,Venta de instrumentos quirúrgicos y ortopédicos,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413534,413534,Venta de artículos en relojerías y joyerías,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413536,413536,Venta de electrodomésticos y muebles,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413538,413538,"Venta de productos de aseo, farmacéuticos, medicinales, y artículos de tocador",FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413540,413540,"Venta de cubiertos, vajillas, cristalería, porcelanas, cerámicas y otros artículos de uso doméstico",FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413542,413542,"Venta de materiales de construcción, fontanería y calefacción",FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413544,413544,Venta de pinturas y lacas,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413546,413546,Venta de productos de vidrios y marquetería,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413548,413548,Venta de herramientas y artículos de ferretría,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413550,413550,Venta de químicos,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413552,413552,"Venta de productos intermedios, desperdicios y desechos",FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413554,413554,"Venta de maquinaria, equipo de oficina y programas de computador",FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413556,413556,Venta de artículos en cacharrerías y misceláneas,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413558,413558,Venta de instrumentos musicales,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413560,413560,Venta de artículos en casas de empeño y prenderías,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413562,413562,Venta de equipo fotográfico,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413564,413564,Venta de equipo óptico y de precisión,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413566,413566,Venta de empaques,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413568,413568,Venta de equipo profesional y científico,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413570,413570,"Venta de loterías, rifas, chance, apuestas y similares",FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413572,413572,Reparación de efectos personales y electrodomésticos,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413595,413595,Venta de Otros Productos,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_413595,413595,Venta de otros productos,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_415505,415505,Arrendamientos de Bienes Inmuebles,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_421005,421005,Intereses,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_421020,421020,Diferencia en Cambio,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
co_puc_421040,421040,Descuentos Comerciales Condicionados,FALSE,account.data_account_type_revenue,l10n_co_chart_template_generic
1 id code name reconcile user_type_id:id chart_template_id:id
58 co_puc_236005 236005 Dividendos FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
59 co_puc_236505 236505 Salarios y Pagos Laborales FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
60 co_puc_236510 236510 Dividendos y/o Participaciones FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
61 co_puc_23651505 23651505 Retencion en la fuente por honorarios persona natural 10% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
62 co_puc_23651510 23651510 Retencion en la fuente por honorarios persona Juridica 11% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
63 co_puc_23651515 23651515 Retencion en la fuente por servicios de licencias software 3.5% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
64 co_puc_23651520 23651520 Retencion en la fuente por servicios de diseño web y consultorí informática 3.5% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
65 co_puc_23652005 23652005 Retencion en la fuente por comisiones persona natural 10% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
66 co_puc_23652010 23652010 Retencion en la fuente por comisiones persona juridica 11% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
67 co_puc_23652505 23652505 Retencion en la fuente por servicios en general 4% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
68 co_puc_23652510 23652510 Retencion en la fuente por servicios en general personas naturales no declarantes Renta 6% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
69 co_puc_23652515 23652515 Retencion en la fuente por servicio transporte nacional carga 1% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
70 co_puc_23652520 23652520 Retencion en la fuente por servicio transporte terrestre nacional pasajeros 3.5% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
71 co_puc_23652525 23652525 Retencion en la fuente por servicio transporte aereo y maritimo nacional pasajeros 1% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
72 co_puc_23652530 23652530 Retencion en la fuente por servicio temporales de empleo (sobre AIU) 1% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
73 co_puc_23652535 23652535 Retencion en la fuente por servicio de vigilancia y aseo (sobre AIU) 2% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
74 co_puc_23652540 23652540 Retencion en la fuente por servicio integrales de salud 2% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
75 co_puc_23652545 23652545 Retencion en la fuente por servicio de hoteles y restaurantes 3.5% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
76 co_puc_23652550 23652550 Retencion en la fuente por contratos de obra inmuebles 2% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
77 co_puc_23653005 23653005 Retencion en la fuente por arrendamientos Bienes Muebles 4% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
78 co_puc_23653010 23653010 Retencion en la fuente por arrendamientos Bienes Inmuebles 3.5% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
79 co_puc_23653510 23653510 Retencion en la fuente por rendimientos financieros generales 7% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
80 co_puc_23654005 23654005 Retencion en la fuente por compras declarantes 2.5% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
81 co_puc_23654010 23654010 Retencion en la fuente por compras no declarantes 3.5% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
82 co_puc_23654015 23654015 Retencion en la fuente por compras bienes agricolas 1.5% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
83 co_puc_23654020 23654020 Retencion en la fuente por compra cafe 0.5% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
84 co_puc_23654025 23654025 Retencion en la fuente por compra combustibles 0.1% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
85 co_puc_23654030 23654030 Retencion en la fuente por adquisicion de vehiculos 1% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
86 co_puc_23654035 23654035 Retencion en la fuente por adquisicion de bienes raices comerciales 2.5% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
87 co_puc_23654040 23654040 Retencion en la fuente por ventas de activos fijos 1% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
88 co_puc_23655005 23655005 Retencion en la fuente por consultorias servicios tecnicos y asistencia tecnica pagos al exterior 10% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
89 co_puc_236575 236575 Autorretenciones FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
90 co_puc_236705 236705 Impuesto a Las Ventas Retenido FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
91 co_puc_236805 236805 Impuesto de Industria y Comercio Retenido FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
109 co_puc_2408101010 2408101010 Compra Anulada Iva 5% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
110 co_puc_2408101015 2408101015 Compra Anulada Iva 16% FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
111 co_puc_240820 240820 Iva Descontable a Regimen Simplificado (Commun/Proporcional) - Solo Esta la DIAN lo Interpreta Utilizable FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
112 co_puc_24082005 24082005 Iva retenido a regimen simplificado FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
113 co_puc_241205 241205 Vigencia Fiscal Corriente FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
114 co_puc_245605 245605 a Las Importaciones FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
115 co_puc_249505 249505 Otros FALSE account.data_account_type_current_liabilities l10n_co_chart_template_generic
136 co_puc_340520 340520 de Resultados de Ejercicios Anteriores FALSE account.data_account_type_equity l10n_co_chart_template_generic
137 co_puc_360505 360505 Utilidad Del Ejercicio FALSE account.data_account_type_equity l10n_co_chart_template_generic
138 co_puc_370505 370505 Utilidades Acumuladas FALSE account.data_account_type_equity l10n_co_chart_template_generic
139 co_puc_415505 co_puc_413502 415505 413502 Arrendamientos de Bienes Inmuebles Venta de vehículos automotores FALSE account.data_account_type_revenue l10n_co_chart_template_generic
140 co_puc_413504 413504 Mantenimiento, reparación y lavado de vehículos automotores FALSE account.data_account_type_revenue l10n_co_chart_template_generic
141 co_puc_413506 413506 Venta de partes, piezas y accesorios de vehículos automotores FALSE account.data_account_type_revenue l10n_co_chart_template_generic
142 co_puc_413508 413508 Venta de combustibles sólidos, líquidos, gaseosos FALSE account.data_account_type_revenue l10n_co_chart_template_generic
143 co_puc_413510 413510 Venta de lubricantes, aditivos, llantas y lujos para automotores FALSE account.data_account_type_revenue l10n_co_chart_template_generic
144 co_puc_413512 413512 Venta a cambio de retribución o por contrata FALSE account.data_account_type_revenue l10n_co_chart_template_generic
145 co_puc_413514 413514 Venta de insumos, materias primas agropecuarias y flores FALSE account.data_account_type_revenue l10n_co_chart_template_generic
146 co_puc_413516 413516 Venta de otros insumos y materias primas no agropecuarias FALSE account.data_account_type_revenue l10n_co_chart_template_generic
147 co_puc_413518 413518 Venta de animales vivos y cueros FALSE account.data_account_type_revenue l10n_co_chart_template_generic
148 co_puc_413520 413520 Venta de productos en almacenes no especializados FALSE account.data_account_type_revenue l10n_co_chart_template_generic
149 co_puc_413522 413522 Venta de productos agropecuarios FALSE account.data_account_type_revenue l10n_co_chart_template_generic
150 co_puc_413524 413524 Venta de productos textiles, de vestir, de cuero y calzado FALSE account.data_account_type_revenue l10n_co_chart_template_generic
151 co_puc_413526 413526 Venta de papel y cartón FALSE account.data_account_type_revenue l10n_co_chart_template_generic
152 co_puc_413528 413528 Venta de libros, revistas, elementos de papelería, útiles y textos escolares FALSE account.data_account_type_revenue l10n_co_chart_template_generic
153 co_puc_413530 413530 Venta de juegos, juguetes y artículos deportivos FALSE account.data_account_type_revenue l10n_co_chart_template_generic
154 co_puc_413532 413532 Venta de instrumentos quirúrgicos y ortopédicos FALSE account.data_account_type_revenue l10n_co_chart_template_generic
155 co_puc_413534 413534 Venta de artículos en relojerías y joyerías FALSE account.data_account_type_revenue l10n_co_chart_template_generic
156 co_puc_413536 413536 Venta de electrodomésticos y muebles FALSE account.data_account_type_revenue l10n_co_chart_template_generic
157 co_puc_413538 413538 Venta de productos de aseo, farmacéuticos, medicinales, y artículos de tocador FALSE account.data_account_type_revenue l10n_co_chart_template_generic
158 co_puc_413540 413540 Venta de cubiertos, vajillas, cristalería, porcelanas, cerámicas y otros artículos de uso doméstico FALSE account.data_account_type_revenue l10n_co_chart_template_generic
159 co_puc_413542 413542 Venta de materiales de construcción, fontanería y calefacción FALSE account.data_account_type_revenue l10n_co_chart_template_generic
160 co_puc_413544 413544 Venta de pinturas y lacas FALSE account.data_account_type_revenue l10n_co_chart_template_generic
161 co_puc_413546 413546 Venta de productos de vidrios y marquetería FALSE account.data_account_type_revenue l10n_co_chart_template_generic
162 co_puc_413548 413548 Venta de herramientas y artículos de ferretría FALSE account.data_account_type_revenue l10n_co_chart_template_generic
163 co_puc_413550 413550 Venta de químicos FALSE account.data_account_type_revenue l10n_co_chart_template_generic
164 co_puc_413552 413552 Venta de productos intermedios, desperdicios y desechos FALSE account.data_account_type_revenue l10n_co_chart_template_generic
165 co_puc_413554 413554 Venta de maquinaria, equipo de oficina y programas de computador FALSE account.data_account_type_revenue l10n_co_chart_template_generic
166 co_puc_413556 413556 Venta de artículos en cacharrerías y misceláneas FALSE account.data_account_type_revenue l10n_co_chart_template_generic
167 co_puc_413558 413558 Venta de instrumentos musicales FALSE account.data_account_type_revenue l10n_co_chart_template_generic
168 co_puc_413560 413560 Venta de artículos en casas de empeño y prenderías FALSE account.data_account_type_revenue l10n_co_chart_template_generic
169 co_puc_413562 413562 Venta de equipo fotográfico FALSE account.data_account_type_revenue l10n_co_chart_template_generic
170 co_puc_413564 413564 Venta de equipo óptico y de precisión FALSE account.data_account_type_revenue l10n_co_chart_template_generic
171 co_puc_413566 413566 Venta de empaques FALSE account.data_account_type_revenue l10n_co_chart_template_generic
172 co_puc_413568 413568 Venta de equipo profesional y científico FALSE account.data_account_type_revenue l10n_co_chart_template_generic
173 co_puc_413570 413570 Venta de loterías, rifas, chance, apuestas y similares FALSE account.data_account_type_revenue l10n_co_chart_template_generic
174 co_puc_413572 413572 Reparación de efectos personales y electrodomésticos FALSE account.data_account_type_revenue l10n_co_chart_template_generic
175 co_puc_413595 413595 Venta de Otros Productos FALSE account.data_account_type_revenue l10n_co_chart_template_generic
176 co_puc_413595 413595 Venta de otros productos FALSE account.data_account_type_revenue l10n_co_chart_template_generic
177 co_puc_415505 415505 Arrendamientos de Bienes Inmuebles FALSE account.data_account_type_revenue l10n_co_chart_template_generic
178 co_puc_421005 421005 Intereses FALSE account.data_account_type_revenue l10n_co_chart_template_generic
179 co_puc_421020 421020 Diferencia en Cambio FALSE account.data_account_type_revenue l10n_co_chart_template_generic
180 co_puc_421040 421040 Descuentos Comerciales Condicionados FALSE account.data_account_type_revenue l10n_co_chart_template_generic
+54 -54
View File
@@ -1,54 +1,54 @@
id,amount,account_id:id,refund_account_id:id,name,type_tax_use,amount_type,children_tax_ids:id,chart_template_id:id
l10n_co_tax_0,5.0,co_puc_2408100510,co_puc_2408101010,IVA Compra 5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_1,19.0,co_puc_2408100505,co_puc_2408101005,IVA Compra 19%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_2,16.0,co_puc_2408100515,co_puc_2408101015,IVA Descontable Compra 16% (2016 y Enero 2017),purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_3,0.0,co_puc_236505,co_puc_236505,RteFte Salarios y Pagos Laborales,None,fixed,,l10n_co_chart_template_generic
l10n_co_tax_4,16.0,,,IVA Devoluciones Ventas 16% 2016,sale,percent,,l10n_co_chart_template_generic
l10n_co_tax_5,0.0,,,IVA Compra Importaciones,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_6,0.0,,,IVA Compra Excluido,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_7,0.0,,,IVA Compra Exento,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_8,19.0,co_puc_2408050505,co_puc_2408051005,IVA Ventas 19%,sale,percent,,l10n_co_chart_template_generic
l10n_co_tax_9,5.0,co_puc_2408050510,co_puc_2408051010,IVA Ventas 5%,sale,percent,,l10n_co_chart_template_generic
l10n_co_tax_10,0.0,,,IVA Excento,sale,percent,,l10n_co_chart_template_generic
l10n_co_tax_11,0.0,,,IVA Excluido,sale,percent,,l10n_co_chart_template_generic
l10n_co_tax_12,-2.85,co_puc_236705,co_puc_236705,RteIVA 15% sobre el 19% IVA,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_13,-0.75,co_puc_236705,co_puc_236705,RteIVA 15% sobre el 5% IVA,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_14,0.75,,,RteIVA 15% sobre el 5% IVA Contrapartida,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_15,2.85,,,RteIVA 15% sobre el 19% IVA Contrapartida,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_16,-0.1,,,RteFte Compra Combustibles 0.1%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_17,-0.5,,,RteFte Compra Cafe 0.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_18,-10.0,,,RteFte Comisiones Persona Natural 10%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_19,-2.5,,,RteFte Compras Declarantes 2.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_20,-10.0,,,"RteFte Consultorias, Servicios Tecnicos y Asistencia Tecnica Pagos al Exterior 10%",purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_21,-1.0,,,RteFte Adquisicion de Vehiculos 1%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_22,-1.0,,,RteFte Compras de Bienes Raices 1%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_23,-4.0,,,RteFte Servicios P Jurídicas y PN Declarantes 4%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_24,-1.0,,,RteFte Servicio Transporte Nacional Carga 1%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_25,-6.0,,,RteFte Servicios en General Personas Naturales No Declarantes Renta 6%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_26,-2.0,,,RteFte Servicio de Vigilancia y Aseo (Sobre AIU) 2%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_27,-3.5,,,RteFte Honorarios Servicios Licencias Software 3.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_28,-2.0,,,RteFte Contratos de Obra Inmuebles 2%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_29,-4.0,,,RteFte Arrendamientos Bienes Muebles 4%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_30,-3.5,,,RteFte Arrendamientos Bienes Inmuebles 3.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_31,-7.0,,,RteFte Rendimientos Financieros Generales 7%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_32,-10.0,,,RteFte Honorarios Persona Natural 10%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_33,-3.5,,,RteFte Honorarios Diseno Web y Consultoria Informatica 3.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_34,-2.5,,,RteFte Adquisicion de Bienes Raices Comerciales 2.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_35,-3.5,,,RteFte Compras No Declarantes 3.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_36,-11.0,,,RteFte Comisiones Persona Juridica 11%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_37,-1.5,,,RteFte Compras Bienes Agricolas 1.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_38,-3.5,,,RteFte Servicio Transporte Terrestre Nacional Pasajeros 3.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_39,-1.0,,,RteFte Servicio Temporales de Empleo (Sobre AIU) 1%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_40,-11.0,,,RteFte Honorarios Persona Juridica 11%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_41,-2.0,,,RteFte Servicio Integrales de Salud 2%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_42,-3.5,,,RteFte Servicio de Hoteles y Restaurantes 3.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_43,0.0,co_puc_236805,co_puc_236805,RteICA,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_44,-0.69,co_puc_236805,co_puc_236805,RteICA 0.69%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_45,-1.104,co_puc_236805,co_puc_236805,RteICA 1.104%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_46,-0.414,co_puc_236805,co_puc_236805,RteICA 0.414%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_47,-1.38,co_puc_236805,co_puc_236805,RteICA 1.38%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_48,-0.966,co_puc_236805,co_puc_236805,RteICA 0.966%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_49,16.0,,,IVA Compra 16% RC,purchase,group,"l10n_co_tax_1,l10n_co_tax_12",l10n_co_chart_template_generic
l10n_co_tax_50,16.0,,,IVA Compra 16% RS,purchase,group,"l10n_co_tax_12,l10n_co_tax_15",l10n_co_chart_template_generic
l10n_co_tax_51,5.0,,,IVA Compra 5% RS,purchase,group,"l10n_co_tax_13,l10n_co_tax_14",l10n_co_chart_template_generic
l10n_co_tax_52,5.0,,,IVA Compra 5% RC,purchase,group,"l10n_co_tax_0,l10n_co_tax_13",l10n_co_chart_template_generic
id,sequence,amount,account_id:id,refund_account_id:id,name,type_tax_use,amount_type,children_tax_ids:id,chart_template_id:id
l10n_co_tax_0,1,5.0,co_puc_2408100510,co_puc_2408101010,IVA Compra 5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_1,0,19.0,co_puc_2408100505,co_puc_2408101005,IVA Compra 19%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_2,1,16.0,co_puc_2408100515,co_puc_2408101015,IVA Descontable Compra 16% (2016 y Enero 2017),purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_3,1,0.0,co_puc_236505,co_puc_236505,RteFte Salarios y Pagos Laborales,None,fixed,,l10n_co_chart_template_generic
l10n_co_tax_4,1,16.0,,,IVA Devoluciones Ventas 16% 2016,sale,percent,,l10n_co_chart_template_generic
l10n_co_tax_5,1,0.0,,,IVA Compra Importaciones,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_6,1,0.0,,,IVA Compra Excluido,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_7,1,0.0,,,IVA Compra Exento,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_8,0,19.0,co_puc_2408050505,co_puc_2408051005,IVA Ventas 19%,sale,percent,,l10n_co_chart_template_generic
l10n_co_tax_9,1,5.0,co_puc_2408050510,co_puc_2408051010,IVA Ventas 5%,sale,percent,,l10n_co_chart_template_generic
l10n_co_tax_10,1,0.0,,,IVA Excento,sale,percent,,l10n_co_chart_template_generic
l10n_co_tax_11,1,0.0,,,IVA Excluido,sale,percent,,l10n_co_chart_template_generic
l10n_co_tax_12,1,-2.85,co_puc_236705,co_puc_236705,RteIVA 15% sobre el 19% IVA,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_13,1,-0.75,co_puc_236705,co_puc_236705,RteIVA 15% sobre el 5% IVA,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_14,1,0.75,co_puc_24082005,co_puc_24082005,RteIVA 15% sobre el 5% IVA Contrapartida,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_15,1,2.85,co_puc_24082005,co_puc_24082005,RteIVA 15% sobre el 19% IVA Contrapartida,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_16,1,-0.1,co_puc_23654025,co_puc_23654025,RteFte Compra Combustibles 0.1%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_17,1,-0.5,co_puc_23654020,co_puc_23654020,RteFte Compra Cafe 0.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_18,1,-10.0,co_puc_23652005,co_puc_23652005,RteFte Comisiones Persona Natural 10%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_19,1,-2.5,co_puc_23654005,co_puc_23654005,RteFte Compras Declarantes 2.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_20,1,-10.0,co_puc_23655005,co_puc_23655005,"RteFte Consultorias, Servicios Tecnicos y Asistencia Tecnica Pagos al Exterior 10%",purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_21,1,-1.0,co_puc_23654030,co_puc_23654030,RteFte Adquisicion de Vehiculos 1%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_22,1,-1.0,co_puc_23654040,co_puc_23654040,RteFte Compras de Bienes Raices 1%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_23,1,-4.0,co_puc_23652505,co_puc_23652505,RteFte Servicios P Jurídicas y PN Declarantes 4%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_24,1,-1.0,co_puc_23652515,co_puc_23652515,RteFte Servicio Transporte Nacional Carga 1%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_25,1,-6.0,co_puc_23652510,co_puc_23652510,RteFte Servicios en General Personas Naturales No Declarantes Renta 6%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_26,1,-2.0,co_puc_23652535,co_puc_23652535,RteFte Servicio de Vigilancia y Aseo (Sobre AIU) 2%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_27,1,-3.5,co_puc_23651515,co_puc_23651515,RteFte Honorarios Servicios Licencias Software 3.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_28,1,-2.0,co_puc_23652550,co_puc_23652550,RteFte Contratos de Obra Inmuebles 2%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_29,1,-4.0,co_puc_23653005,co_puc_23653005,RteFte Arrendamientos Bienes Muebles 4%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_30,1,-3.5,co_puc_23653010,co_puc_23653010,RteFte Arrendamientos Bienes Inmuebles 3.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_31,1,-7.0,co_puc_23653510,co_puc_23653510,RteFte Rendimientos Financieros Generales 7%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_32,1,-10.0,co_puc_23651505,co_puc_23651505,RteFte Honorarios Persona Natural 10%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_33,1,-3.5,co_puc_23651520,co_puc_23651520,RteFte Honorarios Diseno Web y Consultoria Informatica 3.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_34,1,-2.5,co_puc_23654035,co_puc_23654035,RteFte Adquisicion de Bienes Raices Comerciales 2.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_35,1,-3.5,co_puc_23654010,co_puc_23654010,RteFte Compras No Declarantes 3.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_36,1,-11.0,co_puc_23652010,co_puc_23652010,RteFte Comisiones Persona Juridica 11%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_37,1,-1.5,co_puc_23654015,co_puc_23654015,RteFte Compras Bienes Agricolas 1.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_38,1,-3.5,co_puc_23652520,co_puc_23652520,RteFte Servicio Transporte Terrestre Nacional Pasajeros 3.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_39,1,-1.0,co_puc_23652530,co_puc_23652530,RteFte Servicio Temporales de Empleo (Sobre AIU) 1%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_40,1,-11.0,co_puc_23651510,co_puc_23651510,RteFte Honorarios Persona Juridica 11%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_41,1,-2.0,co_puc_23652540,co_puc_23652540,RteFte Servicio Integrales de Salud 2%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_42,1,-3.5,co_puc_23652545,co_puc_23652545,RteFte Servicio de Hoteles y Restaurantes 3.5%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_43,1,0.0,co_puc_236805,co_puc_236805,RteICA,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_44,1,-0.69,co_puc_236805,co_puc_236805,RteICA 0.69%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_45,1,-1.104,co_puc_236805,co_puc_236805,RteICA 1.104%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_46,1,-0.414,co_puc_236805,co_puc_236805,RteICA 0.414%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_47,1,-1.38,co_puc_236805,co_puc_236805,RteICA 1.38%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_48,1,-0.966,co_puc_236805,co_puc_236805,RteICA 0.966%,purchase,percent,,l10n_co_chart_template_generic
l10n_co_tax_49,1,19.0,,,IVA Compra 19% RC,purchase,group,"l10n_co_tax_1,l10n_co_tax_12",l10n_co_chart_template_generic
l10n_co_tax_50,1,19.0,,,IVA Compra 19% RS,purchase,group,"l10n_co_tax_12,l10n_co_tax_15",l10n_co_chart_template_generic
l10n_co_tax_51,1,5.0,,,IVA Compra 5% RS,purchase,group,"l10n_co_tax_13,l10n_co_tax_14",l10n_co_chart_template_generic
l10n_co_tax_52,1,5.0,,,IVA Compra 5% RC,purchase,group,"l10n_co_tax_0,l10n_co_tax_13",l10n_co_chart_template_generic
1 id sequence amount account_id:id refund_account_id:id name type_tax_use amount_type children_tax_ids:id chart_template_id:id
2 l10n_co_tax_0 1 5.0 co_puc_2408100510 co_puc_2408101010 IVA Compra 5% purchase percent l10n_co_chart_template_generic
3 l10n_co_tax_1 0 19.0 co_puc_2408100505 co_puc_2408101005 IVA Compra 19% purchase percent l10n_co_chart_template_generic
4 l10n_co_tax_2 1 16.0 co_puc_2408100515 co_puc_2408101015 IVA Descontable Compra 16% (2016 y Enero 2017) purchase percent l10n_co_chart_template_generic
5 l10n_co_tax_3 1 0.0 co_puc_236505 co_puc_236505 RteFte Salarios y Pagos Laborales None fixed l10n_co_chart_template_generic
6 l10n_co_tax_4 1 16.0 IVA Devoluciones Ventas 16% 2016 sale percent l10n_co_chart_template_generic
7 l10n_co_tax_5 1 0.0 IVA Compra Importaciones purchase percent l10n_co_chart_template_generic
8 l10n_co_tax_6 1 0.0 IVA Compra Excluido purchase percent l10n_co_chart_template_generic
9 l10n_co_tax_7 1 0.0 IVA Compra Exento purchase percent l10n_co_chart_template_generic
10 l10n_co_tax_8 0 19.0 co_puc_2408050505 co_puc_2408051005 IVA Ventas 19% sale percent l10n_co_chart_template_generic
11 l10n_co_tax_9 1 5.0 co_puc_2408050510 co_puc_2408051010 IVA Ventas 5% sale percent l10n_co_chart_template_generic
12 l10n_co_tax_10 1 0.0 IVA Excento sale percent l10n_co_chart_template_generic
13 l10n_co_tax_11 1 0.0 IVA Excluido sale percent l10n_co_chart_template_generic
14 l10n_co_tax_12 1 -2.85 co_puc_236705 co_puc_236705 RteIVA 15% sobre el 19% IVA purchase percent l10n_co_chart_template_generic
15 l10n_co_tax_13 1 -0.75 co_puc_236705 co_puc_236705 RteIVA 15% sobre el 5% IVA purchase percent l10n_co_chart_template_generic
16 l10n_co_tax_14 1 0.75 co_puc_24082005 co_puc_24082005 RteIVA 15% sobre el 5% IVA Contrapartida purchase percent l10n_co_chart_template_generic
17 l10n_co_tax_15 1 2.85 co_puc_24082005 co_puc_24082005 RteIVA 15% sobre el 19% IVA Contrapartida purchase percent l10n_co_chart_template_generic
18 l10n_co_tax_16 1 -0.1 co_puc_23654025 co_puc_23654025 RteFte Compra Combustibles 0.1% purchase percent l10n_co_chart_template_generic
19 l10n_co_tax_17 1 -0.5 co_puc_23654020 co_puc_23654020 RteFte Compra Cafe 0.5% purchase percent l10n_co_chart_template_generic
20 l10n_co_tax_18 1 -10.0 co_puc_23652005 co_puc_23652005 RteFte Comisiones Persona Natural 10% purchase percent l10n_co_chart_template_generic
21 l10n_co_tax_19 1 -2.5 co_puc_23654005 co_puc_23654005 RteFte Compras Declarantes 2.5% purchase percent l10n_co_chart_template_generic
22 l10n_co_tax_20 1 -10.0 co_puc_23655005 co_puc_23655005 RteFte Consultorias, Servicios Tecnicos y Asistencia Tecnica Pagos al Exterior 10% purchase percent l10n_co_chart_template_generic
23 l10n_co_tax_21 1 -1.0 co_puc_23654030 co_puc_23654030 RteFte Adquisicion de Vehiculos 1% purchase percent l10n_co_chart_template_generic
24 l10n_co_tax_22 1 -1.0 co_puc_23654040 co_puc_23654040 RteFte Compras de Bienes Raices 1% purchase percent l10n_co_chart_template_generic
25 l10n_co_tax_23 1 -4.0 co_puc_23652505 co_puc_23652505 RteFte Servicios P Jurídicas y PN Declarantes 4% purchase percent l10n_co_chart_template_generic
26 l10n_co_tax_24 1 -1.0 co_puc_23652515 co_puc_23652515 RteFte Servicio Transporte Nacional Carga 1% purchase percent l10n_co_chart_template_generic
27 l10n_co_tax_25 1 -6.0 co_puc_23652510 co_puc_23652510 RteFte Servicios en General Personas Naturales No Declarantes Renta 6% purchase percent l10n_co_chart_template_generic
28 l10n_co_tax_26 1 -2.0 co_puc_23652535 co_puc_23652535 RteFte Servicio de Vigilancia y Aseo (Sobre AIU) 2% purchase percent l10n_co_chart_template_generic
29 l10n_co_tax_27 1 -3.5 co_puc_23651515 co_puc_23651515 RteFte Honorarios Servicios Licencias Software 3.5% purchase percent l10n_co_chart_template_generic
30 l10n_co_tax_28 1 -2.0 co_puc_23652550 co_puc_23652550 RteFte Contratos de Obra Inmuebles 2% purchase percent l10n_co_chart_template_generic
31 l10n_co_tax_29 1 -4.0 co_puc_23653005 co_puc_23653005 RteFte Arrendamientos Bienes Muebles 4% purchase percent l10n_co_chart_template_generic
32 l10n_co_tax_30 1 -3.5 co_puc_23653010 co_puc_23653010 RteFte Arrendamientos Bienes Inmuebles 3.5% purchase percent l10n_co_chart_template_generic
33 l10n_co_tax_31 1 -7.0 co_puc_23653510 co_puc_23653510 RteFte Rendimientos Financieros Generales 7% purchase percent l10n_co_chart_template_generic
34 l10n_co_tax_32 1 -10.0 co_puc_23651505 co_puc_23651505 RteFte Honorarios Persona Natural 10% purchase percent l10n_co_chart_template_generic
35 l10n_co_tax_33 1 -3.5 co_puc_23651520 co_puc_23651520 RteFte Honorarios Diseno Web y Consultoria Informatica 3.5% purchase percent l10n_co_chart_template_generic
36 l10n_co_tax_34 1 -2.5 co_puc_23654035 co_puc_23654035 RteFte Adquisicion de Bienes Raices Comerciales 2.5% purchase percent l10n_co_chart_template_generic
37 l10n_co_tax_35 1 -3.5 co_puc_23654010 co_puc_23654010 RteFte Compras No Declarantes 3.5% purchase percent l10n_co_chart_template_generic
38 l10n_co_tax_36 1 -11.0 co_puc_23652010 co_puc_23652010 RteFte Comisiones Persona Juridica 11% purchase percent l10n_co_chart_template_generic
39 l10n_co_tax_37 1 -1.5 co_puc_23654015 co_puc_23654015 RteFte Compras Bienes Agricolas 1.5% purchase percent l10n_co_chart_template_generic
40 l10n_co_tax_38 1 -3.5 co_puc_23652520 co_puc_23652520 RteFte Servicio Transporte Terrestre Nacional Pasajeros 3.5% purchase percent l10n_co_chart_template_generic
41 l10n_co_tax_39 1 -1.0 co_puc_23652530 co_puc_23652530 RteFte Servicio Temporales de Empleo (Sobre AIU) 1% purchase percent l10n_co_chart_template_generic
42 l10n_co_tax_40 1 -11.0 co_puc_23651510 co_puc_23651510 RteFte Honorarios Persona Juridica 11% purchase percent l10n_co_chart_template_generic
43 l10n_co_tax_41 1 -2.0 co_puc_23652540 co_puc_23652540 RteFte Servicio Integrales de Salud 2% purchase percent l10n_co_chart_template_generic
44 l10n_co_tax_42 1 -3.5 co_puc_23652545 co_puc_23652545 RteFte Servicio de Hoteles y Restaurantes 3.5% purchase percent l10n_co_chart_template_generic
45 l10n_co_tax_43 1 0.0 co_puc_236805 co_puc_236805 RteICA purchase percent l10n_co_chart_template_generic
46 l10n_co_tax_44 1 -0.69 co_puc_236805 co_puc_236805 RteICA 0.69% purchase percent l10n_co_chart_template_generic
47 l10n_co_tax_45 1 -1.104 co_puc_236805 co_puc_236805 RteICA 1.104% purchase percent l10n_co_chart_template_generic
48 l10n_co_tax_46 1 -0.414 co_puc_236805 co_puc_236805 RteICA 0.414% purchase percent l10n_co_chart_template_generic
49 l10n_co_tax_47 1 -1.38 co_puc_236805 co_puc_236805 RteICA 1.38% purchase percent l10n_co_chart_template_generic
50 l10n_co_tax_48 1 -0.966 co_puc_236805 co_puc_236805 RteICA 0.966% purchase percent l10n_co_chart_template_generic
51 l10n_co_tax_49 1 16.0 19.0 IVA Compra 16% RC IVA Compra 19% RC purchase group l10n_co_tax_1,l10n_co_tax_12 l10n_co_chart_template_generic
52 l10n_co_tax_50 1 16.0 19.0 IVA Compra 16% RS IVA Compra 19% RS purchase group l10n_co_tax_12,l10n_co_tax_15 l10n_co_chart_template_generic
53 l10n_co_tax_51 1 5.0 IVA Compra 5% RS purchase group l10n_co_tax_13,l10n_co_tax_14 l10n_co_chart_template_generic
54 l10n_co_tax_52 1 5.0 IVA Compra 5% RC purchase group l10n_co_tax_0,l10n_co_tax_13 l10n_co_chart_template_generic
+14 -1
View File
@@ -12,7 +12,7 @@ class ResPartner(models.Model):
('foreign_id_card', 'Cedula de Extranjeria'),
('external_id', 'ID del Exterior')], string='Document Type',
help='Indicates to what document the information in here belongs to.')
l10n_co_verification_code = fields.Char(compute='_compute_verification_code', string='VC',
l10n_co_verification_code = fields.Char(compute='_compute_verification_code', string='VC', # todo remove this field in master
help='Redundancy check to verify the vat number has been typed in correctly.')
@api.depends('vat')
@@ -40,3 +40,16 @@ class ResPartner(models.Model):
partner.l10n_co_verification_code = 11 - number
except ValueError:
partner.l10n_co_verification_code = False
@api.constrains('vat', 'commercial_partner_country_id', 'l10n_co_document_type')
def check_vat(self):
# check_vat is implemented by base_vat which this localization
# doesn't directly depend on. It is however automatically
# installed for Colombia.
if self.sudo().env.ref('base.module_base_vat').state == 'installed':
# don't check Colombian partners unless they have RUT (= Colombian VAT) set as document type
self = self.filtered(lambda partner: partner.country_id != self.env.ref('base.co') or\
partner.l10n_co_document_type == 'rut')
return super(ResPartner, self).check_vat()
else:
return True
+1 -1
View File
@@ -9,7 +9,7 @@
<field name="l10n_co_document_type"/>
</field>
<field name="vat" position="after">
<field name="l10n_co_verification_code"/>
<field name="l10n_co_verification_code" invisible="1"/>
</field>
</field>
</record>
+3 -2
View File
@@ -757,9 +757,10 @@ class Message(models.Model):
'datas_fname': name,
'res_model': 'mail.message',
})
attachment.generate_access_token()
values['attachment_ids'].append((4, attachment.id))
data_to_url[key] = '/web/image/%s' % attachment.id
return '%s%s alt="%s"' % (data_to_url[key], match.group(3), name)
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']))
# delegate creation of tracking after the create as sudo to avoid access rights issues
+1 -1
View File
@@ -126,7 +126,7 @@ var MessagingMenu = Widget.extend({
this.do_action({
type: 'ir.actions.act_window',
res_model: resModel,
views: [[false, 'form'], [false, 'kanban']],
views: [[false, 'form']],
res_id: resID
});
} else {
@@ -148,15 +148,12 @@ odoo.define('payment_stripe.stripe', function(require) {
});
}
create_tx.done(function () {
if (!_.contains(int_currencies, currency)) {
amount = amount*100;
}
getStripeHandler().open({
name: $("input[name='merchant']").val(),
description: $("input[name='invoice_num']").val(),
email: $("input[name='email']").val(),
currency: currency,
amount: amount,
amount: _.contains(int_currencies, currency) ? amount : amount * 100,
});
});
}
@@ -11,20 +11,21 @@ class PhoneValidationMixin(models.AbstractModel):
def _phone_get_country(self):
if 'country_id' in self:
return self.country_id
return self.env.user.company_id.country_id
def _phone_get_always_international(self):
if 'company_id' in self:
if 'company_id' in self and self.country_id:
return self.company_id.phone_international_format == 'prefix'
return self.env.user.company_id.phone_international_format == 'prefix'
def phone_format(self, number, country=None, company=None):
country = country or self._phone_get_country()
if not country:
return number
always_international = company.phone_international_format == 'prefix' if company else self._phone_get_always_international()
return phone_validation.phone_format(
number,
country.code if country else None,
country.phone_code if country else None,
always_international=always_international,
raise_exception=True
raise_exception=False
)
@@ -41,7 +41,7 @@ try:
if raise_exception:
raise
else:
_logger.warning(_('Unable to format %s:\n%s') % number, e)
_logger.warning(_('Unable to format %s:\n%s'), number, e)
return number
if always_international or phone_nbr.country_code != country_phone_code:
phone_fmt = phonenumbers.PhoneNumberFormat.INTERNATIONAL
@@ -2038,6 +2038,7 @@ var PaymentScreenWidget = ScreenWidget.extend({
invoiced.fail(function(error){
self.invoicing = false;
order.finalized = false;
if (error.message === 'Missing Customer') {
self.gui.show_popup('confirm',{
'title': _t('Please select the Customer'),
+20 -16
View File
@@ -909,22 +909,8 @@ class ProcurementRule(models.Model):
for line in po.order_line:
if line.product_id == product_id and line.product_uom == product_id.uom_po_id:
if line._merge_in_existing_line(product_id, product_qty, product_uom, location_id, name, origin, values):
procurement_uom_po_qty = product_uom._compute_quantity(product_qty, product_id.uom_po_id)
seller = product_id._select_seller(
partner_id=partner,
quantity=line.product_qty + procurement_uom_po_qty,
date=po.date_order and po.date_order[:10],
uom_id=product_id.uom_po_id)
price_unit = self.env['account.tax']._fix_tax_included_price_company(seller.price, line.product_id.supplier_taxes_id, line.taxes_id, values['company_id']) if seller else 0.0
if price_unit and seller and po.currency_id and seller.currency_id != po.currency_id:
price_unit = seller.currency_id.compute(price_unit, po.currency_id)
po_line = line.write({
'product_qty': line.product_qty + procurement_uom_po_qty,
'price_unit': price_unit,
'move_dest_ids': [(4, x.id) for x in values.get('move_dest_ids', [])]
})
vals = self._update_purchase_order_line(product_id, product_qty, product_uom, values, line, partner)
po_line = line.write(vals)
break
if not po_line:
vals = self._prepare_purchase_order_line(product_id, product_qty, product_uom, values, po, supplier)
@@ -948,6 +934,24 @@ class ProcurementRule(models.Model):
return schedule_date - relativedelta(days=int(seller.delay))
def _update_purchase_order_line(self, product_id, product_qty, product_uom, values, line, partner):
procurement_uom_po_qty = product_uom._compute_quantity(product_qty, product_id.uom_po_id)
seller = product_id._select_seller(
partner_id=partner,
quantity=line.product_qty + procurement_uom_po_qty,
date=line.order_id.date_order and line.order_id.date_order[:10],
uom_id=product_id.uom_po_id)
price_unit = self.env['account.tax']._fix_tax_included_price_company(seller.price, line.product_id.supplier_taxes_id, line.taxes_id, values['company_id']) if seller else 0.0
if price_unit and seller and line.order_id.currency_id and seller.currency_id != line.order_id.currency_id:
price_unit = seller.currency_id.compute(price_unit, line.order_id.currency_id)
return {
'product_qty': line.product_qty + procurement_uom_po_qty,
'price_unit': price_unit,
'move_dest_ids': [(4, x.id) for x in values.get('move_dest_ids', [])]
}
@api.multi
def _prepare_purchase_order_line(self, product_id, product_qty, product_uom, values, po, supplier):
procurement_uom_po_qty = product_uom._compute_quantity(product_qty, product_id.uom_po_id)
+1 -1
View File
@@ -57,7 +57,7 @@ class CustomerPortal(CustomerPortal):
if access_token:
values['no_breadcrumbs'] = True
values['access_token'] = access_token
values['portal_confirmation'] = request.env['ir.config_parameter'].sudo().get_param('sale.sale_portal_confirmation_options', default='none')
values['portal_confirmation'] = order.get_portal_confirmation_action()
if kwargs.get('error'):
values['error'] = kwargs['error']
@@ -31,7 +31,7 @@
<template id="portal_my_orders_payment" name="Payment on my orders" inherit_id="sale.portal_order_page">
<xpath expr="//t[@name='portal_confirmation_sign']" position="after">
<t t-if="not invoices and order.state in ('sent', 'sale') and portal_confirmation == 'pay' and order.payment_tx_id.state != 'done'" name="portal_confirmation_pay">
<t t-if="order.amount_total and not invoices and order.state in ('sent', 'sale') and portal_confirmation == 'pay' and order.payment_tx_id.state != 'done'" name="portal_confirmation_pay">
<a class="btn btn-primary ml8 pull-right" href="#portal_pay">
<i class="fa fa-arrow-circle-right"/> Pay Now
</a>
@@ -49,7 +49,7 @@
</div>
</xpath>
<xpath expr="//div[@id='portal_sign']" position="after">
<div class="row" t-if="not invoices and order.state in ('sent') and portal_confirmation == 'pay'" id="portal_pay">
<div class="row" t-if="order.amount_total and not invoices and order.state in ('sent', 'sale') and portal_confirmation == 'pay' and order.payment_tx_id.state != 'done'" id="portal_pay">
<div class="col-md-offset-3 col-md-6">
<div t-if="pms or s2s_acquirers or form_acquirers" id="payment_method" class="text-left col-md-13">
<h4 class="mb24">Pay with</h4>
+57 -48
View File
@@ -70,6 +70,13 @@ class AccountAnalyticLine(models.Model):
@api.multi
def _timesheet_compute_theorical_revenue(self):
for timesheet in self:
values = timesheet._timesheet_compute_theorical_revenue_values()
timesheet.write(values)
return True
@api.multi
def _timesheet_compute_theorical_revenue_values(self):
""" This method set the theorical revenue on the current timesheet lines.
If invoice on delivered quantity:
@@ -82,53 +89,55 @@ class AccountAnalyticLine(models.Model):
else:
0
"""
for timesheet in self:
# find the timesheet UoM
timesheet_uom = timesheet.product_uom_id
if not timesheet_uom: # fallback on default company timesheet UoM
timesheet_uom = self.env.user.company_id.project_time_mode_id
self.ensure_one()
timesheet = self
# default values
unit_amount = timesheet.unit_amount
so_line = timesheet.so_line
values = {
'timesheet_revenue': 0.0,
'timesheet_invoice_type': 'non_billable_project' if not timesheet.task_id else 'non_billable',
}
# set the revenue and billable type according to the product and the SO line
if timesheet.task_id and so_line.product_id.type == 'service':
# find the analytic account to convert revenue into its currency
analytic_account = timesheet.account_id
# convert the unit of mesure into hours
sale_price_hour = so_line.product_uom._compute_price(so_line.price_unit, timesheet_uom)
sale_price = so_line.currency_id.compute(sale_price_hour, analytic_account.currency_id) # amount from SO should be convert into analytic account currency
# find the timesheet UoM
timesheet_uom = timesheet.product_uom_id
if not timesheet_uom: # fallback on default company timesheet UoM
timesheet_uom = self.env.user.company_id.project_time_mode_id
# calculate the revenue on the timesheet
if so_line.product_id.invoice_policy == 'delivery':
values['timesheet_revenue'] = analytic_account.currency_id.round(unit_amount * sale_price * (1-(so_line.discount/100)))
values['timesheet_invoice_type'] = 'billable_time' if so_line.product_id.service_type == 'timesheet' else 'billable_fixed'
elif so_line.product_id.invoice_policy == 'order' and so_line.product_id.service_type == 'timesheet':
quantity_hour = unit_amount
if so_line.product_uom.category_id == timesheet_uom.category_id:
quantity_hour = so_line.product_uom._compute_quantity(so_line.product_uom_qty, timesheet_uom)
# compute the total revenue the SO since we are in fixed price
total_revenue_so = analytic_account.currency_id.round(quantity_hour * sale_price * (1-(so_line.discount/100)))
# compute the total revenue already existing (without the current timesheet line)
domain = [('so_line', '=', so_line.id)]
if timesheet.ids:
domain += [('id', 'not in', timesheet.ids)]
analytic_lines = timesheet.search(domain)
total_revenue_invoiced = sum(analytic_lines.mapped('timesheet_revenue'))
# compute (new) revenue of current timesheet line
values['timesheet_revenue'] = min(
analytic_account.currency_id.round(unit_amount * so_line.currency_id.compute(so_line.price_unit, analytic_account.currency_id) * (1-so_line.discount)),
total_revenue_so - total_revenue_invoiced
)
values['timesheet_invoice_type'] = 'billable_fixed'
# if the so line is already invoiced, and the delivered qty is still smaller than the ordered, then link the timesheet to the invoice
if so_line.invoice_status == 'invoiced':
values['timesheet_invoice_id'] = so_line.invoice_lines[0].invoice_id.id
elif so_line.product_id.invoice_policy == 'order' and so_line.product_id.service_type != 'timesheet':
values['timesheet_invoice_type'] = 'billable_fixed'
timesheet.write(values)
return True
# default values
unit_amount = timesheet.unit_amount
so_line = timesheet.so_line
values = {
'timesheet_revenue': 0.0,
'timesheet_invoice_type': 'non_billable_project' if not timesheet.task_id else 'non_billable',
}
# set the revenue and billable type according to the product and the SO line
if timesheet.task_id and so_line.product_id.type == 'service':
# find the analytic account to convert revenue into its currency
analytic_account = timesheet.account_id
# convert the unit of mesure into hours
sale_price_hour = so_line.product_uom._compute_price(so_line.price_unit, timesheet_uom)
sale_price = so_line.currency_id.compute(sale_price_hour, analytic_account.currency_id) # amount from SO should be convert into analytic account currency
# calculate the revenue on the timesheet
if so_line.product_id.invoice_policy == 'delivery':
values['timesheet_revenue'] = analytic_account.currency_id.round(unit_amount * sale_price * (1-(so_line.discount/100)))
values['timesheet_invoice_type'] = 'billable_time' if so_line.product_id.service_type == 'timesheet' else 'billable_fixed'
elif so_line.product_id.invoice_policy == 'order' and so_line.product_id.service_type == 'timesheet':
quantity_hour = unit_amount
if so_line.product_uom.category_id == timesheet_uom.category_id:
quantity_hour = so_line.product_uom._compute_quantity(so_line.product_uom_qty, timesheet_uom)
# compute the total revenue the SO since we are in fixed price
total_revenue_so = analytic_account.currency_id.round(quantity_hour * sale_price * (1-(so_line.discount/100)))
# compute the total revenue already existing (without the current timesheet line)
domain = [('so_line', '=', so_line.id)]
if timesheet.ids:
domain += [('id', 'not in', timesheet.ids)]
analytic_lines = timesheet.search(domain)
total_revenue_invoiced = sum(analytic_lines.mapped('timesheet_revenue'))
# compute (new) revenue of current timesheet line
values['timesheet_revenue'] = min(
analytic_account.currency_id.round(unit_amount * so_line.currency_id.compute(so_line.price_unit, analytic_account.currency_id) * (1-so_line.discount)),
total_revenue_so - total_revenue_invoiced
)
values['timesheet_invoice_type'] = 'billable_fixed'
# if the so line is already invoiced, and the delivered qty is still smaller than the ordered, then link the timesheet to the invoice
if so_line.invoice_status == 'invoiced':
values['timesheet_invoice_id'] = so_line.invoice_lines[0].invoice_id.id
elif so_line.product_id.invoice_policy == 'order' and so_line.product_id.service_type != 'timesheet':
values['timesheet_invoice_type'] = 'billable_fixed'
return values
+4
View File
@@ -14,6 +14,10 @@ The service is provided by the In App Purchase Odoo platform.
'data': [
'wizard/send_sms_views.xml',
'views/res_partner_views.xml',
'views/templates.xml',
],
'qweb': [
'static/src/xml/sms_widget.xml',
],
'installable': True,
'auto_install': True,
+120
View File
@@ -0,0 +1,120 @@
odoo.define('sms.sms_widget', function (require) {
"use strict";
var basicFields = require('web.basic_fields');
var core = require('web.core');
var fieldRegistry = require('web.field_registry');
var framework = require('web.framework');
var FieldText = basicFields.FieldText;
var QWeb = core.qweb;
/**
* SmsWidget is a widget to display a textarea (the body) and a text representing
* the number of SMS and the number of characters. This text is computed every
* time the user changes the body.
*/
var SmsWidget = FieldText.extend({
/**
* @constructor
*/
init: function () {
this._super.apply(this, arguments);
this.nbrChar = 0;
this.nbrSMS = 0;
this.encoding = "GSM7";
this.tagName = 'div';
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* Compute the number of characters and sms
* @private
*/
_compute: function () {
var content = this._getValue();
this.encoding = this._extractEncoding(content);
this.nbrChar = content.length;
this.nbrChar += (content.match(/\n/g) || []).length;
this.nbrSMS = this._countSMS(this.nbrChar, this.encoding);
this._renderSMS();
},
/**
* Count the number of SMS of the content
* @private
* @returns {integer} Number of SMS
*/
_countSMS: function () {
if (this.nbrChar === 0) {
return 0;
}
if (this.encoding === 'UNICODE') {
if (this.nbrChar <= 70) {
return 1;
}
return Math.ceil(this.nbrChar / 67);
}
if (this.nbrChar <= 160) {
return 1;
}
return Math.ceil(this.nbrChar / 153);
},
/**
* @private
* @override
*/
_renderEdit: function () {
this.$el.empty();
this._prepareInput($('<textarea/>')).appendTo(this.$el);
this.$el.append($(QWeb.render("sms.sms_count", {})));
this._compute();
},
/**
* Extract the encoding depending on the characters in the content
* @private
* @param {String} content Content of the SMS
* @returns {String} Encoding of the content (GSM7 or UNICODE)
*/
_extractEncoding: function (content) {
if (String(content).match(RegExp("^[@£$¥èéùìòÇ\\nØø\\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !\\\"#¤%&'()*+,-./0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà]*$"))) {
return 'GSM7';
}
return 'UNICODE';
},
/**
* Render the number of characters, sms and the encoding.
* @private
*/
_renderSMS: function () {
this.$('.o_sms_count').text(this.nbrChar + ' / ' + this.nbrSMS + ' SMS (' + this.encoding + ') ');
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* @override
* @private
*/
_onChange: function () {
this._super.apply(this, arguments);
this._compute();
},
/**
* @override
* @private
*/
_onInput: function () {
this._super.apply(this, arguments);
this._compute();
},
});
fieldRegistry.add('sms_widget', SmsWidget);
return SmsWidget;
});
@@ -0,0 +1,67 @@
odoo.define('sms.sms_widget_tests', function (require) {
"use strict";
var FormView = require('web.FormView');
var testUtils = require('web.test_utils');
var createView = testUtils.createView;
QUnit.module('fields', {
beforeEach: function () {
this.data = {
partner: {
fields: {
message: {string: "message", type: "text"},
},
records: [{
id: 1,
message: "",
}]
},
};
}
}, function () {
QUnit.module('SmsWidget');
QUnit.test('Sms widgets are correctly rendered', function (assert) {
assert.expect(9);
var form = createView({
View: FormView,
model: 'partner',
data: this.data,
arch: '<form><sheet><field name="message" widget="sms_widget"/></sheet></form>',
});
form.$buttons.find('.o_form_button_edit').click();
assert.ok(form.$('.o_sms_count').length, "Should have a sms counter");
assert.strictEqual(form.$('.o_sms_count').text(), '0 / 0 SMS (GSM7) ', 'Should be "0 / 0 SMS (GSM7) " by default');
// GSM-7
form.$('.o_input').val("Hello from Odoo").trigger('input');
assert.strictEqual(form.$('.o_sms_count').text(), '15 / 1 SMS (GSM7) ', 'Should be "15 / 1 SMS (GSM7) " for "Hello from Odoo"');
// GSM-7 with \n => this one count as 2 characters
form.$('.o_input').val("Hello from Odoo\n").trigger('input');
assert.strictEqual(form.$('.o_sms_count').text(), '17 / 1 SMS (GSM7) ', 'Should be "17 / 1 SMS (GSM7) " for "Hello from Odoo\\n"');
// Unicode => ê
form.$('.o_input').val("Hêllo from Odoo").trigger('input');
assert.strictEqual(form.$('.o_sms_count').text(), '15 / 1 SMS (UNICODE) ', 'Should be "15 / 1 SMS (UNICODE) " for "Hêllo from Odoo"');
// GSM-7 with 160c
var text = Array(161).join('a');
form.$('.o_input').val(text).trigger('input');
assert.strictEqual(form.$('.o_sms_count').text(), '160 / 1 SMS (GSM7) ', 'Should be "160 / 1 SMS (GSM7) " for 160 x "a"');
// GSM-7 with 161c
text = Array(162).join('a');
form.$('.o_input').val(text).trigger('input');
assert.strictEqual(form.$('.o_sms_count').text(), '161 / 2 SMS (GSM7) ', 'Should be "161 / 2 SMS (GSM7) " for 161 x "a"');
// Unicode with 70c
text = Array(71).join('ê');
form.$('.o_input').val(text).trigger('input');
assert.strictEqual(form.$('.o_sms_count').text(), '70 / 1 SMS (UNICODE) ', 'Should be "70 / 1 SMS (UNICODE) " for 70 x "ê"');
// Unicode with 71c
text = Array(72).join('ê');
form.$('.o_input').val(text).trigger('input');
assert.strictEqual(form.$('.o_sms_count').text(), '71 / 2 SMS (UNICODE) ', 'Should be "71 / 2 SMS (UNICODE) " for 71 x "ê"');
form.destroy();
});
});
});
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<templates>
<t t-name="sms.sms_count">
<span class="pull-right"><span class="text-muted o_sms_count"></span> <a href="https://iap-services.odoo.com/iap/sms/pricing" class="fa fa-lg fa-info"/></span>
</t>
</templates>
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<template id="assets_backend" name="sms_assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/sms/static/src/js/sms_widget.js"></script>
</xpath>
</template>
<template id="qunit_suite" name="sms_widget_tests" inherit_id="web.qunit_suite">
<xpath expr="." position="inside">
<script type="text/javascript" src="/sms/static/src/tests/sms_widget_test.js"></script>
</xpath>
</template>
</data>
</odoo>
+1 -2
View File
@@ -71,8 +71,7 @@ class SendSMS(models.TransientModel):
phone_numbers = []
no_phone_partners = []
for partner in partners:
default_field_name = 'mobile' if partner.mobile else 'phone'
number = self._sms_sanitization(partner, self.env.context.get('field_name') or default_field_name)
number = self._sms_sanitization(partner, self.env.context.get('field_name') or 'mobile')
if number:
phone_numbers.append(number)
else:
+1 -1
View File
@@ -9,7 +9,7 @@
<sheet>
<group>
<field name="recipients"/>
<field name="message" widget="text"/>
<field name="message" widget="sms_widget"/>
</group>
</sheet>
<footer>
+2 -1
View File
@@ -816,7 +816,8 @@ class StockMove(models.Model):
# Find a candidate move line to update or create a new one.
for reserved_quant, quantity in quants:
to_update = self.move_line_ids.filtered(lambda m: m.location_id.id == reserved_quant.location_id.id and m.lot_id.id == reserved_quant.lot_id.id and m.package_id.id == reserved_quant.package_id.id and m.owner_id.id == reserved_quant.owner_id.id)
to_update = self.move_line_ids.filtered(lambda m: m.product_id.tracking != 'serial' and
m.location_id.id == reserved_quant.location_id.id and m.lot_id.id == reserved_quant.lot_id.id and m.package_id.id == reserved_quant.package_id.id and m.owner_id.id == reserved_quant.owner_id.id)
if to_update:
to_update[0].with_context(bypass_reservation_update=True).product_uom_qty += self.product_id.uom_id._compute_quantity(quantity, self.product_uom, rounding_method='HALF-UP')
else:
+7 -2
View File
@@ -340,8 +340,13 @@ class StockMoveLine(models.Model):
raise UserError(_('You can not delete product moves if the picking is done. You can only correct the done quantities.'))
# Unlinking a move line should unreserve.
if ml.product_id.type == 'product' and not ml.location_id.should_bypass_reservation() and not float_is_zero(ml.product_qty, precision_digits=precision):
self.env['stock.quant']._update_reserved_quantity(ml.product_id, ml.location_id, -ml.product_qty, lot_id=ml.lot_id,
package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
try:
self.env['stock.quant']._update_reserved_quantity(ml.product_id, ml.location_id, -ml.product_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
except UserError:
if ml.lot_id:
self.env['stock.quant']._update_reserved_quantity(ml.product_id, ml.location_id, -ml.product_qty, lot_id=False, package_id=ml.package_id, owner_id=ml.owner_id, strict=True)
else:
raise
moves = self.mapped('move_id')
res = super(StockMoveLine, self).unlink()
if moves:
+71
View File
@@ -606,6 +606,55 @@ class StockMove(TransactionCase):
quants = self.env['stock.quant']._gather(self.product2, self.stock_location)
self.assertEqual(len(quants), 0)
def test_mixed_tracking_reservation_8(self):
""" Send one product tracked by lot to a customer. In your stock, there are one tracked and
one untracked quant. Reserve the move, then edit the lot to one not present in stock. The
system will update the reservation and use the untracked quant. Now unreserve, no error
should happen
"""
lot1 = self.env['stock.production.lot'].create({
'name': 'lot1',
'product_id': self.product2.id,
})
# at first, we only make the tracked quant available in stock to make sure this one is selected
self.env['stock.quant']._update_available_quantity(self.product2, self.stock_location, 1, lot_id=lot1)
# creation
move1 = self.env['stock.move'].create({
'name': 'test_mixed_tracking_reservation_7',
'location_id': self.stock_location.id,
'location_dest_id': self.customer_location.id,
'product_id': self.product2.id,
'product_uom': self.uom_unit.id,
'product_uom_qty': 1.0,
})
move1._action_confirm()
move1._action_assign()
self.assertEqual(move1.reserved_availability, 1.0)
self.assertEqual(move1.move_line_ids.lot_id.id, lot1.id)
# change the lot_id to one not available in stock while an untracked quant is available
self.env['stock.quant']._update_available_quantity(self.product2, self.stock_location, 1)
lot2 = self.env['stock.production.lot'].create({
'name': 'lot2',
'product_id': self.product2.id,
})
move1.move_line_ids.lot_id = lot2
self.assertEqual(move1.reserved_availability, 1.0)
self.assertEqual(move1.move_line_ids.lot_id.id, lot2.id)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.stock_location, strict=True), 0.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.stock_location, lot_id=lot1, strict=True), 1.0)
# unreserve
move1._do_unreserve()
self.assertEqual(move1.reserved_availability, 0.0)
self.assertEqual(len(move1.move_line_ids), 0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.stock_location, strict=True), 1.0)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.stock_location, lot_id=lot1, strict=True), 1.0)
def test_putaway_1(self):
""" Receive products from a supplier. Check that putaway rules are rightly applied on
the receipt move line.
@@ -756,6 +805,28 @@ class StockMove(TransactionCase):
self.assertEqual(customer_quants.quantity, 30)
self.assertEqual(customer_quants.reserved_quantity, 0)
def test_availability_5(self):
""" Check that rerun action assign only create new stock move
lines instead of adding quantity in existing one.
"""
self.env['stock.quant']._update_available_quantity(self.product2, self.stock_location, 2.0)
# move from shelf1
move = self.env['stock.move'].create({
'name': 'test_edit_moveline_1',
'location_id': self.stock_location.id,
'location_dest_id': self.customer_location.id,
'product_id': self.product2.id,
'product_uom': self.uom_unit.id,
'product_uom_qty': 4.0,
})
move._action_confirm()
move._action_assign()
self.env['stock.quant']._update_available_quantity(self.product2, self.stock_location, 4.0)
move._action_assign()
self.assertEqual(len(move.move_line_ids), 4.0)
def test_unreserve_1(self):
""" Check that unreserving a stock move sets the products reserved as available and
set the state back to confirmed.
@@ -111,6 +111,15 @@ class TestMessageValues(common.BaseFunctionalTest, common.MockEmails):
self.assertNotIn('mail.test', msg.message_id)
self.assertNotIn('-%d-' % self.alias_record.id, msg.message_id)
def test_mail_message_base64_image(self):
msg = self.env['mail.message'].sudo(self.user_employee).create({
'body': 'taratata <img src="data:image/png;base64,iV/+OkI=" width="2"> <img src="data:image/png;base64,iV/+OkI=" width="2">',
})
self.assertEqual(len(msg.attachment_ids), 1)
body = '<p>taratata <img src="/web/image/%s?access_token=%s" alt="image0" width="2"> <img src="/web/image/%s?access_token=%s" alt="image0" width="2"></p>'
body = body % (msg.attachment_ids[0].id, msg.attachment_ids[0].access_token, msg.attachment_ids[0].id, msg.attachment_ids[0].access_token)
self.assertEqual(msg.body, body)
class TestMessageAccess(common.BaseFunctionalTest, common.MockEmails):
@@ -511,7 +511,7 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
// TODO this will tell the renderer to rerender the widget that
// asked for the discard but will unfortunately lose the click
// made on another row if any
self._confirmChange(self.handle, [ev.data.fieldName], ev)
self._confirmChange(recordID, [ev.data.fieldName], ev)
.always(ev.data.onSuccess);
})
.fail(ev.data.onFailure);
@@ -254,7 +254,10 @@ var BasicRenderer = AbstractRenderer.extend({
if ('readonly' in modifiers && element.widget) {
var mode = modifiers.readonly ? 'readonly' : modifiersData.baseMode;
if (mode !== element.widget.mode) {
self._rerenderFieldWidget(element.widget, record, mode);
self._rerenderFieldWidget(element.widget, record, {
keepBaseMode: true,
mode: mode,
});
return; // Rerendering already applied the modifiers, no need to go further
}
}
@@ -406,12 +409,25 @@ var BasicRenderer = AbstractRenderer.extend({
* @param {Object} record
* @param {jQuery|AbstractField} [element]
* @param {Object} [options]
* @param {Object} [options.callback] - the callback to call on registration
* and on modifiers updates
* @param {Object} [options.callback] the callback to call on registration
* and on modifiers updates
* @param {boolean} [options.keepBaseMode=false] this function registers the
* 'baseMode' of the node; this is a field widget specific settings which
* represents the generic mode of the widget, regardless of its modifiers
* (the interesting case is the list view: all widgets are supposed to be
* in the baseMode 'readonly', except the ones that are in the line that
* is currently being edited).
* With option 'keepBaseMode' set to true, the current baseMode of the
* node isn't overridden (this is particularily useful when a field widget
* is re-rendered because its readonly modifier changed, as in this case,
* we don't want to change its base mode).
* @param {string} [options.mode] the 'baseMode' of the node is set to this
* value (if not given, it is set to this.mode, the mode of the renderer)
* @returns {Object} for code efficiency, returns the last evaluated
* modifiers for the given node and record.
* modifiers for the given node and record.
*/
_registerModifiers: function (node, record, element, options) {
options = options || {};
// Check if we already registered the modifiers for the given node
// If yes, this is simply an update of the related element
// If not, check the modifiers to see if it needs registration
@@ -428,12 +444,11 @@ var BasicRenderer = AbstractRenderer.extend({
this.allModifiersData.push(modifiersData);
}
}
// we register here the base mode of the node. This is a field widget
// specific settings which represents the generic mode for the widget,
// regardless of its modifiers. The interesting case is the list view:
// all widgets are supposed to be in the baseMode 'readonly', except the
// ones that are in the line that is currently being edited.
modifiersData.baseMode = (options && options.mode) || this.mode;
// Compute node's base mode if necessary
if (!options.keepBaseMode) {
modifiersData.baseMode = options.mode || this.mode;
}
// Evaluate if necessary
if (!modifiersData.evaluatedModifiers[record.id]) {
@@ -497,13 +512,16 @@ var BasicRenderer = AbstractRenderer.extend({
* @private
* @param {Object} node
* @param {Object} record
* @param {Object} [options]
* @param {Object} [options] passed to @_registerModifiers
* @param {string} [options.mode] either 'edit' or 'readonly' (defaults to
* this.mode, the mode of the renderer)
* @returns {jQueryElement}
*/
_renderFieldWidget: function (node, record, options) {
options = options || {};
var fieldName = node.attrs.name;
// Register the node-associated modifiers
var mode = options && options.mode || this.mode;
var mode = options.mode || this.mode;
var modifiers = this._registerModifiers(node, record, null, options);
// Initialize and register the widget
// Readonly status is known as the modifiers have just been registered
@@ -545,7 +563,8 @@ var BasicRenderer = AbstractRenderer.extend({
&& !element.widget.isSet()
));
},
mode: mode
keepBaseMode: !!options.keepBaseMode,
mode: mode,
});
self._postProcessField(widget, node);
});
@@ -614,11 +633,11 @@ var BasicRenderer = AbstractRenderer.extend({
* @private
* @param {Widget} widget
* @param {Object} record
* @param {string} mode either 'readonly' or 'edit'
* @param {Object} [options] options passed to @_renderFieldWidget
*/
_rerenderFieldWidget: function (widget, record, mode) {
_rerenderFieldWidget: function (widget, record, options) {
// Render the new field widget
var $el = this._renderFieldWidget(widget.__node, record, {mode: mode});
var $el = this._renderFieldWidget(widget.__node, record, options);
widget.$el.replaceWith($el);
// Destroy the old widget and position the new one at the old one's
@@ -545,7 +545,6 @@ var PivotModel = AbstractModel.extend({
var data = Array.prototype.slice.call(arguments);
if (data[0][0].__count === 0) {
self.data.has_data = false;
return;
}
self._prepareData(data);
});
+4 -1
View File
@@ -630,7 +630,7 @@ QUnit.module('Views', {
});
QUnit.test('readonly attrs on fields are re-evaluated on field change', function (assert) {
assert.expect(3);
assert.expect(4);
var form = createView({
View: FormView,
@@ -656,6 +656,9 @@ QUnit.module('Views', {
form.$('.o_field_boolean input').click();
assert.strictEqual(form.$('span[name="foo"]').length, 1,
"the foo field widget should have been rerendered to now be readonly again");
form.$('.o_field_boolean input').click();
assert.strictEqual(form.$('input[name="foo"]').length, 1,
"the foo field widget should have been rerendered to now be editable again");
form.destroy();
});
+30 -3
View File
@@ -1929,7 +1929,7 @@ QUnit.module('Views', {
});
QUnit.test('readonly attrs on fields are re-evaluated on field change', function (assert) {
assert.expect(7);
assert.expect(9);
var list = createView({
View: ListView,
@@ -1963,9 +1963,14 @@ QUnit.module('Views', {
assert.strictEqual(list.$('tbody td.o_readonly_modifier').length, 3,
"the foo field widget parent cell should now be readonly again");
// Reswitch the cell to editable and save the row
list.$('tbody tr:nth(0) td:nth(2) input').click();
list.$('thead').click();
assert.strictEqual(list.$('tbody tr:nth(0) td:nth(1) > input[name="foo"]').length, 1,
"the foo field widget should have been rerendered as editable again");
assert.strictEqual(list.$('tbody td.o_readonly_modifier').length, 2,
"the foo field widget parent cell should not be readonly again");
// Click outside to leave edition mode
list.$el.click();
assert.strictEqual(list.$('tbody td.o_readonly_modifier').length, 2,
"there should be 2 readonly foo cells in readonly mode");
@@ -2773,6 +2778,28 @@ QUnit.module('Views', {
list.destroy();
});
QUnit.test('pressing ESC discard the current line changes (with required)', function (assert) {
assert.expect(3);
var list = createView({
View: ListView,
model: 'foo',
data: this.data,
arch: '<tree editable="top"><field name="foo" required="1"/></tree>',
});
list.$buttons.find('.o_list_button_add').click();
list.$('input[name="foo"]').trigger({type: 'keydown', which: $.ui.keyCode.ESCAPE});
assert.strictEqual(list.$('tr.o_data_row').length, 4,
"should have 4 data row in list");
assert.strictEqual(list.$('tr.o_data_row.o_selected_row').length, 0,
"no rows should be selected");
assert.ok(!list.$buttons.find('.o_list_button_save').is(':visible'),
"should not have a visible save button");
list.destroy();
});
QUnit.test('field with password attribute', function (assert) {
assert.expect(2);
+27 -2
View File
@@ -1,7 +1,6 @@
odoo.define('web.pivot_tests', function (require) {
"use strict";
var Context = require('web.Context');
var core = require('web.core');
var PivotView = require('web.PivotView');
var testUtils = require('web.test_utils');
@@ -739,7 +738,33 @@ QUnit.module('Views', {
},
});
$('.o_pivot_download').click();
pivot.$buttons.find('.o_pivot_download').click();
pivot.destroy();
});
QUnit.test('can download a file without data', function (assert) {
assert.expect(1);
this.data.partner.records = [];
var pivot = createView({
View: PivotView,
model: "partner",
data: this.data,
arch: '<pivot>' +
'<field name="date" interval="month" type="col"/>' +
'<field name="foo" type="measure"/>' +
'</pivot>',
session: {
get_file: function (args) {
assert.strictEqual(args.url, '/web/pivot/export_xls',
"should call get_file with correct parameters");
args.complete();
},
},
});
pivot.$buttons.find('.o_pivot_download').click();
pivot.destroy();
});
+11 -4
View File
@@ -146,6 +146,9 @@ class Web_Editor(http.Controller):
# therefore we have to recover the files from the request object
Attachments = request.env['ir.attachment'] # registry for the attachment table
res_model = kwargs.get('res_model', 'ir.ui.view')
res_id = res_model != 'ir.ui.view' and kwargs.get('res_id') or None
uploads = []
message = None
if not upload: # no image provided, storing the link and the image name
@@ -155,9 +158,11 @@ class Web_Editor(http.Controller):
'type': 'url',
'url': url,
'public': True,
'res_model': 'ir.ui.view',
'res_id': res_id,
'res_model': res_model,
})
uploads += attachment.read(['name', 'mimetype', 'checksum', 'url'])
attachment.generate_access_token()
uploads += attachment.read(['name', 'mimetype', 'checksum', 'url', 'res_id', 'res_model', 'access_token'])
else: # images provided
try:
attachments = request.env['ir.attachment']
@@ -180,10 +185,12 @@ class Web_Editor(http.Controller):
'datas': base64.b64encode(data),
'datas_fname': c_file.filename,
'public': True,
'res_model': 'ir.ui.view',
'res_id': res_id,
'res_model': res_model,
})
attachment.generate_access_token()
attachments += attachment
uploads += attachments.read(['name', 'mimetype', 'checksum', 'url'])
uploads += attachments.read(['name', 'mimetype', 'checksum', 'url', 'res_id', 'res_model', 'access_token'])
except Exception as e:
logger.exception("Failed to upload image to attachment")
message = pycompat.text_type(e)
@@ -118,6 +118,7 @@ var FieldTextHtmlSimple = basic_fields.DebouncedField.extend(TranslatableFieldMi
*/
_getValue: function () {
if (this.nodeOptions['style-inline']) {
transcoder.linkImgToAttachmentThumbnail(this.$content);
transcoder.classToStyle(this.$content);
transcoder.fontToImg(this.$content);
}
@@ -133,6 +134,8 @@ var FieldTextHtmlSimple = basic_fields.DebouncedField.extend(TranslatableFieldMi
this.$textarea.summernote(this._getSummernoteConfig());
this.$content = this.$('.note-editable:first');
this.$content.html(this._textToHtml(this.value));
this.$content.data('oe-id', this.recordData.res_id || this.res_id);
this.$content.data('oe-model', this.recordData.model || this.model);
// trigger a mouseup to refresh the editor toolbar
this.$content.trigger('mouseup');
if (this.nodeOptions['style-inline']) {
@@ -1080,8 +1080,12 @@ var SummernoteManager = Class.extend(mixins.EventDispatcherMixin, {
return;
}
data.__alreadyDone = true;
var mediaDialog = new weWidgets.MediaDialog(this,
data.options || {},
_.extend({
res_model: data.$editable.data('oe-model'),
res_id: data.$editable.data('oe-id'),
}, data.options),
data.$editable,
data.media
);
@@ -872,7 +872,12 @@ registry.background = SnippetOption.extend({
// Put fake image in the DOM, edit it and use it as background-image
var $image = $('<img/>', {class: 'hidden', src: value}).appendTo(this.$target);
var _editor = new widget.MediaDialog(this, {}, null, $image[0]).open();
var $editable = this.$target.closest('.o_editable');
var options = {
res_model: $editable.data('oe-model'),
res_id: $editable.data('oe-id'),
};
var _editor = new widget.MediaDialog(this, options, null, $image[0]).open();
_editor.opened(function () {
_editor.$('[href="#editor-media-video"], [href="#editor-media-icon"]').addClass('hidden');
});
@@ -913,15 +913,21 @@ range.WrappedRange.prototype.deleteContents = function (towrite) {
return this;
}
var prevBP = dom.removeBetween(this.sc, this.so, this.ec, this.eo, towrite);
var r;
var image = this.isOnImg();
if (image) {
// If the range matches/is in an image, then the image is to be removed
// and the cursor moved to its previous position
var parentNode = image.parentNode;
var index = _.indexOf(parentNode.childNodes, image);
parentNode.removeChild(image);
r = new range.WrappedRange(parentNode, index, parentNode, index);
} else {
r = dom.removeBetween(this.sc, this.so, this.ec, this.eo, towrite);
}
$(dom.node(prevBP.sc)).trigger("click"); // trigger click to disable and reanable editor and image handler
return new range.WrappedRange(
prevBP.sc,
prevBP.so,
prevBP.ec,
prevBP.eo
);
$(dom.node(r.sc)).trigger("click"); // trigger click to disable and reanable editor and image handler
return new range.WrappedRange(r.sc, r.so, r.ec, r.eo);
};
range.WrappedRange.prototype.clean = function (mergeFilter, all) {
var node = dom.node(this.sc === this.ec ? this.sc : this.commonAncestor());
@@ -1258,7 +1264,7 @@ $.summernote.pluginEvents.visible = function (event, editor, layoutInfo) {
};
function remove_table_content(r) {
var nodes = dom.listBetween(r.sc, r.ec);
var nodes = dom.listBetween(r.sc, r.ec, r.so, r.eo);
if (dom.isText(r.sc)) {
r.sc.textContent = r.sc.textContent.slice(0, r.so);
}
@@ -18,7 +18,7 @@ function getMatchedCSSRules(a) {
var sheets = document.styleSheets;
for (i = sheets.length-1 ; i >= 0 ; i--) {
var rules;
if (sheets[i].rules) {
if (sheets[i].hasOwnProperty('rules')) {
rules = sheets[i].rules;
} else {
// try...catch because Firefox not able to enumerate
@@ -259,10 +259,40 @@ function styleToClass($editable) {
$c.remove();
}
/**
* Converts css display for attachment link to real image.
* Without this post process, the display depends on the css and the picture
* does not appear when we use the html without css (to send by email for e.g.)
*
* @param {jQuery} $editable
*/
function attachmentThumbnailToLinkImg($editable) {
$editable.find('a[href*="/web/content/"][data-mimetype]:empty').each(function () {
var $link = $(this);
var $img = $('<img/>')
.attr('src', $link.css('background-image').replace(/(^url\(['"])|(['"]\)$)/g, ''))
.css('height', Math.max(1, $link.height()) + 'px')
.css('width', Math.max(1, $link.width()) + 'px');
$link.append($img);
});
}
/**
* Revert attachmentThumbnailToLinkImg changes
*
* @see attachmentThumbnailToLinkImg
* @param {jQuery} $editable
*/
function linkImgToAttachmentThumbnail($editable) {
$editable.find('a[href*="/web/content/"][data-mimetype] > img').remove();
}
return {
fontToImg: fontToImg,
imgToFont: imgToFont,
classToStyle: classToStyle,
styleToClass: styleToClass,
attachmentThumbnailToLinkImg: attachmentThumbnailToLinkImg,
linkImgToAttachmentThumbnail: linkImgToAttachmentThumbnail,
};
});
@@ -53,6 +53,7 @@ snippet_editor.Class.include({
this._super.apply(this, arguments);
var $editable = $('#editable_area');
transcoder.linkImgToAttachmentThumbnail($editable);
transcoder.fontToImg($editable);
transcoder.classToStyle($editable);
@@ -120,7 +120,13 @@ var ImageDialog = Widget.extend({
this._super.apply(this, arguments);
this.options = options || {};
this.accept = this.options.accept || this.options.document ? "*/*" : "image/*";
this.domain = this.options.domain || ['|', ['mimetype', '=', false], ['mimetype', this.options.document ? 'not in' : 'in', ['image/gif', 'image/jpe', 'image/jpeg', 'image/jpg', 'image/gif', 'image/png']]];
if (this.options.res_id) {
this.domain = ['|',
'&', ['res_model', '=', this.options.res_model], ['res_id', '=', this.options.res_id],
['res_model', '=', 'ir.ui.view']];
} else {
this.domain = [['res_model', '=', 'ir.ui.view']];
}
this.parent = parent;
this.old_media = media;
this.media = media;
@@ -171,6 +177,7 @@ var ImageDialog = Widget.extend({
}
},
save: function () {
var self = this;
if (this.options.select_images) {
return this.images;
}
@@ -181,34 +188,55 @@ var ImageDialog = Widget.extend({
img = _.find(this.images, function (img) { return img.id === id;});
}
var media;
if (!img.is_document) {
if (this.media.tagName !== "IMG" || !this.old_media) {
this.add_class = "pull-left";
this.style = {"width": "100%"};
}
if (this.media.tagName !== "IMG") {
media = document.createElement('img');
$(this.media).replaceWith(media);
this.media = media;
}
this.media.setAttribute('src', img.src);
} else {
if (this.media.tagName !== "A") {
$('.note-control-selection').hide();
media = document.createElement('a');
$(this.media).replaceWith(media);
this.media = media;
}
this.media.setAttribute('href', '/web/content/' + img.id + '?unique=' + img.checksum + '&download=true');
$(this.media).addClass('o_image').attr('title', img.name).attr('data-mimetype', img.mimetype);
var def = $.when();
if (!img.access_token) {
def = this._rpc({
model: 'ir.attachment',
method: 'generate_access_token',
args: [[img.id]]
}).then(function (access_token) {
img.access_token = access_token[0];
});
}
$(this.media).attr('alt', img.alt);
var style = this.style;
if (style) { $(this.media).css(style); }
return def.then(function () {
var media;
if (!img.is_document) {
if (img.access_token && self.options.res_model !== 'ir.ui.view') {
img.src += _.str.sprintf('?access_token=%s', img.access_token);
}
if (self.media.tagName !== "IMG" || !self.old_media) {
self.add_class = "pull-left";
self.style = {"width": "100%"};
}
if (self.media.tagName !== "IMG") {
media = document.createElement('img');
$(self.media).replaceWith(media);
self.media = media;
}
self.media.setAttribute('src', img.src);
} else {
if (self.media.tagName !== "A") {
$('.note-control-selection').hide();
media = document.createElement('a');
$(self.media).replaceWith(media);
self.media = media;
}
var href = '/web/content/' + img.id + '?';
if (img.access_token && self.options.res_model !== 'ir.ui.view') {
href += _.str.sprintf('access_token=%s&', img.access_token);
}
href += 'unique=' + img.checksum + '&download=true';
self.media.setAttribute('href', href);
$(self.media).addClass('o_image').attr('title', img.name).attr('data-mimetype', img.mimetype);
}
return this.media;
$(self.media).attr('alt', img.alt);
var style = self.style;
if (style) { $(self.media).css(style); }
return self.media;
});
},
clear: function () {
this.media.className = this.media.className.replace(/(^|\s+)((img(\s|$)|img-(?!circle|rounded|thumbnail))[^\s]*)/g, ' ');
@@ -282,7 +310,7 @@ var ImageDialog = Widget.extend({
}
},
fetch_existing: function (needle) {
var domain = [['res_model', '=', 'ir.ui.view']].concat(this.domain);
var domain = this.domain.concat(['|', ['mimetype', '=', false], ['mimetype', this.options.document ? 'not in' : 'in', ['image/gif', 'image/jpe', 'image/jpeg', 'image/jpg', 'image/gif', 'image/png']]]);
if (needle && needle.length) {
domain.push('|', ['datas_fname', 'ilike', needle], ['name', 'ilike', needle]);
}
@@ -292,7 +320,7 @@ var ImageDialog = Widget.extend({
args: [],
kwargs: {
domain: domain,
fields: ['name', 'mimetype', 'checksum', 'url', 'type'],
fields: ['name', 'mimetype', 'checksum', 'url', 'type', 'res_id', 'res_model', 'access_token'],
order: [{name: 'id', asc: false}],
context: weContext.get(),
}
@@ -305,7 +333,7 @@ var ImageDialog = Widget.extend({
return (r.url || r.id);
});
_.each(this.records, function (record) {
record.src = record.url || _.str.sprintf('/web/image/%s/%s', record.id, record.name); // Name is added for SEO purposes
record.src = record.url || _.str.sprintf('/web/image/%s/%s', record.id, encodeURI(record.name)); // Name is added for SEO purposes
record.is_document = !(/gif|jpe|jpg|png/.test(record.mimetype));
});
this.display_attachments();
@@ -1001,18 +1029,21 @@ var MediaDialog = Dialog.extend({
return this._super.apply(this, arguments);
},
save: function () {
var self = this;
var args = arguments;
var _super = this._super;
if (this.options.select_images) {
this.final_data = this.active.save();
this._super.apply(this, arguments);
return;
return $.when(this.active.save()).then(function (data) {
self.final_data = data;
return _super.apply(self, args);
});
}
if (this.rte) {
this.range.select();
this.rte.historyRecordUndo(this.media);
}
var self = this;
if (self.media) {
if (this.media) {
this.media.innerHTML = "";
if (this.active !== this.imageDialog && this.active !== this.documentDialog) {
this.imageDialog.clear();
@@ -1029,27 +1060,27 @@ var MediaDialog = Dialog.extend({
this.range.insertNode(this.media, true);
this.active.media = this.media;
}
this.active.save();
if (this.active.add_class) {
$(this.active.media).addClass(this.active.add_class);
}
var media = this.active.media;
return $.when(this.active.save()).then(function () {
if (self.active.add_class) {
$(self.active.media).addClass(self.active.add_class);
}
var media = self.active.media;
this.final_data = [media, self.old_media];
$(document.body).trigger("media-saved", this.final_data);
$(self.old_media).trigger("save", this.final_data);
$(this.final_data).trigger('input');
self.final_data = [media, self.old_media];
$(document.body).trigger("media-saved", self.final_data);
$(self.old_media).trigger("save", self.final_data);
$(self.final_data).trigger('input');
// Update editor bar after image edition (in case the image change to icon or other)
_.defer(function () {
if (!media.parentNode) return;
range.createFromNode(media).select();
click_event(media, "mousedown");
click_event(media, "mouseup");
// Update editor bar after image edition (in case the image change to icon or other)
_.defer(function () {
if (!media.parentNode) return;
range.createFromNode(media).select();
click_event(media, "mousedown");
click_event(media, "mouseup");
});
return _super.apply(self, args);
});
this._super.apply(this, arguments);
},
searchTimer: null,
search: function () {
+5 -2
View File
@@ -86,6 +86,8 @@
target="fileframe"
class="form-inline">
<input type="hidden" name="csrf_token" t-att-value="csrf_token"/>
<input t-if="widget.options.res_id" type="hidden" name="res_id" t-att-value="widget.options.res_id"/>
<input t-if="widget.options.res_model" type="hidden" name="res_model" t-att-value="widget.options.res_model"/>
<div class="well">
<div class="form-group pull-left">
<input type="file" name="upload" t-att-accept="widget.accept" multiple="multiple" style="position: absolute; opacity: 0; width: 1px; height: 1px;"/>
@@ -145,8 +147,9 @@
<div class="existing-attachments">
<div class="row mt16" t-as="row" t-foreach="rows">
<div class="col-sm-2 o_existing_attachment_cell" t-as="attachment" t-foreach="row">
<i class="fa fa-times o_existing_attachment_remove" t-att-data-id="attachment.id"/>
<div class="o_attachment_border"><div t-att-data-src="attachment.src" t-att-data-url="attachment.url" t-att-alt="attachment.name" t-att-title="attachment.name" t-att-data-id="attachment.id" t-att-data-mimetype="attachment.mimetype" class="o_image"/></div>
<i t-if="attachment.res_model === 'ir.ui.view'" class="fa fa-times o_existing_attachment_remove" title="This file is a public view attachment" t-att-data-id="attachment.id"/>
<i t-else="" class="fa fa-times o_existing_attachment_remove" title="This file is attached to the current record" t-att-data-id="attachment.id"/>
<div class="o_attachment_border" t-att-style="attachment.res_model === 'ir.ui.view' ? null : 'border: 1px solid #5cb85c;'"><div t-att-data-src="attachment.src" t-att-data-url="attachment.url" t-att-alt="attachment.name" t-att-title="attachment.name" t-att-data-id="attachment.id" t-att-data-mimetype="attachment.mimetype" class="o_image"/></div>
</div>
</div>
</div>
+1 -1
View File
@@ -26,7 +26,7 @@ class QWeb(models.AbstractModel):
def _get_asset(self, xmlid, options, css=True, js=True, debug=False, async=False, values=None):
website = getattr(request, 'website', None) if request else None
if website and website.cdn_activated:
values = dict(values, url_for=website.get_cdn_url)
values = dict(values or {}, url_for=website.get_cdn_url)
return super(QWeb, self)._get_asset(xmlid, options, css, js, debug, async, values)
def _website_build_attribute(self, tagName, name, value, options, values):
+2 -2
View File
@@ -200,8 +200,8 @@ class SaleOrder(models.Model):
def get_portal_confirmation_action(self):
""" Template override default behavior of pay / sign chosen in sales settings """
if self.template_id:
return 'sign' if self.require_payment == 1 else 'pay'
if self.require_payment is not None or self.require_payment is not False:
return 'pay' if self.require_payment == 1 else 'sign'
return super(SaleOrder, self).get_portal_confirmation_action()
@api.multi
+15
View File
@@ -0,0 +1,15 @@
Austria, 2018-02-06
WT-IO-IT GmbH agrees to the terms of the Odoo Corporate Contributor License
Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this
declaration.
Signed,
Wolfgang Taferner wolfgang.taferner@wt-io-it.at https://github.com/wt-io-it
List of contributors:
Wolfgang Taferner wolfgang.taferner@wt-io-it.at https://github.com/wtaferner
+1 -1
View File
@@ -8,4 +8,4 @@ declaration.
Signed,
Rémi CAZENAVE remi@le-filament.com https://github.com/remi-filament
Rémi CAZENAVE 30716308+remi-filament@users.noreply.github.com https://github.com/remi-filament
+2 -1
View File
@@ -39,7 +39,8 @@ Step 2: Configure the odoo instance with your zone
In the Odoo back end, go to the :guilabel:`Website Settings`: menu, then
activate the CDN support and copy/paste your zone URL in the
:guilabel:`CDN Base URL` field.
:guilabel:`CDN Base URL` field. This field is only visible and configurable if
you have developer mode activated.
.. image:: cdn/odoo_cdn_base_url.png
:class: img-responsive
+10 -1
View File
@@ -8,6 +8,7 @@ import mimetypes
import os
import re
from collections import defaultdict
import uuid
from odoo import api, fields, models, tools, SUPERUSER_ID, _
from odoo.exceptions import AccessError
@@ -280,7 +281,7 @@ class IrAttachment(models.Model):
public = fields.Boolean('Is public document')
# for external access
access_token = fields.Char('Access Token')
access_token = fields.Char('Access Token', groups="base.group_user")
# the field 'datas' is computed and may use the other fields below
datas = fields.Binary(string='File Content', compute='_compute_datas', inverse='_inverse_datas')
@@ -438,6 +439,14 @@ class IrAttachment(models.Model):
self.browse().check('write', values=values)
return super(IrAttachment, self).create(values)
@api.one
def generate_access_token(self):
if self.access_token:
return self.access_token
access_token = str(uuid.uuid4())
self.write({'access_token': access_token})
return access_token
@api.model
def action_get(self):
return self.env['ir.actions.act_window'].for_xml_id('base', 'action_attachment')
+6 -1
View File
@@ -21,7 +21,7 @@ import odoo
from odoo import api, http, models, tools, SUPERUSER_ID
from odoo.exceptions import AccessDenied, AccessError
from odoo.http import request, STATIC_CACHE, content_disposition
from odoo.tools import pycompat
from odoo.tools import pycompat, consteq
from odoo.tools.mimetypes import guess_mimetype
from odoo.modules.module import get_resource_path, get_module_path
@@ -269,6 +269,7 @@ class IrHttp(models.AbstractModel):
:param str mimetype: mintype of the field (for headers)
:param str default_mimetype: default mintype if no mintype found
:param str access_token: optional token for unauthenticated access
only available for ir.attachment
:param Environment env: by default use request.env
:returns: (status, headers, content)
"""
@@ -277,6 +278,10 @@ class IrHttp(models.AbstractModel):
obj = None
if xmlid:
obj = env.ref(xmlid, False)
elif id and model == 'ir.attachment' and access_token:
obj = env[model].sudo().browse(int(id))
if not consteq(obj.access_token, access_token):
return (403, [], None)
elif id and model in env.registry:
obj = env[model].browse(int(id))
+2 -2
View File
@@ -144,8 +144,8 @@ class Company(models.Model):
self.ensure_one()
currency_id = self._get_user_currency()
if country_id:
currency_id = self.env['res.country'].browse(country_id).currency_id.id
return {'value': {'currency_id': currency_id}}
currency_id = self.env['res.country'].browse(country_id).currency_id
return {'value': {'currency_id': currency_id.id}}
@api.onchange('country_id')
def _onchange_country_id_wrapper(self):