Преглед на файлове

Módulo para imprimir orden de servicio

SEBAS преди 1 година
ревизия
0571552d3c

+ 3 - 0
__init__.py

@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+import controllers
+import models

BIN
__init__.pyc


+ 22 - 0
__openerp__.py

@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+{
+    'name': "Eiru Reports para Orden de Servicio",
+    'author': "Eiru",
+    'category': 'Reports',
+    'version': '0.1',
+    'depends': [
+        'base',
+        'sale',
+        'eiru_reports',
+        'orden_servicio',
+    ],
+    'qweb': [
+        'static/src/xml/*.xml',
+        'static/src/reports/*.xml'
+    ],
+    'data': [
+        'templates.xml',
+        'views/actions.xml',
+        'views/menus.xml',
+    ],
+}

+ 2 - 0
controllers/__init__.py

@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+import main

BIN
controllers/__init__.pyc


+ 2 - 0
controllers/helpers/__init__.py

@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+from sale_order import get_sale_order_line

BIN
controllers/helpers/__init__.pyc


+ 103 - 0
controllers/helpers/sale_order.py

@@ -0,0 +1,103 @@
+# -*- coding: utf-8 -*-
+from openerp.http import request as r
+
+def get_sale_order_line():
+    query = '''
+        SELECT
+            sale_line.id,
+            sale.id,
+            sale.name,
+            sale.date_order,
+            ARRAY[CAST(company.id AS VARCHAR),company.name] as company,
+            ARRAY[CAST(partner.id AS VARCHAR), partner.name] AS partner,
+            product.name_template,
+            ARRAY[CAST(sale_line.medic_id AS VARCHAR), salesdoctor.name] AS salesdoctor,
+            ARRAY[CAST(brand.id AS VARCHAR), brand.name] AS brand,
+            ARRAY[CAST(category.id AS VARCHAR), category.name] AS category,
+            sale_line.price_unit,
+            sale_line.product_uos_qty,
+            sale_line.discount,
+            (array_agg(distinct tax.amount)) AS tax,
+            (array_agg(distinct attr_rel.att_id)) AS attr_rel,
+            (array_agg(distinct attr.id)) AS attr,
+            (array_agg(distinct attr_value.name)) AS attr_value,
+            ARRAY[CAST(sale_line.salesman_id AS VARCHAR), salesman.name] AS salesman,
+            ARRAY[CAST(store.id AS VARCHAR), store.name] AS store
+        FROM sale_order_line AS sale_line
+        LEFT JOIN sale_order AS sale
+        ON sale.id = sale_line.order_id
+        LEFT JOIN res_partner AS partner
+        ON partner.id = sale.partner_id
+        LEFT JOIN product_product AS product
+        ON product.id = sale_line.product_id
+        LEFT JOIN res_partner AS salesdoctor
+        ON salesdoctor.id = sale_line.medic_id
+        LEFT JOIN product_template AS protemplate
+        ON protemplate.id = product.product_tmpl_id
+        LEFT JOIN product_category AS category
+        ON category.id = protemplate.categ_id
+        LEFT JOIN product_attribute_value_product_product_rel AS attr_rel
+        ON attr_rel.prod_id = product.id
+        LEFT JOIN product_attribute_value AS attr_value
+        ON attr_value.id = attr_rel.att_id
+        LEFT JOIN product_attribute AS attr
+        ON attr.id = attr_value.attribute_id
+        LEFT JOIN sale_order_tax AS sale_tax
+        ON sale_tax.order_line_id = sale_line.id
+        LEFT JOIN account_tax AS tax
+        ON tax.id = sale_tax.tax_id
+        LEFT JOIN res_users AS users
+        ON users.id = sale_line.salesman_id
+        LEFT JOIN res_partner AS salesman
+        ON salesman.id = users.partner_id
+        LEFT JOIN res_company AS company
+        ON company.id = sale_line.company_id
+        LEFT JOIN stock_warehouse AS warehouse
+        ON warehouse.id = sale.warehouse_id
+        LEFT JOIN res_store AS store
+        ON store.id = warehouse.store_id
+        LEFT JOIN product_brand AS brand
+        ON brand.id = protemplate.product_brand_id
+        WHERE sale_line.state != 'draft'
+        GROUP BY
+            sale.id,
+            sale_line.id,
+            sale.name,
+            company.id,
+            sale.date_order,
+            partner.id,
+            sale_line.medic_id,
+            salesdoctor.name,
+            product.name_template,
+            brand.id,
+            category.id,
+            salesman.id,
+            store.id
+    '''
+
+    r.cr.execute(query)
+
+    return [
+        {
+            'sale_line_id': j[0],
+            'sale_id': j[1],
+            'sale_name':j[2],
+            'sale_date': j[3],
+            'company': j[4],
+            'partner': j[5],
+            'product_name':j[6],
+            'medic_id':j[7],
+            'brand':j[8],
+            'category':j[9],
+            'price_unit': j[10],
+            'qty':j[11],
+            'discount':j[12],
+            'tax':j[13],
+            'attribute_rel':j[14],
+            'attribute':j[15],
+            'attribute_value':j[16],
+            'salesman':j[17],
+            'store':j[18]
+
+        } for j in r.cr.fetchall()
+    ]

BIN
controllers/helpers/sale_order.pyc


+ 36 - 0
controllers/main.py

@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+from openerp import http
+from werkzeug.wrappers import Response
+from werkzeug.datastructures import Headers
+from gzip import GzipFile
+from StringIO import StringIO as IO
+import simplejson as json
+import helpers as hp
+import logging
+
+LOGGER = logging.getLogger(__name__)
+GZIP_COMPRESSION_LEVEL = 9
+
+def make_gzip_response(data=None, status=200):
+    gzip_buffer = IO()
+
+    with GzipFile(mode='wb', compresslevel=GZIP_COMPRESSION_LEVEL, fileobj=gzip_buffer) as gzip_file:
+        gzip_file.write(json.dumps(data))
+
+    value = gzip_buffer.getvalue()
+    gzip_buffer.close()
+
+    headers = Headers()
+    headers.add('Content-Encoding', 'gzip')
+    headers.add('Vary', 'Accept-Encoding')
+    headers.add('Content-Length', len(value))
+
+    return Response(value, status=status, headers=headers, content_type='application/json')
+
+class ReportMoconaController(http.Controller):
+
+    @http.route('/report-budgetdental-analytic', auth='user', methods=['GET', 'POST'])
+    def getSaleBudget(self, **kw):
+        return make_gzip_response({
+             'order_lines': hp.get_sale_order_line(),
+        })

BIN
controllers/main.pyc


+ 497 - 0
models.py

@@ -0,0 +1,497 @@
+# -*- coding: utf-8 -*-
+
+from openerp import models, fields, api
+
+class OrdenServicio(models.Model):
+	_inherit = 'orden.servicio'
+
+	############################################################
+	#	ACCOUNT INVOICE
+	############################################################
+
+	@api.model
+	def getOrdenServicio(self,domain):
+		OrdenServicio = self.env['orden.servicio'].search(domain)
+		decimal_precision = self.env['decimal.precision'].precision_get('Account')
+		values = []
+		for servicio in OrdenServicio:
+			values.append({
+				'id': servicio.id,
+				'name': servicio.name,
+				'state': servicio.state,
+				'celular_partner': servicio.celular_partner,
+				'telefono_partner': servicio.telefono_partner,
+				'planned_start_date': servicio.planned_start_date,
+				'planned_end_date': servicio.planned_end_date,
+				'contacto_obra': servicio.contacto_obra,
+				'responsable': servicio.responsable,
+				'order_date': servicio.order_date,
+				'name_obra': servicio.name_obra,
+				'name_local': servicio.name_local,
+				'distancia_obra': servicio.distancia_obra,
+				'croquis': servicio.croquis,
+				'hrs_total': servicio.hrs_total,
+				'zona_obra': servicio.zona_obra,
+				'obs_obra': servicio.obs_obra,
+				'sale_order_id': servicio.sale_order_id,
+				'company_id': servicio.company_id,
+				'currency_id': servicio.currency_id,
+				'partner_id': [
+					servicio.partner_id.id,
+					servicio.partner_id.name,
+					servicio.partner_id.ruc,
+				],
+				'partner_info': {
+					'mobile': servicio.partner_id.mobile,
+					'phone': servicio.partner_id.phone,
+				},
+				'user_id': [
+					servicio.user_id.id,
+					servicio.user_id.name,
+				],
+
+			})
+
+		return values
+
+
+class ServicioProducto(models.Model):
+	_inherit = 'servicio.producto'
+
+	############################################################
+	#	servicio producto
+	############################################################
+
+	@api.model
+	def getServicioProducto(self,domain):
+		ServicioProducto = self.env['servicio.producto'].search(domain)
+		decimal_precision = self.env['decimal.precision'].precision_get('Account')
+		values = []
+		for line in ServicioProducto:
+			values.append({
+				'id': line.id,
+				'servicio_id':line.servicio_id.id,
+				'number':line.servicio_id.name,
+				'order_date': line.servicio_id.order_date,
+				'user_id': [
+					line.servicio_id.user_id.id,
+					line.servicio_id.user_id.name,
+				],
+				'partner_id': [
+					line.servicio_id.partner_id.id,
+					line.servicio_id.partner_id.name,
+					line.servicio_id.partner_id.ruc,
+				],
+				'invoice_state': line.servicio_id.state,
+				'product_id': [
+					line.product_id.id,
+					line.product_id.display_name,
+					line.product_id.categ_id.complete_name,
+					line.product_id.standard_price,
+				],
+				'product_category_id': line.product_id.categ_id.id,
+				'price_unit': line.price_unit,
+				'price_subtotal': line.subtotal,
+				'quantity': line.quantity,
+				'price_unit_currency': round(line.price_unit * (line.servicio_id.company_id.currency_id.rate / line.servicio_id.currency_id.rate),decimal_precision),
+				'price_subtotal_currency': round(line.subtotal * (line.servicio_id.company_id.currency_id.rate / line.servicio_id.currency_id.rate),decimal_precision),
+				'amount_currency': round((line.quantity * line.price_unit) * (line.servicio_id.company_id.currency_id.rate / line.servicio_id.currency_id.rate),decimal_precision),
+			})
+
+		return values
+
+class ServicioInsumo(models.Model):
+	_inherit = 'servicio.insumo'
+	############################################################
+	#	servicio insumo
+	############################################################
+
+	@api.model
+	def getServicioInsumo(self,domain):
+		ServicioInsumo = self.env['servicio.insumo'].search(domain)
+		decimal_precision = self.env['decimal.precision'].precision_get('Account')
+		values = []
+		for insumo in ServicioInsumo:
+			values.append({
+				'id': insumo.id,
+				'servicio_id':insumo.servicio_id.id,
+				'number':insumo.servicio_id.name,
+				'order_date': insumo.servicio_id.order_date,
+				'user_id': [
+					insumo.servicio_id.user_id.id,
+					insumo.servicio_id.user_id.name,
+				],
+				'partner_id': [
+					insumo.servicio_id.partner_id.id,
+					insumo.servicio_id.partner_id.name,
+					insumo.servicio_id.partner_id.ruc,
+				],
+				'invoice_state': insumo.servicio_id.state,
+				'product_id': [
+					insumo.product_id.id,
+					insumo.product_id.display_name,
+					insumo.product_id.categ_id.complete_name,
+					insumo.product_id.standard_price,
+				],
+				'product_category_id': insumo.product_id.categ_id.id,
+				'descripcion': insumo.descripcion,
+				'price_unit': insumo.price_unit,
+				'price_subtotal': insumo.subtotal,
+				'quantity': insumo.quantity,
+				'price_unit_currency': round(insumo.price_unit * (insumo.servicio_id.company_id.currency_id.rate / insumo.servicio_id.currency_id.rate),decimal_precision),
+				'price_subtotal_currency': round(insumo.subtotal * (insumo.servicio_id.company_id.currency_id.rate / insumo.servicio_id.currency_id.rate),decimal_precision),
+				'amount_currency': round((insumo.quantity * insumo.price_unit) * (insumo.servicio_id.company_id.currency_id.rate / insumo.servicio_id.currency_id.rate),decimal_precision),
+			})
+
+		return values
+
+class ServicioLogistica(models.Model):
+	_inherit = 'servicio.logistica'
+	############################################################
+	#	servicio logistica
+	############################################################
+
+	@api.model
+	def getServicioLogistica(self,domain):
+		ServicioLogistica = self.env['servicio.logistica'].search(domain)
+		decimal_precision = self.env['decimal.precision'].precision_get('Account')
+		values = []
+		for logistica in ServicioLogistica:
+			values.append({
+				'id': logistica.id,
+				'servicio_id':logistica.servicio_id.id,
+				'number':logistica.servicio_id.name,
+				'order_date': logistica.servicio_id.order_date,
+				'user_id': [
+					logistica.servicio_id.user_id.id,
+					logistica.servicio_id.user_id.name,
+				],
+				'partner_id': [
+					logistica.servicio_id.partner_id.id,
+					logistica.servicio_id.partner_id.name,
+					logistica.servicio_id.partner_id.ruc,
+				],
+				'invoice_state': logistica.servicio_id.state,
+				'product_id': [
+					logistica.product_id.id,
+					logistica.product_id.display_name,
+					logistica.product_id.categ_id.complete_name,
+					logistica.product_id.standard_price,
+				],
+				'product_category_id': logistica.product_id.categ_id.id,
+				'fecha': logistica.fecha,
+				'descripcion': logistica.descripcion,
+				'price_unit': logistica.price_unit,
+				'price_subtotal': logistica.subtotal,
+				'quantity': logistica.quantity,
+				'price_unit_currency': round(logistica.price_unit * (logistica.servicio_id.company_id.currency_id.rate / logistica.servicio_id.currency_id.rate),decimal_precision),
+				'price_subtotal_currency': round(logistica.subtotal * (logistica.servicio_id.company_id.currency_id.rate / logistica.servicio_id.currency_id.rate),decimal_precision),
+				'amount_currency': round((logistica.quantity * logistica.price_unit) * (logistica.servicio_id.company_id.currency_id.rate / logistica.servicio_id.currency_id.rate),decimal_precision),
+			})
+
+		return values
+
+class DevolucionInsumo(models.Model):
+	_inherit = 'devolucion.insumo'
+
+	############################################################
+	#	servicio logistica
+	############################################################
+
+	@api.model
+	def getDevolucionInsumo(self,domain):
+		DevolucionInsumo = self.env['devolucion.insumo'].search(domain)
+		decimal_precision = self.env['decimal.precision'].precision_get('Account')
+		values = []
+		for devolucion in DevolucionInsumo:
+			values.append({
+				'id': devolucion.id,
+				'servicio_id':devolucion.servicio_id.id,
+				'number':devolucion.servicio_id.name,
+				'order_date': devolucion.servicio_id.order_date,
+				'user_id': [
+					devolucion.servicio_id.user_id.id,
+					devolucion.servicio_id.user_id.name,
+				],
+				'partner_id': [
+					devolucion.servicio_id.partner_id.id,
+					devolucion.servicio_id.partner_id.name,
+					devolucion.servicio_id.partner_id.ruc,
+				],
+				'invoice_state': devolucion.servicio_id.state,
+				'product_id': [
+					devolucion.product_id.id,
+					devolucion.product_id.display_name,
+					devolucion.product_id.categ_id.complete_name,
+					devolucion.product_id.standard_price,
+				],
+				'product_category_id': devolucion.product_id.categ_id.id,
+				'descripcion': devolucion.descripcion,
+				'price_unit': devolucion.price_unit,
+				'price_subtotal': devolucion.subtotal,
+				'quantity': devolucion.quantity,
+				'price_unit_currency': round(devolucion.price_unit * (devolucion.servicio_id.company_id.currency_id.rate / devolucion.servicio_id.currency_id.rate),decimal_precision),
+				'price_subtotal_currency': round(devolucion.subtotal * (devolucion.servicio_id.company_id.currency_id.rate / devolucion.servicio_id.currency_id.rate),decimal_precision),
+				'amount_currency': round((devolucion.quantity * devolucion.price_unit) * (devolucion.servicio_id.company_id.currency_id.rate / devolucion.servicio_id.currency_id.rate),decimal_precision),
+			})
+
+		return values
+
+class RecepcionFabrica(models.Model):
+	_inherit = 'recepcion.fabrica'
+	############################################################
+	#	recepción fabrica
+	############################################################
+
+	@api.model
+	def getRecepcionFabrica(self,domain):
+		RecepcionFabrica = self.env['recepcion.fabrica'].search(domain)
+		decimal_precision = self.env['decimal.precision'].precision_get('Account')
+		values = []
+		for fabrica in RecepcionFabrica:
+			values.append({
+				'id': fabrica.id,
+				'servicio_id':fabrica.servicio_id.id,
+				'number':fabrica.servicio_id.name,
+				'order_date': fabrica.servicio_id.order_date,
+				'user_id': [
+					fabrica.servicio_id.user_id.id,
+					fabrica.servicio_id.user_id.name,
+				],
+				'partner_id': [
+					fabrica.servicio_id.partner_id.id,
+					fabrica.servicio_id.partner_id.name,
+					fabrica.servicio_id.partner_id.ruc,
+				],
+				'invoice_state': fabrica.servicio_id.state,
+				'product_id': [
+					fabrica.product_id.id,
+					fabrica.product_id.display_name,
+					fabrica.product_id.categ_id.complete_name,
+					fabrica.product_id.standard_price,
+				],
+				'product_category_id': fabrica.product_id.categ_id.id,
+				'price_unit': fabrica.price_unit,
+				'price_subtotal': fabrica.subtotal,
+				'quantity': fabrica.quantity,
+				'price_unit_currency': round(fabrica.price_unit * (fabrica.servicio_id.company_id.currency_id.rate / fabrica.servicio_id.currency_id.rate),decimal_precision),
+				'price_subtotal_currency': round(fabrica.subtotal * (fabrica.servicio_id.company_id.currency_id.rate / fabrica.servicio_id.currency_id.rate),decimal_precision),
+				'amount_currency': round((fabrica.quantity * fabrica.price_unit) * (fabrica.servicio_id.company_id.currency_id.rate / fabrica.servicio_id.currency_id.rate),decimal_precision),
+			})
+
+		return values
+
+class ResCompany(models.Model):
+	_inherit = 'res.company'
+
+	@api.model
+	def getResCompany(self,domain):
+		ResCompany = self.env['res.company'].search(domain)
+		values = []
+		for company in ResCompany:
+			values.append({
+				'id': company.id,
+				'name': company.name,
+				'currency_id': [
+					company.currency_id.id,
+					company.currency_id.name,
+				],
+				'company_ruc': company.partner_id.ruc,
+				'phone': company.phone,
+				'logo': company.logo,
+			})
+
+		return values
+
+
+class ResCurrency(models.Model):
+	_inherit = 'res.currency'
+
+	@api.model
+	def getResCurrency(self,domain):
+		ResCurrency = self.env['res.currency'].search(domain)
+		values = []
+		for currency in ResCurrency:
+			values.append({
+				'id': currency.id,
+				'name': currency.name,
+				'symbol': currency.symbol,
+				'rate_silent': currency.rate_silent,
+				'base': currency.base,
+				'decimal_separator': currency.decimal_separator,
+				'decimal_places': currency.decimal_places,
+				'thousands_separator': currency.thousands_separator,
+				'symbol_position': currency.symbol_position,
+			})
+
+		return values
+
+class ResPartner(models.Model):
+	_inherit = 'res.partner'
+
+	@api.model
+	def getResPartner(self,domain):
+		ResPartner = self.env['res.partner'].search(domain)
+		values = []
+		for partner in ResPartner:
+			values.append({
+				'id': partner.id,
+				'name': partner.name,
+				'ruc': partner.ruc,
+				'street': partner.street,
+				'city': partner.city,
+				'phone': partner.phone,
+				'mobile': partner.mobile,
+				'email': partner.email,
+				'property_product_pricelist': partner.property_product_pricelist.name,
+				'property_product_pricelist_purchase': partner.property_product_pricelist_purchase.name,
+				'credit': partner.credit,
+				'debit': partner.debit,
+				'supplier': partner.supplier,
+			})
+
+		return values
+
+class ProductProduct(models.Model):
+	_inherit = 'product.product'
+
+	############################################################
+	#	PRODUCT PRODUCT
+	############################################################
+
+	@api.model
+	def getProductProduct(self,domain):
+		ProductProduct = self.env['product.product'].search(domain)
+		values = []
+		for product in ProductProduct:
+			attributeValuesLines = map(lambda x: x.id, product.attribute_value_ids)
+			attributeIDS = []
+			for arttIds in self.env['product.attribute.value'].search([('id', 'in', attributeValuesLines)]):
+				attributeIDS.append(arttIds.attribute_id.id)
+
+			try:
+				# sale list price
+				sale_price = map(lambda x: x.id, product.pricelists)
+				saleIDS = []
+				for item in self.env['product.pricelist'].search([('id', 'in', sale_price)]):
+					saleIDS.append(item.id)
+
+				# purchase list price
+				buy_price = map(lambda x: x.id, product.purchase_pricelists)
+				buyIDS = []
+				for item in self.env['product.pricelist'].search([('id', 'in', buy_price)]):
+					buyIDS.append(item.id)
+			except:
+				buyIDS = []
+				saleIDS = []
+
+			try:
+				brand = product.product_brand_id.id
+			except:
+				brand = ''
+
+			values.append({
+				'id': product.id,
+				'name': product.name,
+				'display_name': product.display_name,
+				'standard_price': product.standard_price,
+				'lst_price': product.lst_price,
+				'categ_id': {
+					'id': product.categ_id.id,
+					'name': product.categ_id.name,
+					'complete_name': product.categ_id.complete_name,
+				},
+				'product_brand_id':brand,
+				'atribute_value_ids': attributeValuesLines,
+				'attribute_ids': attributeIDS,
+				'qty_available': product.qty_available,
+				'default_code': product.default_code,
+				'image_medium': product.image_medium,
+				'pricelists': saleIDS,
+				'purchase_pricelists':buyIDS,
+				'product_tmpl_id': product.product_tmpl_id.id,
+				'image': product.image,
+				'ean13': product.ean13,
+			})
+
+		return values
+
+	############################################################
+	#	PRODUCT PRODUCT - STOCK 'minimo_quantity': product.minimo_quantity,
+	############################################################
+
+	@api.model
+	def getProductProductStock(self,domain):
+		ProductProduct = self.env['product.product'].search(domain)
+		values = []
+		for product in ProductProduct:
+			attributeValuesLines = map(lambda x: x.id, product.attribute_value_ids)
+			attributeIDS = []
+			for arttIds in self.env['product.attribute.value'].search([('id', 'in', attributeValuesLines)]):
+				attributeIDS.append(arttIds.attribute_id.id)
+
+			values.append({
+				'id': product.id,
+				'display_name': product.display_name,
+				'standard_price': product.standard_price,
+				'lst_price': product.lst_price,
+				'categ_id': {
+					'id': product.categ_id.id,
+					'name': product.categ_id.name,
+					'complete_name': product.categ_id.complete_name,
+				},
+				'atribute_value_ids': attributeValuesLines,
+				'attribute_ids': attributeIDS,
+				'default_code': product.default_code,
+				'ean13': product.ean13,
+			})
+
+		return values
+
+
+class ProductCategory(models.Model):
+	_inherit = 'product.category'
+
+	@api.model
+	def getProductCategory(self,domain):
+		ProductCategory = self.env['product.category'].search(domain)
+		values = []
+		for category in ProductCategory:
+			values.append({
+				'id': category.id,
+				'name': category.name,
+				'display_name': category.display_name,
+				'parent_id': [
+					category.parent_id.id,
+					category.parent_id.name,
+				],
+			})
+
+		return values
+
+
+class StockLocation(models.Model):
+	_inherit = 'stock.location'
+
+	@api.model
+	def getStockLocation(self,domain):
+		StockLocation = self.env['stock.location'].search(domain)
+		values = []
+		for location in StockLocation:
+			values.append({
+				'id': location.id,
+				'name': location.name,
+				'display_name': location.display_name,
+				'parent_name': location.location_id.name,
+				'company_id': [
+					location.company_id.id,
+					location.company_id.name,
+				],
+				'store_id': [
+					location.store_id.id,
+					location.store_id.name,
+				],
+				'usage': location.usage,
+			})
+
+		return values

BIN
models.pyc


+ 10 - 0
static/src/css/custom.css

@@ -0,0 +1,10 @@
+.openerp_webclient_container {
+    height: 100% !important;
+    height: calc(100% - 45px) !important;
+    overflow: auto !important;
+  }
+
+.hover:hover{
+  cursor: -webkit-grab;
+  cursor: grab;
+}

+ 18 - 0
static/src/js/main.js

@@ -0,0 +1,18 @@
+openerp.eiru_reports_servicio = function(instance) {
+  "use strict";
+
+  var reporting = instance.eiru_reports_servicio;
+
+  reporting_base(instance, reporting);
+
+  try {
+    report_orden_servicio_analytic(reporting);
+
+  } catch (e) {
+    // ignorar error
+  }
+
+  // analisis de nominas
+  instance.web.client_actions.add('eiru_reports_servicio.ordenservicio_analytic_action', 'instance.eiru_reports_servicio.ReportOrdenServicioWidget');
+
+}

+ 22 - 0
static/src/js/reporting_base.js

@@ -0,0 +1,22 @@
+function reporting_base (instance, widget) {
+    "use strict";
+
+    widget.Base = instance.Widget.extend({
+
+        position: 0,
+
+        init: function (parent, position) {
+            this._super(parent);
+            this.position = position || this.position;
+        },
+        start: function () {
+            
+        },
+        getPosition: function () {
+            return this.position;
+        },
+        setPosition: function (position) {
+            this.position = position;
+        }
+    });
+}

+ 755 - 0
static/src/js/reports/report_orden_servicio_analytic.js

@@ -0,0 +1,755 @@
+function report_orden_servicio_analytic(reporting){
+    "use strict";
+
+    var model = openerp;
+
+    reporting.ReportOrdenServicioWidget = reporting.Base.extend({
+        template: 'ReportOrdenServicio',
+          servicios: [],
+          servicioLines: [],
+          productProduct:[],
+          ResCurrency:[],
+          insumoLines:[],
+          logisticaLines:[],
+          rowsData :[],
+          content :[],
+          rowOrigin:[],
+          fabricaLines:[],
+          resCompany:[],
+          events:{
+              'click #toolbar > button' : 'clickOnAction',
+              'click #X' : 'fectSearch',
+              'click #A' : 'fectSearch',
+              'click #B' : 'fectSearch',
+              'click #C' : 'fectSearch',
+              'click #D' : 'fectSearch',
+              'click #Z' : 'fectSearch',
+              'click #W' : 'fectSearch',
+              'click #draft' : 'fectSearch',
+              'click #in_progress' : 'fectSearch',
+              'click #done' : 'fectSearch',
+              'click #canceled' : 'fectSearch',
+              'change #current-store': 'fectSearch',
+              'change #current-category' : 'fectSearch',
+              'change #current-attribute': 'fectSearch',
+              'change #current-attribute-value': 'fectSearch',
+              'change #user': 'fectSearch',
+              'change #from' : 'fectSearch',
+              'change #to': 'fectSearch',
+              'click #volver_btn': 'volver',
+              'click-row.bs.table #table' : 'ckickAnalysisDetail',
+          },
+          init : function(parent){
+            this._super(parent);
+          },
+          start: function () {
+              var self = this;
+              var table = this.$el.find('#table');
+              table.bootstrapTable({data : self.rowsData});
+              this.fecthFecha();
+              this.submitForm();
+          },
+          ckickAnalysisDetail: function(e, row, $element, field){
+
+              // if (field == 'number'){
+              //     this.do_action({
+              //         name : "Factura de Cliente",
+              //         type : 'ir.actions.act_window',
+              //         res_model : "account.invoice",
+              //         views : [[false,'form']],
+              //         target : 'new',
+              //         domain : [['type', '=', 'out_invoice'],['id','=', row.id]],
+              //         context : {},
+              //         flags : {'form': {'action_buttons': false, 'options': {'mode': 'view'}}},
+              //         res_id : row.id,
+              //     });
+              // }
+              e.stopImmediatePropagation();
+          },
+          volver: function(){
+              this.$el.find('#volver').empty();
+              this.$el.find('#grafico').empty();
+              this.$el.find('.bootstrap-table').show({
+                  effect: 'drop',
+                  direction: 'down',
+                  duration: 200,
+              });
+          },
+           // Fecha
+          fecthFecha: function() {
+              var to;
+              var dateFormat1 = "mm/dd/yy",
+                from = $( "#from" )
+                  .datepicker({
+                    dateFormat: "dd/mm/yy",
+                    changeMonth: true,
+                    numberOfMonths: 1,
+                  })
+                  .on( "change", function() {
+                    to.datepicker( "option", "minDate", getDate(this), "dd/mm/yyyy");
+                  });
+                to = $( "#to" ).datepicker({
+                  dateFormat: "dd/mm/yy",
+                  defaultDate: "+7d",
+                  changeMonth: true,
+                  numberOfMonths: 1,
+                })
+                .on( "change", function() {
+                  from.datepicker( "option", "maxDate", getDate(this));
+                });
+
+              function getDate( element ) {
+                var fechaSel =element.value.split('/');
+                var date;
+                try {
+                  date = $.datepicker.parseDate( dateFormat1, (fechaSel[1]+"/"+fechaSel[0]+"/"+fechaSel[2]));
+                } catch( error ) {
+                 date = null;
+                }
+                return date;
+              }
+          },
+
+          // Cansultar
+          submitForm: function () {
+              var self = this;
+              this.fetchResCurrency().then(function(ResCurrency) {
+                  self.ResCurrency = ResCurrency;
+                  return ResCurrency;
+              }).then(function (ResCurrency) {
+                  return self.fetchOrdenServicio();
+              }).then(function (servicios){
+                  self.servicios = servicios;
+                  return self.fetchServicioProducto(servicios);
+              }).then(function (servicioLines) {
+                  self.servicioLines = servicioLines;
+                  return self.fetchServicioInsumo();
+              }).then(function (insumoLines) {
+                  self.insumoLines = insumoLines;
+                  return self.fetchServicioLogistica();
+              }).then(function (logisticaLines) {
+                  self.logisticaLines = logisticaLines;
+                  return self.fetchDevolucionInsumo();
+              }).then(function (devolucionLines) {
+                  self.devolucionLines = devolucionLines;
+                  return self.fetchRecepcionFabrica();
+              }).then(function (fabricaLines) {
+                  self.fabricaLines = fabricaLines;
+                  return self.fetchProductProduct();
+              }).then(function(ProductProduct){
+                  self.ProductProduct = ProductProduct;
+                  return self.fetchProductCategory();
+              }).then(function(ProductCategory){
+                  self.ProductCategory= ProductCategory;
+                  self.$el.find('#current-category').append('<option value="9999999">Todas las categorias</option>');
+                  _.each(ProductCategory, function (item) {
+                      self.$el.find('#current-category').append('<option value="' + item.id + '">' + item.complete_name + '</option>');
+                  });
+                  return self.fecthCompanyCurrency();
+              }).then(function(resCompany){
+                  self.resCompany = resCompany;
+                  return self.fetchResPartner();
+              }).then(function(ResPartner){
+                  self.ResPartner = ResPartner;
+                  return self.fecthResUser();
+              }).then(function (ResUser) {
+                  self.ResUser = ResUser;
+                  self.search();
+                  self.searchProduct();
+                  self.searchUser();
+                  return self.fectUtility();
+              });
+          },
+
+          valorNull:function(dato){
+              var valor ="";
+              if (dato){
+                  valor=dato;
+              }
+              return valor;
+          },
+
+          search: function () {
+              var self = this;
+              var results = self.ResPartner;
+              results = _.map(results, function (item) {
+                  return {
+                          label: item.id + '-'+ item.name + ' ' + self.valorNull(item.ruc),
+                          value: item.id + '-'+ item.name + ' ' + self.valorNull(item.ruc)
+                  }
+              });
+              self.$('#partner').autocomplete({
+                  source: results,
+                  minLength:0,
+                  search: function(event, ui) {
+                      if (!(self.$('#partner').val())){
+                          self.fectSearch();
+                      }
+                  },
+                  close: function( event, ui ) {
+                          self.fectSearch();
+                  },
+                  select: function(event, ui) {
+                      self.fectSearch();
+                  }
+              });
+          },
+
+          searchProduct: function () {
+              var self = this;
+              var results = self.ProductProduct;
+              results = _.map(results, function (item) {
+                  return {
+                      label: item.id + '- '+ ' [ ' + self.valorNull(item.default_code) + ' - ' + self.valorNull(item.ean13) + ' ] ' + item.name + ' ( ' +  self.valorNull(item.attribute_str) + ' ) ' ,
+                      value: item.id + '- '+ ' [ ' + self.valorNull(item.default_code) + ' - ' + self.valorNull(item.ean13) + ' ] ' + item.name + ' ( ' +  self.valorNull(item.attribute_str) + ' ) '
+                  }
+              });
+              self.$('#product').autocomplete({
+                  source: results,
+                  minLength:0,
+                  search: function(event, ui) {
+                      if (!(self.$('#product').val())){
+                          self.fectSearch();
+                      }
+                  },
+                  close: function( event, ui ) {
+                          self.fectSearch();
+                  },
+                  select: function(event, ui) {
+                      self.fectSearch();
+                  }
+              });
+          },
+
+
+          fecthCompanyCurrency: function(){
+              var self = this;
+              var defer = $.Deferred();
+              var field=['id','name', 'currency_id'];
+              var domain = [['id', '=', self.session.company_id]];
+              var ResCompany = new model.web.Model('res.company');
+              ResCompany.query(field).filter(domain).all().then(function(results){
+                  defer.resolve(results);
+              });
+              return defer;
+          },
+
+          fetchResCurrency : function(){
+              var self = this;
+              var defer = $.Deferred();
+              var fields = ['id','name', 'symbol', 'rate_silent', 'base', 'decimal_separator', 'decimal_places', 'thousands_separator', 'symbol_position'];
+              var domain = [['active', '=', true]];
+              var ResCurrency = new model.web.Model('res.currency');
+              ResCurrency.query(fields).filter(domain).all().then(function(results) {
+                  defer.resolve(results);
+              });
+              return defer;
+          },
+
+          fetchOrdenServicio: function () {
+              var self = this;
+              var filter ="[]";
+              filter=filter.concat("]");
+              var field =['id', 'name', 'user_id', 'order_date', 'partner_id', 'state', 'celular_partner', 'planned_start_date', 'company_id', 'currency_id', 'product_ids', 'telefono_partner','insumos_ids','logistica_ids','devolucion_ids','recepcion_ids','invoice_ids'];
+              var defer = $.Deferred();
+              var OrdenServicio = new model.web.Model('orden.servicio');
+              OrdenServicio.query(field).filter().all().then(function (results) {
+                  defer.resolve(results);
+              });
+              return defer;
+          },
+
+          fetchServicioProducto: function (servicios) {
+              var defer = $.Deferred();
+              var linesIds = _.flatten(_.map(servicios, function (item) {
+                  return item.product_ids;
+              }));
+
+              var ServicioProducto = new model.web.Model('servicio.producto');
+              ServicioProducto.query(['id', 'quantity', 'price_unit', 'price_subtotal', 'product_id', 'product_category_id','servicio_id']).filter([['id', 'in', linesIds]]).all().then(function (results) {
+                  defer.resolve(results)
+              });
+              return defer;
+          },
+
+          fetchServicioInsumo: function (servicios) {
+              var defer = $.Deferred();
+              var insumoIds = _.flatten(_.map(servicios, function (item) {
+                  return item.insumos_ids;
+              }));
+              var ServicioInsumo = new model.web.Model('servicio.insumo');
+              ServicioInsumo.query(['id', 'descripcion', 'quantity', 'price_unit', 'price_subtotal', 'product_id', 'servicio_id']).filter([['id', 'in', insumoIds]]).all().then(function (results) {
+                  defer.resolve(results)
+              });
+              return defer;
+          },
+
+          fetchServicioLogistica: function (servicios) {
+              var defer = $.Deferred();
+              var logisticaIds = _.flatten(_.map(servicios, function (item) {
+                  return item.logistica_ids;
+              }));
+              var ServicioLogistica = new model.web.Model('servicio.logistica');
+              ServicioLogistica.query(['id', 'fecha', 'descripcion', 'quantity', 'price_unit', 'price_subtotal', 'product_id', 'servicio_id']).filter([['id', 'in', logisticaIds]]).all().then(function (results) {
+                  defer.resolve(results)
+              });
+              return defer;
+          },
+
+          fetchDevolucionInsumo: function (servicios) {
+              var defer = $.Deferred();
+              var devolucion_ids = _.flatten(_.map(servicios, function (item) {
+                  return item.devolucion_ids;
+              }));
+              var DevolucionInsumo = new model.web.Model('devolucion.insumo');
+              DevolucionInsumo.query(['id', 'descripcion', 'quantity', 'price_unit', 'price_subtotal', 'product_id', 'servicio_id']).filter([['id', 'in', devolucion_ids]]).all().then(function (results) {
+                  defer.resolve(results)
+              });
+              return defer;
+          },
+
+
+          fetchRecepcionFabrica: function (servicios) {
+              var defer = $.Deferred();
+              var recepcion_ids = _.flatten(_.map(servicios, function (item) {
+                  return item.recepcion_ids;
+              }));
+              var fabricaLines = new model.web.Model('recepcion.fabrica');
+              fabricaLines.query(['id', 'fecha', 'descripcion', 'quantity', 'price_unit', 'price_subtotal', 'product_id', 'servicio_id']).filter([['id', 'in', recepcion_ids]]).all().then(function (results) {
+                    defer.resolve(results)
+                  });
+                  return defer;
+              },
+
+          fetchResPartner: function () {
+              var self = this;
+              var defer = $.Deferred();
+              var ResPartner = new model.web.Model('res.partner');
+              ResPartner.query(['id','name','ruc']).filter([['active', '=', true],['customer', '=', true]]).all().then(function(results){
+                  defer.resolve(results);
+              });
+              return defer;
+          },
+
+          fecthResUser: function() {
+              var self = this;
+              var defer = $.Deferred();
+              var user_ids = _.map(self.servicios,function(map){
+                  return map.user_id[0];
+              });
+              var fields = ['id', 'name'];
+              var domain = [['id', 'in', user_ids]];
+              var ResUsers = new model.web.Model('res.users');
+              ResUsers.query(fields).filter(domain).all().then(function(results) {
+                  defer.resolve(results);
+              });
+
+              return defer;
+          },
+
+          searchUser: function () {
+              var self = this;
+              var results = self.ResUser;
+              results = _.map(results, function (item) {
+                  return {
+                          label: item.id + '-'+ item.name,
+                          value: item.id + '-'+ item.name
+                  }
+              });
+              self.$('#user').autocomplete({
+                  source: results,
+                  minLength:0,
+                  searchUser: function(event, ui) {
+                      if (!(self.$('#user').val())){
+                          self.fectSearch();
+                      }
+                  },
+                  close: function( event, ui ) {
+                          self.fectSearch();
+                  },
+                  select: function(event, ui) {
+                      self.fectSearch();
+                  }
+              });
+          },
+
+          // Product Product
+          fetchProductProduct: function(){
+              var self = this;
+              var product_ids = _.flatten(_.map(self.servicioLines, function (item) {
+                  return item.product_id[0];
+              }));
+              var domain = [['id','in',product_ids]];
+              var ProductProduct = new model.web.Model('product.product');
+              return ProductProduct.call('getProductProduct',[domain], {
+                  context: new model.web.CompoundContext()
+              });
+          },
+
+          // Buscar Category
+          fetchProductCategory : function(){
+              var self = this;
+              var defer = $.Deferred();
+              var fields = ['id','name','parent_id','complete_name'];
+              var ProductCategory = new model.web.Model('product.category');
+              ProductCategory.query(fields).filter().all().then(function(results) {
+                  defer.resolve(results);
+              });
+              return defer;
+          },
+
+
+          // Obtener Monedas de la Factura
+          getResCurrency: function (id) {
+              var self = this;
+              return _.filter(self.ResCurrency,function (item) {
+                  return item.id === id;
+              })
+          },
+
+          // Obtener la Detalles de la Factura
+          getServicio: function (id_line){
+              var self = this;
+              return _.find(this.servicios, function (inv) {
+                  return _.contains(inv.product_ids, id_line);
+              });
+          },
+
+          // Obtener las lineas de las Facturas
+          getProductProduct: function(pro_id){
+              var self = this;
+              return _.find(self.ProductProduct, function(item){
+                  return _.contains(pro_id, item.id);
+              });
+          },
+
+          fectUtility: function(){
+              var self = this;
+              var data=[];
+              var CurrencyBase = self.getResCurrency(self.resCompany[0].currency_id[0]).shift();
+              var item;
+              var state;
+              var servicio=[];
+              var product;
+
+              for (var i = 0; i < this.servicioLines.length; i++) {
+                  item = this.servicioLines[i];
+                  servicio = this.getServicio(item.id);
+                  if(servicio.state=='draft'){
+                      state = 'Borrador'
+                  }
+                  if(servicio.state=='in_progress'){
+                      state = 'En progreso'
+                  }
+                  if(servicio.state=='done'){
+                      state = 'Realizado'
+                  }
+                  if(servicio.state=='canceled'){
+                      state = 'Cancelado'
+                  }
+
+                  // var currency = self.getResCurrency(servicio.currency_id[0]).shift();
+                  // console.log(currency);
+
+
+
+                  product =this.getProductProduct(item.product_id);
+
+                  if (product != undefined){
+
+                          data.push({
+                              id : servicio.id,
+                              name : (servicio.name),
+                              planned_start_date : (servicio.planned_start_date),
+                              celular_obra: (servicio.celular_obra),
+                              product_id : item.product_id[0],
+                              product_name : item.product_id[1],
+                              quantity : accounting.formatNumber((item.quantity),0, ".", ","),
+                              // price_unity : accounting.formatNumber((item.price_unit * (CurrencyBase.rate_silent/currency.rate_silent)),0, ".", ","),
+                              price_unity : accounting.formatNumber((item.price_unit),0, ".", ","),
+                              // price_tot : accounting.formatNumber((item.quantity * (item.price_unit * (CurrencyBase.rate_silent/currency.rate_silent))),0, ".", ","),
+                              price_tot : accounting.formatNumber((item.quantity * (item.price_unit)),0, ".", ","),
+                              quantity_tot : (item.quantity),
+                              // price_tot_tot : ((item.quantity * (item.price_unit *(CurrencyBase.rate_silent/currency.rate_silent)))),
+                              price_tot_tot : ((item.quantity * (item.price_unit))),
+                              order_date : moment(servicio.order_date).format("DD/MM/YYYY"),
+                              date_invoice : (servicio.order_date),
+                              partner_id : servicio.partner_id[0],
+                              partner_name : servicio.partner_id[1],
+                              category_name : product.categ_id.complete_name,
+                              category_id : product.categ_id.id,
+                              user_id : self.valorNull(servicio.user_id[0]),
+                              user_name : servicio.user_id[1],
+                              state: state,
+                          });
+                  }
+            }
+            data.sort(function (a, b) {
+                 if (a.date_invoice > b.date_invoice) {
+                     return -1;
+                 }
+                 if (a.date_invoice < b.date_invoice) {
+                     return 1;
+                 }
+                 return 0;
+             });
+            this.rowsData=data;
+            self.content = data;
+            this.loadTable(data)
+          },
+
+          fectSearch: function(){
+              var self = this;
+              var today = moment().format('YYYY-MM-DD');
+              var yesterday = moment().add(-1, 'days').format('YYYY-MM-DD');
+              var month = moment().format('YYYY-MM');
+              var last_month = moment().add(-1, 'months').format('YYYY-MM');
+              var partner = this.$el.find('#partner').val().split('-');
+              var user = this.$el.find('#user').val().split('-');
+              var product = this.$el.find('#product').val().split('-');
+              var categ_ids = [];
+              var category = self.$el.find('#current-category').val();
+              var state = self.$el.find('#current-state').val();
+              var desde =this.$el.find('#from').val();
+              var hasta =this.$el.find('#to').val();
+              var content = self.content;
+
+              if ($('#A').is(":checked")){
+                  content = _.filter(content, function (inv){
+                      return moment(inv.date_invoice).format('YYYY-MM-DD') == today;
+                  });
+              }
+              if ($('#B').is(":checked")){
+                  content = _.filter(content, function (inv){
+                      return moment(inv.date_invoice).format('YYYY-MM-DD') == yesterday;
+                  });
+              }
+              if ($('#C').is(":checked")){
+                  content = _.filter(content, function (inv){
+                      return moment(inv.date_invoice).format('YYYY-MM') == month;
+                  });
+              }
+              if ($('#D').is(":checked")){
+                  content = _.filter(content, function (inv){
+                      return moment(inv.date_invoice).format('YYYY-MM') == last_month;
+                  });
+              }
+
+              if ($('#Z').is(":checked")){
+                  $('#datepicker').css('display','block');
+                  if (desde.length > 0){
+                      var date= desde.split('/');
+                      content = _.filter(content, function (inv){
+                          return inv.date_invoice >= (date[2]+"-"+date[1]+"-"+date[0]);
+                      });
+                  }
+                  if (hasta.length > 0){
+                      var date= hasta.split('/');
+                      content = _.filter(content, function (inv){
+                          return inv.date_invoice <= (date[2]+"-"+date[1]+"-"+date[0]);
+                      });
+                  }
+              }else{
+                  $('#datepicker').css('display','none');
+              }
+              if ($('#draft').is(":checked")){
+                  content = _.filter(content, function (inv){
+                      return inv.state == 'Pendiente';
+                  });
+              }
+              if ($('#in_progress').is(":checked")){
+                  content = _.filter(content, function (inv){
+                      return inv.state == 'En progreso';
+                  });
+              }
+              if ($('#done').is(":checked")){
+                  content = _.filter(content, function (inv){
+                      return inv.state == 'Realizado';
+                  });
+              }
+              if ($('#canceled').is(":checked")){
+                  content = _.filter(content, function (inv){
+                      return inv.state == 'Cancelado';
+                  });
+              }
+              if (partner != ""){
+                  content = _.filter(content, function(inv){
+                      return inv.partner_id == partner[0];
+                  });
+              }
+              if (product != ""){
+                  content = _.filter(content, function(inv){
+                      return inv.product_id == product[0];
+                  });
+              }
+
+              if(category){
+                  // Nivel 0, nivel 1
+                  var category_ids = _.map(_.filter(self.ProductCategory,function (item) {
+                      return item.id == category || item.parent_id[0] == category;
+                  }), function(map){
+                      return map.id;
+                  });
+
+                  // Nivel 0, nivel 1, nivel 2
+                  var category_children_ids = _.map(_.filter(self.ProductCategory,function (item) {
+                      return _.contains(category_ids, item.parent_id[0]) || item.id == category;
+                  }), function(map){
+                      return map.id;
+                  });
+
+                  var category_grandchildren_ids = _.map(_.filter(self.ProductCategory,function (item) {
+                      return _.contains(category_children_ids, item.parent_id[0]) || item.id == category;
+                  }), function(map){
+                      return map.id;
+                  }) ;
+
+                  categ_ids =  _.map(_.filter(self.ProductCategory,function (item) {
+                      return _.contains(category_grandchildren_ids, item.parent_id[0]) || item.id == category;
+                  }), function(map){
+                      return map.id;
+                  });
+              };
+
+              if(category && category != 9999999){
+                  content = _.filter(content,function (inv) {
+                      return _.contains(categ_ids, inv.category_id);
+                  });
+              }
+
+              if (user != ""){
+                  content = _.filter(content, function(inv){
+                      return inv.user_id == user[0];
+                  });
+              }
+
+              if(state && state != 9999999){
+                  content = _.flatten(_.filter(content,function (item) {
+                      return item.state == state;
+                  }));
+              }
+
+              var price_total_total = _.reduce(_.map(content,function(map){
+                  return(map.price_tot_tot);
+              }),function(memo, num){
+                  return memo + num;
+              },0);
+
+
+              content.push({
+                  name: "Totales:",
+                  quantity: accounting.formatNumber((quantity_tot_total),0,".",","),
+                  price_tot: accounting.formatNumber((price_total_total),0,".",","),
+              });
+
+              self.loadTable(content)
+          },
+
+          loadTable:function(rowsTable){
+              var self = this;
+              self.rowsData = rowsTable;
+              var table = this.$el.find('#table');
+              table.bootstrapTable('load', rowsTable);
+          },
+
+          getObjetPdf: function(rowsTable){
+              var self = this;
+              var rows=self.rowsData;
+
+              return rows;
+          },
+
+          clickOnAction: function (e) {
+              var self = this;
+              var rowsNew;
+              var action = this.$el.find(e.target).val();
+              var getColumns=[];
+              var rows=[];
+              rowsNew = self.getObjetPdf();
+              var table = this.$el.find("#table");
+              var data2 = table.bootstrapTable('getVisibleColumns');
+              if (action === 'pdf') {
+                  var dataNEW = _.map(data2, function (val){ return val.field});
+                  _.each(rowsNew,function (item){
+                      rows.push(_.pick(item, dataNEW));
+                  });
+                  // Obtener los nombre de la Cabezera
+                  _.each(_.map(data2,function(val){
+                      return val}), function(item){
+                      getColumns.push([{
+                                      title: item.title,
+                                      dataKey: item.field
+                                  }]);
+                  });
+                  // Llamar al pdf
+                  this.drawPDF(_.flatten(getColumns),rows)
+              }
+
+          },
+
+          drawPDF: function (getColumns,rows) {
+              var self = this;
+              var rowsPdf=[];
+              var desde =(this.$el.find('#from').val());
+              var hasta =(this.$el.find('#to').val());
+              var totalPagesExp = "{total_pages_count_string}";
+              var pdfDoc = new jsPDF('l');
+
+              var company = _.map(self.resCompany, function (map) {
+                  return map.currency_id[1];
+              });
+
+              pdfDoc.autoTable(getColumns, rows, {
+                  styles: { overflow: 'linebreak', fontSize: 7, columnWidth: 'wrap'},
+                  columnStyles: {
+                                name : {columnWidth: 20},
+                                order_date : {columnWidth: 20},
+                                partner_name : {columnWidth: 25},
+                                product_name : {columnWidth: 40},
+                                category_name : {columnWidth: 30},
+                                quantity : {halign:'right', columnWidth: 6},
+                                price_unity : {halign:'right', columnWidth: 18},
+                                price_tot : {halign:'right', columnWidth: 18},
+                                user_name : {columnWidth: 15},
+                                state: {columnWidth: 10},
+                            },
+                  margin: { top: 16, horizontal: 7},
+                  addPageContent: function (data) {
+                      pdfDoc.setFontSize(12);
+                      pdfDoc.setFontStyle('bold');
+                      pdfDoc.setTextColor(40);
+                      pdfDoc.text('Análisis de orden de servicio ', data.settings.margin.left, 10);
+
+                      if(desde.length > 0 || hasta.length > 0){
+                        var fecha='';
+                        if(desde){
+                          fecha=fecha.concat(' Desde '+desde);
+                        }
+                        if (hasta){
+                          fecha=fecha.concat(' Hasta '+hasta);
+                        }
+                          pdfDoc.setFontSize(10);
+                          pdfDoc.setFontStyle('bold');
+                          pdfDoc.setTextColor(40);
+                          pdfDoc.text(fecha, data.settings.margin.left,14);
+                      }
+                      // FOOTER
+                      var str = "Pagina  " + data.pageCount;
+                      // Total page number plugin only available in jspdf v1.0+
+                      if (typeof pdfDoc.putTotalPages === 'function') {
+                          str = str + " de " + totalPagesExp;
+                      }
+                      pdfDoc.setFontSize(9);
+                      pdfDoc.setFontStyle('bold');
+                      pdfDoc.setTextColor(40);
+                      pdfDoc.text(str, data.settings.margin.left, pdfDoc.internal.pageSize.height - 5);
+                  }
+              });
+
+              if (typeof pdfDoc.putTotalPages === 'function') {
+                  pdfDoc.putTotalPages(totalPagesExp);
+              }
+              pdfDoc.save('Análisis de orden de servicio.pdf')
+          },
+      });
+  }

+ 141 - 0
static/src/reports/report_orden_servicio_analytic.xml

@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<template xml:space="preserve">
+    <t t-name="ReportOrdenServicio">
+        <div class="report_view">
+      <div class="reporting_page_header">
+        <h1>Análisis de orden de servicio</h1>
+        <div id="volver"></div>
+      </div>
+      <button type="button" class="oe_button oe_form_button oe_highlight" aria-label="Left Align" data-toggle="collapse" href="#collapseExample" aria-expanded="false" aria-controls="collapseExample">FILTRAR
+        </button>
+        <div class="collapse" id="collapseExample">
+            <br/>
+            <div class="row">
+                <div class="col-xs-6">
+                    <div class="panel panel-default">
+                        <div class="panel-heading">Fechas</div>
+                        <div class="panel-body">
+                            <ul class="list-unstyled">
+                                <li>
+                                    <input type="radio" name="valores" id="X" value="X" checked="checked"/>
+                                    <label for="X">Sin Filtro</label>
+                                </li>
+                                <li>
+                                    <input type="radio" name="valores" id="A" value="A"/>
+                                    <label for="A">Hoy</label>
+                                </li>
+                                <li>
+                                    <input type="radio" name="valores" id="B" value="B"/>
+                                    <label for="B">Ayer</label>
+                                </li>
+                                <li>
+                                    <input type="radio" name="valores" id="C" value="C"/>
+                                    <label for="C">Mes Actual</label>
+                                </li>
+                                <li>
+                                    <input type="radio" name="valores" id="D" value="D"/>
+                                    <label for="D">Mes Pasado</label>
+                                </li>
+                                <li>
+                                    <input type="radio" name="valores" id="Z" value="Z"/>
+                                    <label for="Z">Busqueda Avanzada</label>
+                                </li>
+                            </ul>
+                            <div id="datepicker" style="display:none;" class="container">
+                                <label for="from">Desde: </label>
+                                <input type="text"  id="from" name="from"/>
+                                <label for="to" >Hasta: </label>
+                                <input type="text"  id="to" name="to" />
+                            </div>
+
+                        </div>
+                    </div>
+                </div>
+                <div class="col-xs-6">
+                    <div class="panel panel-default">
+                        <div class="panel-heading">Características</div>
+                        <div class="panel-body">
+                            <div class="form-group">
+                                <label for="partner">Buscar Cliente</label>
+                                <input id="partner" type="text" class="form-control ui-autocomplete-input" autocomplete="off"/>
+                            </div>
+                            <div class="form-group">
+                                <label>Categoria</label>
+                                <select id="current-category" class="form-control form-control-sm">
+                                </select>
+                            </div>
+                            <div class="form-group">
+                                <label for="product">Buscar Producto</label>
+                                <input id="product" type="text" class="form-control ui-autocomplete-input" autocomplete="off" placeholder="Nombre/ Referencia/ Codigo de barras"/>
+                            </div>
+
+                            <div class="form-group">
+                                <label for="user">Vendedor: </label>
+                                <input id="user" type="text" class="form-control ui-autocomplete-input" autocomplete="off" placeholder="Nombre/ CI"/>
+                            </div>
+                            <div class="form-group">
+                                <h3>Estado</h3>
+                                <ul class="list-unstyled">
+                                    <li>
+                                        <input type="radio" name="estado" id="W" value="W" checked="checked"/>
+                                        <label for="W">Sin Filtro</label>
+                                    </li>
+                                    <li>
+                                        <input type="radio" name="estado" id="open" value="draft"/>
+                                        <label for="open">Borrador</label>
+                                    </li>
+                                    <li>
+                                        <input type="radio" name="estado" id="in_progress" value="in_progress"/>
+                                        <label for="paid">En progreso</label>
+                                    </li>
+                                    <li>
+                                        <input type="radio" name="estado" id="done" value="done"/>
+                                        <label for="open">Realizado</label>
+                                    </li>
+                                    <li>
+                                        <input type="radio" name="estado" id="canceled" value="canceled"/>
+                                        <label for="paid">Cancelado</label>
+                                    </li>
+                                </ul>
+                            </div>
+
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+      <div id="toolbar">
+        <button class="oe_button oe_form_button oe_highlight" value="pdf">PDF</button>
+    </div>
+    <table id="table" class="table_paint_first_row"
+        data-pagination="true"
+        data-toggle="table"
+        data-reorderable-columns="true"
+        data-toolbar="#toolbar"
+        data-show-columns="true"
+        data-buttons-class="oe_button oe_form_button oe_highlight"
+        data-height="auto"
+        data-classes="table table-hover table-condensed"
+        data-row-style="rowStyle"
+        data-search="true">
+        <thead>
+          <tr>
+            <th data-field="name" data-sortable="true">Ref.</th>
+            <th data-field="order_date">Fecha</th>
+            <th data-field="partner_name" data-sortable="true">Cliente</th>
+            <th data-field="product_name" >Producto</th>
+            <th data-field="category_name" data-sortable="true">Categoria</th>
+            <th data-field="quantity" data-sortable="true" data-align="right">Cant.</th>
+            <th data-field="price_unity" data-sortable="true" data-align="right">Precio Venta</th>
+            <th data-field="price_tot" data-sortable="true" data-align="right">Total Venta</th>
+            <th data-field="user_name" data-sortable="true">Usuario</th>
+            <th data-field="state">Estado</th>
+          </tr>
+        </thead>
+    </table>
+    <!-- <canvas></canvas> -->
+    <div class="widget-content" id="grafico"></div>
+    <div id="dialog"></div>
+  </div>
+  </t>
+</template>

+ 5 - 0
static/src/xml/eiru_reporting.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    
+</template>

+ 5 - 0
static/src/xml/eiru_reporting_base.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    
+</template>

+ 21 - 0
templates.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+  <data>
+    <template id="eiru_reports_servicio_assets" inherit_id="eiru_assets.assets">
+      <xpath expr="." position="inside">
+        <link rel="stylesheet" href="/eiru_reports_servicio/static/src/css/custom.css"/>
+
+        <!-- configuration < main > -->
+        <script type="text/javascript" src="/eiru_reports_servicio/static/src/js/main.js"/>
+        <script type="text/javascript" src="/eiru_reports_servicio/static/src/js/reporting_base.js"/>
+
+
+        <!--============================= Analisis de presupuestos ==============================-->
+        <script type="text/javascript" src="/eiru_reports_servicio/static/src/js/reports/report_orden_servicio_analytic.js"/>
+
+
+
+      </xpath>
+    </template>
+  </data>
+</openerp>

+ 11 - 0
views/actions.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+	<data>
+
+		<record id="ordenservicio_analytic_action" model="ir.actions.client">
+			 <field name="name">Análisis de orden de servicio</field>
+			 <field name="tag">eiru_reports_servicio.ordenservicio_analytic_action</field>
+	 </record>
+
+	</data>
+</openerp>

+ 11 - 0
views/menus.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+  <data>
+
+    <!-- sub menu -->
+
+    <menuitem id="ordenservicio_analytic_menu" parent="eiru_reports.sale_parent_menu" name="Análisis de orden de servicio" action="ordenservicio_analytic_action" sequence="3"/>
+
+
+  </data>
+</openerp>