Prechádzať zdrojové kódy

Listado de utilidad por lineas de venta

Sebas 5 rokov pred
commit
325185f66c

+ 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 Decorart",
+    'author': "Eiru",
+    'category': 'Reports',
+    'version': '0.1',
+    'depends': [
+        'base',
+        'sale',
+        'eiru_reports',
+        'product_brand',
+    ],
+    '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


+ 809 - 0
models.py

@@ -0,0 +1,809 @@
+# -*- coding: utf-8 -*-
+
+from openerp import models, fields, api
+
+class AccountInvoice(models.Model):
+	_inherit = 'account.invoice'
+
+	############################################################
+	#	ACCOUNT INVOICE
+	############################################################
+
+	@api.model
+	def getAccountInvoice(self,domain):
+		AccountInvoice = self.env['account.invoice'].search(domain)
+		decimal_precision = self.env['decimal.precision'].precision_get('Account')
+		values = []
+		for invoice in AccountInvoice:
+			values.append({
+				'id': invoice.id,
+				'type': invoice.type,
+				'state': invoice.state,
+				'number': invoice.number,
+				'journal_id': [
+					invoice.journal_id.id,
+					invoice.journal_id.name
+				],
+				'journal_type': invoice.journal_id.type,
+				'invoice_currency': [
+					invoice.currency_id.id,
+					invoice.currency_id.name,
+					invoice.currency_id.rate
+				],
+				'company_currency': [
+					invoice.company_id.currency_id.id,
+					invoice.company_id.currency_id.name,
+					invoice.company_id.currency_id.rate
+				],
+				'date_invoice': invoice.date_invoice,
+				'partner_id': [
+					invoice.partner_id.id,
+					invoice.partner_id.name,
+					invoice.partner_id.ruc,
+				],
+				'partner_info': {
+					'mobile': invoice.partner_id.mobile,
+					'phone': invoice.partner_id.phone,
+				},
+				'supplier_invoice_number': invoice.supplier_invoice_number,
+				'user_id': [
+					invoice.user_id.id,
+					invoice.user_id.name
+				],
+                'period_id': [
+                	invoice.period_id.id,
+                	invoice.period_id.name
+                ],
+                'amount_untaxed': invoice.amount_untaxed,
+                'origin': invoice.origin,
+                'residual': invoice.residual,
+                'amount_tax': invoice.amount_tax,
+				'amount_total': invoice.amount_total,
+				'amount_untaxed_currency': invoice.amount_untaxed * (invoice.company_id.currency_id.rate / invoice.currency_id.rate),
+				'residual_currency': invoice.residual * (invoice.company_id.currency_id.rate / invoice.currency_id.rate),
+				'amount_tax_currency': invoice.amount_tax * (invoice.company_id.currency_id.rate / invoice.currency_id.rate),
+				'amount_total_currency': invoice.amount_total * (invoice.company_id.currency_id.rate / invoice.currency_id.rate),
+			})
+
+		return values
+
+	############################################################
+	#	POS ORDER
+	############################################################
+
+	@api.model
+	def getPosOrder(self,domain):
+		PosOrder = self.env['pos.order'].search(domain)
+		decimal_precision = self.env['decimal.precision'].precision_get('Account')
+		values = []
+		for order in PosOrder:
+			values.append({
+				'id': order.id,
+				'name': order.name,
+				'date_order': order.date_order,
+				'pricelist_id':[
+					order.pricelist_id.id,
+					order.pricelist_id.name,
+				],
+				'sale_journal':[
+					order.sale_journal.id,
+					order.sale_journal.name,
+				],
+				'partner_id': [
+					order.partner_id.id,
+					order.partner_id.name,
+					order.partner_id.ruc,
+				],
+				'user_id': [
+					order.user_id.id,
+					order.user_id.name
+				],
+				'session_id': [
+					order.session_id.id,
+					order.session_id.name
+				],
+				'order_currency': [
+					order.pricelist_id.currency_id.id,
+					order.pricelist_id.currency_id.name,
+					order.pricelist_id.currency_id.rate
+				],
+				'company_currency': [
+					order.company_id.currency_id.id,
+					order.company_id.currency_id.name,
+					order.company_id.currency_id.rate
+				],
+                'amount_tax': order.amount_tax,
+                'amount_total': order.amount_total,
+				'amount_tax_currency': order.amount_tax * (order.company_id.currency_id.rate / order.pricelist_id.currency_id.rate),
+				'amount_total_currency': order.amount_total * (order.company_id.currency_id.rate / order.pricelist_id.currency_id.rate),
+			})
+
+		return values
+
+class AccountInvoiceLine(models.Model):
+	_inherit = 'account.invoice.line'
+
+	############################################################
+	#	ACCOUNT INVOICE LINE
+	############################################################
+
+	@api.model
+	def getAccountInvoiceLine(self,domain):
+		AccountInvoiceLine = self.env['account.invoice.line'].search(domain)
+		decimal_precision = self.env['decimal.precision'].precision_get('Account')
+		values = []
+		for line in AccountInvoiceLine:
+			values.append({
+				'id': line.id,
+				'invoice_id':line.invoice_id.id,
+				'number':line.invoice_id.number,
+				'supplier_invoice_number':line.invoice_id.supplier_invoice_number,
+				'date_invoice': line.invoice_id.date_invoice,
+				'user_id': [
+					line.invoice_id.user_id.id,
+					line.invoice_id.user_id.name,
+				],
+				'partner_id': [
+					line.invoice_id.partner_id.id,
+					line.invoice_id.partner_id.name,
+					line.invoice_id.partner_id.ruc,
+				],
+				'store_id': [
+					line.invoice_id.journal_id.store_ids.id,
+					line.invoice_id.journal_id.store_ids.name,
+				],
+				'period_id': [
+					line.invoice_id.period_id.id,
+					line.invoice_id.period_id.name,
+				],
+				'journal_id': [
+					line.invoice_id.journal_id.id,
+					line.invoice_id.journal_id.name,
+				],
+				'invoice_state': line.invoice_id.state,
+				'journal_type': line.invoice_id.journal_id.type,
+				'invoice_type': line.invoice_id.type,
+				'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.price_subtotal,
+				'quantity': line.quantity,
+				'company_currency':[
+					line.invoice_id.company_id.currency_id.id,
+					line.invoice_id.company_id.currency_id.name,
+					line.invoice_id.company_id.currency_id.rate,
+				],
+				'invoice_currency':[
+					line.invoice_id.currency_id.id,
+					line.invoice_id.currency_id.name,
+					line.invoice_id.currency_id.rate,
+				],
+				'price_unit_currency': round(line.price_unit * (line.invoice_id.company_id.currency_id.rate / line.invoice_id.currency_id.rate),decimal_precision),
+				'price_subtotal_currency': round(line.price_subtotal * (line.invoice_id.company_id.currency_id.rate / line.invoice_id.currency_id.rate),decimal_precision),
+				'tax_currency': round((line.price_unit * (line.invoice_id.company_id.currency_id.rate / line.invoice_id.currency_id.rate) * line.quantity) - line.price_subtotal * (line.invoice_id.company_id.currency_id.rate / line.invoice_id.currency_id.rate),decimal_precision),
+				'amount_currency': round((line.quantity * line.price_unit) * (line.invoice_id.company_id.currency_id.rate / line.invoice_id.currency_id.rate),decimal_precision),
+			})
+
+		return values
+
+	############################################################
+	#	POS ORDER LINE
+	############################################################
+
+	@api.model
+	def getPosOrderLine(self,domain):
+		PosOrderLine = self.env['pos.order.line'].search(domain)
+		decimal_precision = self.env['decimal.precision'].precision_get('Account')
+		values = []
+		for line in PosOrderLine:
+			values.append({
+				'id': line.id,
+				'order_id': [
+					line.order_id.id,
+					line.order_id.name
+				],
+				'product_id': [
+					line.product_id.id,
+					line.product_id.display_name,
+					line.product_id.standard_price,
+				],
+				'store_id': [
+					line.order_id.sale_journal.store_ids.id,
+					line.order_id.sale_journal.store_ids.name,
+				],
+				'sale_journal': [
+					line.order_id.sale_journal.id,
+					line.order_id.sale_journal.name,
+				],
+				'qty': line.qty,
+				'create_date': line.create_date,
+				'user_id': [
+					line.order_id.user_id.id,
+					line.order_id.user_id.name
+				],
+				'partner_id': [
+					line.order_id.partner_id.id,
+					line.order_id.partner_id.name,
+				],
+				'company_currency':[
+					line.order_id.company_id.currency_id.id,
+					line.order_id.company_id.currency_id.name,
+					line.order_id.company_id.currency_id.rate,
+				],
+				'order_currency':[
+					line.order_id.pricelist_id.currency_id.id,
+					line.order_id.pricelist_id.currency_id.name,
+					line.order_id.pricelist_id.currency_id.rate,
+				],
+				'price_unit': line.price_unit,
+				'price_subtotal': line.price_subtotal,
+				'price_subtotal_incl': line.price_subtotal_incl,
+				'price_unit_currency': round(line.price_unit * (line.order_id.company_id.currency_id.rate / line.order_id.pricelist_id.currency_id.rate),decimal_precision),
+				'price_subtotal_currency': round(line.price_subtotal * (line.order_id.company_id.currency_id.rate / line.order_id.pricelist_id.currency_id.rate),decimal_precision),
+				'price_subtotal_incl_currency': round(line.price_subtotal_incl * (line.order_id.company_id.currency_id.rate / line.order_id.pricelist_id.currency_id.rate),decimal_precision),
+				# 'amount_currency': round(line.price_subtotal_incl * (line.order_id.company_id.currency_id.rate / line.order_id.pricelist_id.currency_id.rate),decimal_precision)
+			})
+
+		return values
+
+class AccountJournal(models.Model):
+	_inherit = 'account.journal'
+
+	@api.model
+	def getAccountJournal(self,domain):
+		AccountJournal = self.env['account.journal'].search(domain)
+		values = []
+		for journal in AccountJournal:
+			if(journal.currency):
+				complete_name = journal.name + ' (' + journal.currency.local_name + ')'
+			else:
+				complete_name = journal.name + ' (' + journal.company_id.currency_id.local_name + ')'
+			values.append({
+				'id': journal.id,
+				'name': journal.name,
+				'complete_name': complete_name,
+				'type': journal.type,
+				'store_ids': [
+					journal.store_ids.id,
+					journal.store_ids.name,
+				],
+				'company_id': [
+					journal.company_id.id,
+					journal.company_id.name
+				],
+				'currency': [
+					journal.currency.id,
+					journal.currency.name
+				],
+			})
+
+		return values
+
+class AccountBankStatementLine(models.Model):
+	_inherit = 'account.bank.statement.line'
+
+	@api.model
+	def getAccountBankStatementLine(self,domain):
+		AccountBankStatementLine = self.env['account.bank.statement.line'].search(domain)
+		decimal_precision = self.env['decimal.precision'].precision_get('Account')
+		values = []
+		for line in AccountBankStatementLine:
+			try:
+				pos_statement_id = line.pos_statement_id.id
+				partner_id = [line.partner_id.id,line.partner_id.name]
+			except:
+				pos_statement_id = ''
+				partner_id = ''
+
+			if(line.journal_id.currency):
+				amount_currency = round(line.amount * (line.company_id.currency_id.rate / line.journal_id.currency.rate),decimal_precision),
+			else:
+				amount_currency = line.amount
+
+			values.append({
+				'id': line.id,
+				'name': line.name,
+				'date': line.date,
+				'partner_id': partner_id,
+				'ref': line.ref,
+				'currency_id': [
+					line.currency_id.id,
+					line.currency_id.name,
+				],
+				'journal_id': [
+					line.journal_id.id,
+					line.journal_id.name,
+				],
+				'pos_statement_id': pos_statement_id,
+				'amount': line.amount,
+				'amount': line.amount_currency,
+				'amount_currency': amount_currency
+			})
+
+		return values
+
+class AccountMoveLine(models.Model):
+	_inherit = 'account.move.line'
+
+	@api.model
+	def getAccountMoveLine(self,domain):
+		AccountMoveLine = self.env['account.move.line'].search(domain)
+		decimal_precision = self.env['decimal.precision'].precision_get('Account')
+		values = []
+		for line in AccountMoveLine:
+
+			values.append({
+				'id': line.id,
+				'name': line.name,
+				'date': line.date,
+				'date_maturity': line.date_maturity,
+				'reconcile_ref': line.reconcile_ref,
+				'amount_residual': line.amount_residual,
+				'partner_id': [
+					line.partner_id.id,
+					line.partner_id.name,
+				],
+				'move_id': [
+					line.move_id.id,
+					line.move_id.name,
+				],
+				'account_id': [
+					line.account_id.id,
+					line.account_id.name,
+				],
+				'journal_id': [
+					line.journal_id.id,
+					line.journal_id.name,
+				],
+				'debit': line.debit,
+				'credit': line.credit,
+			})
+
+		return values
+
+class AccountAccount(models.Model):
+	_inherit = 'account.account'
+
+	@api.model
+	def getAccountAccount(self,domain):
+		AccountAccount = self.env['account.account'].search(domain)
+		values = []
+		for account in AccountAccount:
+			values.append({
+				'id': account.id,
+				'name': account.name,
+			})
+
+		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 AccountVoucher(models.Model):
+	_inherit = 'account.voucher'
+
+	@api.model
+	def getAccountVoucher(self,domain):
+		AccountVoucher = self.env['account.voucher'].search(domain)
+		values = []
+		for voucher in AccountVoucher:
+			values.append({
+				'id': voucher.id,
+				'number': voucher.number,
+				'create_uid': voucher.create_uid.name,
+				'partner_id': [
+					voucher.partner_id.id,
+					voucher.partner_id.name,
+				],
+				'journal_id': [
+					voucher.journal_id.id,
+					voucher.journal_id.name,
+				],
+				'period_id': [
+					voucher.period_id.id,
+					voucher.period_id.name,
+				],
+				'currency_id': [
+					voucher.currency_id.id,
+					voucher.currency_id.name,
+				],
+				'reference': voucher.reference,
+				'date': voucher.date,
+				'amount': voucher.amount,
+				'amount_currency': voucher.amount * (voucher.company_id.currency_id.rate / voucher.currency_id.rate),
+			})
+
+		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
+
+
+	############################################################
+	#	PRODUCT BRAND
+	############################################################
+
+	@api.model
+	def getProductBrand(self,domain):
+		ProductBrand = self.env['product.brand'].search(domain)
+		values = []
+		for brand in ProductBrand:
+			values.append({
+				'id': brand.id,
+				'name': brand.name,
+			})
+
+		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 ProductAttribute(models.Model):
+	_inherit = 'product.attribute'
+
+	@api.model
+	def getProductAttribute(self,domain):
+		ProductAttribute = self.env['product.attribute'].search(domain)
+		values = []
+		for attribute in ProductAttribute:
+			values.append({
+				'id': attribute.id,
+				'name': attribute.name,
+			})
+
+		return values
+
+class ProductAttributeValue(models.Model):
+	_inherit = 'product.attribute.value'
+
+	@api.model
+	def getProductAttributeValue(self,domain):
+		ProductAttributeValue = self.env['product.attribute.value'].search(domain)
+		values = []
+		for value in ProductAttributeValue:
+			values.append({
+				'id': value.id,
+				'name': value.name,
+				'attribute_id': [
+					value.attribute_id.id,
+					value.attribute_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
+
+class StockQuant(models.Model):
+	_inherit = 'stock.quant'
+
+	@api.model
+	def getStockQuant(self,domain):
+		StockQuant = self.env['stock.quant'].search(domain)
+		values = []
+		for quant in StockQuant:
+			values.append({
+				'id': quant.id,
+				'name': quant.name,
+				'display_name': quant.display_name,
+				'location_id': [
+					quant.location_id.id,
+					quant.location_id.name,
+				],
+				'product_id': [
+					quant.product_id.id,
+					quant.product_id.name,
+				],
+				'qty': quant.qty,
+			})
+
+		return values
+
+class StockMove(models.Model):
+	_inherit = 'stock.move'
+
+	@api.model
+	def getStockMove(self,domain):
+		StockMove = self.env['stock.move'].search(domain)
+		values = []
+		for move in StockMove:
+		    values.append({
+		        'id': move.id,
+		        'create_date' : move.create_date,
+		        'name': move.name,
+		        'state' : move.state,
+		        'location_id': {
+		            'id' : move.location_id.id,
+		            'complete_name' : move.location_id.complete_name,
+		            'store_id' : move.location_id.store_id.id,
+		        },
+		        'location_dest_id': {
+		            'id' : move.location_dest_id.id,
+		            'complete_name' : move.location_dest_id.complete_name,
+		            'store_id' : move.location_dest_id.store_id.id,
+		        },
+		        'origin' : move.origin,
+		        'picking_id' : {
+		            'id' : move.picking_id.id,
+		            'name' : move.picking_id.name,
+		            },
+		        'partner_id' : {
+		            'id' : move.partner_id.id,
+		            'name' : move.partner_id.name,
+		        },
+		        'product_id': {
+		            'id' : move.product_id.id,
+		            'display_name' : move.product_id.display_name,
+
+		        },
+		        'product_uom_qty': move.product_uom_qty,
+		    })
+
+		return values
+
+class StockPicking(models.Model):
+	_inherit = 'stock.picking'
+
+	@api.model
+	def getStockPicking(self,domain):
+		StockPicking = self.env['stock.picking'].search(domain)
+		values = []
+		for picking in StockPicking:
+		    values.append({
+		        'id' : picking.id,
+		        'date' : picking.create_date,
+		        'name' : picking.name,
+		        'state' : picking.state,
+		        'partner_id' : {
+		            'id' : picking.partner_id.id,
+		            'name' : picking.partner_id.name,
+		        },
+		        'move_type' : picking.move_type,
+		        'picking_type_id' : {
+		            'id' : picking.picking_type_id.id,
+		            'name' : picking.picking_type_id.name,
+		        },
+		        'date_done' : picking.date_done,
+		        'priority' : picking.priority,
+
+		    })
+
+		return values
+
+class ProductPriceList(models.Model):
+	_inherit = 'product.pricelist'
+
+	@api.model
+	def getProductPriceList(self,domain):
+		ProductPriceList = self.env['product.pricelist'].search(domain)
+		values = []
+
+		for pricelist in ProductPriceList:
+			version_ids = map(lambda x: x.id, pricelist.version_id)
+			versionIDS = []
+			for item in self.env['product.pricelist'].search([('id', 'in', version_ids)]):
+				versionIDS.append(item.id)
+
+			values.append({
+		        'id' : pricelist.id,
+		        'name' : pricelist.name,
+		        'type' : pricelist.type,
+		        'version_id' : versionIDS,
+		        'store_id' : {
+		            'id' : pricelist.store_id.id,
+		            'name' : pricelist.store_id.name,
+		        },
+		        'currency_id' : {
+		            'id' : pricelist.currency_id.id,
+		            'name' : pricelist.currency_id.name,
+					'rate_silent': pricelist.currency_id.rate_silent,
+		        },
+		    })
+
+		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_decorart = function(instance) {
+  "use strict";
+
+  var reporting = instance.eiru_reports_decorart;
+
+  reporting_base(instance, reporting);
+
+  try {
+    report_saledecorart_utility_analytic(reporting);
+
+  } catch (e) {
+    // ignorar error
+  }
+
+  // analisis de nominas
+  instance.web.client_actions.add('eiru_reports_decorart.saledecorart_analytic_action', 'instance.eiru_reports_decorart.ReportSaleDecorartUtilityAnalyticWidget');
+
+}

+ 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;
+        }
+    });
+}

+ 885 - 0
static/src/js/reports/report_saledecorart_utility_analytic.js

@@ -0,0 +1,885 @@
+function report_saledecorart_utility_analytic(reporting){
+    "use strict";
+
+    var model = openerp;
+
+    reporting.ReportSaleDecorartUtilityAnalyticWidget = reporting.Base.extend({
+        template: 'ReportSaleDecorartUtilityAnalytic',
+          invoices: [],
+          invoiceLines: [],
+          productProduct:[],
+          ResCurrency:[],
+          AccountVoucher:[],
+          AccountMoveLine:[],
+          rowsData :[],
+          content :[],
+          rowOrigin:[],
+          accountJournal:[],
+          resCompany:[],
+          events:{
+              'click #toolbar > button' : 'clickOnAction',
+              'click #X' : 'fectSearch',
+              'click #A' : 'fectSearch',
+              'click #B' : 'fectSearch',
+              'click #C' : 'fectSearch',
+              'click #D' : 'fectSearch',
+              'click #Z' : 'fectSearch',
+              'change #current-store': 'fectSearch',
+              'change #current-journal': '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.fecthResStore();
+              }).then(function(ResStore){
+                  self.ResStore = ResStore;
+                  self.$el.find('#current-store').append('<option value="9999999">Todas las Sucursales</option>');
+                  _.each(ResStore,function(item){
+                      self.$el.find('#current-store').append('<option value="' + item.id + '">' + item.name + '</option>');
+                  });
+                   return self.fecthAccountJournal();
+              }).then(function(AccountJournal){
+                  self.AccountJournal = AccountJournal;
+                  self.$el.find('#current-journal').append('<option value="9999999">Todas las formas de pagos</option>');
+                  _.each(AccountJournal,function(item){
+                      self.$el.find('#current-journal').append('<option value="' + item.id + '">' + item.name + '</option>');
+                  });
+                  return self.fetchInvoiceV2();
+              }).then(function (invoices){
+                  self.invoices = invoices;
+                  return self.fetchInvoiceLine(invoices);
+              }).then(function (invoiceLines) {
+                  self.invoiceLines = invoiceLines;
+                  return self.fetchProductProduct();
+              }).then(function(ProductProduct){
+                  self.ProductProduct = ProductProduct;
+                  return self.fetchProductAttribute();
+              }).then(function (ProductAttribute) {
+                  self.ProductAttribute = ProductAttribute;
+                  if(ProductAttribute.length > 0){
+                      self.$el.find('#current-attribute').append('<option value="9999999">Todos los atributos</option>');
+                      _.each(ProductAttribute,function(item){
+                          self.$el.find('#current-attribute').append('<option value="' + item.id + '">' + item.name + '</option>');
+                      });
+                  }else{
+                      self.$el.find('.attribute').css('display','none');
+                  }
+                  return self.fetchProductAttributeValue();
+              }).then(function(ProductAttributeValue){
+                  self.ProductAttributeValue = ProductAttributeValue;
+                  if(ProductAttributeValue.length > 0){
+                      self.$el.find('#current-attribute-value').append('<option value="9999999">Todos los valores de atributos</option>');
+                      _.each(ProductAttributeValue,function(item){
+                          self.$el.find('#current-attribute-value').append('<option value="' + item.id + '">' + item.name + '</option>');
+                      });
+                  }else{
+                      self.$el.find('.attribute-value').css('display','none');
+                  }
+                  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.fetchAccountVoucher();
+              }).then(function (AccountVoucher) {
+                  self.AccountVoucher = AccountVoucher;
+                  return self.fetchAccountMoveLine();
+              }).then(function (AccountMoveLine){
+                  self.AccountMoveLine = AccountMoveLine;
+                  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();
+              });
+          },
+
+          fecthResStore: function(){
+              var self = this;
+              var defer = $.Deferred();
+              var field=['id', 'name'];
+              var ResStore = new model.web.Model('res.store');
+              ResStore.query(field).all().then(function(results){
+                  defer.resolve(results);
+              });
+              return defer;
+          },
+
+          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();
+                  }
+              });
+          },
+
+          fecthAccountJournal: function(){
+              var self = this;
+              var defer = $.Deferred();
+              var field = ['id', 'name','store_ids'];
+              var domain = [['active','=',true],['type','in',['sale','bank','cash']]];
+              var AccountJournal = new model.web.Model('account.journal');
+              AccountJournal.query(field).filter(domain).all().then(function(results){
+                  defer.resolve(results);
+              });
+              return defer;
+          },
+
+          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;
+          },
+
+          // Invoice (FACTURAS)
+          fetchInvoiceV2: function () {
+              var self = this;
+              var filter ="[['state', 'in',['open','paid']],['type', '=', 'out_invoice']";
+              var journal_ids = _.flatten(_.map(self.AccountJournal, function (item) {
+                  return item.id;
+              }));
+              if (journal_ids){
+                  filter=filter.concat(",['journal_id', 'in',["+journal_ids+"]]");
+              }
+              filter=filter.concat("]");
+              var field =['id', 'type', 'number', 'origin', 'state', 'journal_id', 'currency_id', 'invoice_line','date_invoice','partner_id' ,'user_id', 'reference' ,'payment_ids'];
+              var defer = $.Deferred();
+              var Invoice = new model.web.Model('account.invoice');
+              Invoice.query(field).filter(filter).all().then(function (results) {
+                  defer.resolve(results);
+              });
+              return defer;
+          },
+
+          // Invoice line (Linea de Factura)
+          fetchInvoiceLine: function (invoices) {
+              var defer = $.Deferred();
+              var linesIds = _.flatten(_.map(invoices, function (item) {
+                  return item.invoice_line;
+              }));
+              var InvoiceLine = new model.web.Model('account.invoice.line');
+              InvoiceLine.query(['id', 'quantity', 'price_unit', 'discount', 'name', 'product_id', 'origin','invoice_id']).filter([['id', 'in', linesIds]]).all().then(function (results) {
+                  defer.resolve(results)
+              });
+              return defer;
+          },
+
+          /*
+          ====================================================================
+              ACCOUNT INVOICE LINE
+          ====================================================================
+          */
+          fetchAccountMoveLine: function (){
+              var self = this;
+              var defer = $.Deferred();
+              var invoice_numbers = _.flatten(_.map(self.invoices, function (item) {
+                  return item.number;
+              }));
+              var domain = [
+                  ['move_id','in',invoice_numbers],
+                  ['debit','>',0],
+                  ['date_maturity','!=', false]
+              ];
+
+              var AccountMoveLine = new model.web.Model('account.move.line');
+              AccountMoveLine.query(['id', 'move_id','journal_id']).filter(domain).all().then(function(results){
+                  defer.resolve(results);
+              });
+              return defer;
+          },
+
+
+          fetchAccountVoucher: function () {
+              var self = this;
+              var defer = $.Deferred();
+              var AccountVoucher = new model.web.Model('account.voucher');
+              AccountVoucher.query(['id', 'number','reference','journal_id','type']).filter([['state', '=', 'posted']]).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.invoices,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.invoiceLines, 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;
+          },
+
+          fetchProductAttribute : function(){
+              var self = this;
+              var defer = $.Deferred();
+              var fields = ['id','name'];
+              var ProductAttribute = new model.web.Model('product.attribute');
+              ProductAttribute.query(fields).filter().all().then(function(results) {
+                  defer.resolve(results);
+              });
+              return defer;
+          },
+
+          fetchProductAttributeValue : function(){
+              var self = this;
+              var defer = $.Deferred();
+              var fields = ['id','name','attribute_id'];
+              var ProductAttributeValue = new model.web.Model('product.attribute.value');
+              ProductAttributeValue.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
+          getInvoice: function (id_line){
+              var self = this;
+              return _.find(this.invoices, function (inv) {
+                  return _.contains(inv.invoice_line, id_line);
+              });
+          },
+
+          getAccountVoucher: function (id) {
+              var self = this;
+              return _.filter(self.AccountVoucher,function (item) {
+                  return item.reference === id;
+              });
+          },
+
+          getAccountMoveLine: function (number) {
+              var self = this;
+              return _.filter(self.AccountMoveLine,function (item) {
+                  return item.move_id[1] === number;
+              });
+          },
+
+          // 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);
+              });
+          },
+
+          getAccountJournal: function (id) {
+              var self = this;
+              return _.filter(self.AccountJournal,function (item) {
+                  return item.id === id;
+              });
+          },
+
+          fectUtility: function(){
+              var self = this;
+              var data=[];
+              var CurrencyBase = self.getResCurrency(self.resCompany[0].currency_id[0]).shift();
+              var item;
+              var invoice=[];
+              var voucher=[];
+              var product;
+
+              for (var i = 0; i < this.invoiceLines.length; i++) {
+                  item = this.invoiceLines[i];
+                  invoice = this.getInvoice(item.id);
+                  var currency = self.getResCurrency(invoice.currency_id[0]).shift();
+                  voucher = self.getAccountMoveLine(invoice.number);
+                  var x = voucher.length;
+
+
+
+                  product =this.getProductProduct(item.product_id);
+
+                  if (product != undefined){
+                      var store_id = self.getAccountJournal(invoice.journal_id[0]);
+                      if(store_id.length > 0){
+                          data.push({
+                              id : invoice.id,
+                              number : (invoice.number),
+                              product_id : item.product_id[0],
+                              product_name : item.product_id[1],
+                              ean13 : self.valorNull(product.ean13),
+                              quantity : accounting.formatNumber((item.quantity),0, ".", ","),
+                              price_unity : accounting.formatNumber((item.price_unit * (CurrencyBase.rate_silent/currency.rate_silent)),0, ".", ","),
+                              standar_price : accounting.formatNumber((product.standard_price),0, ".", ","),
+                              price_tot : accounting.formatNumber((item.quantity * (item.price_unit * (CurrencyBase.rate_silent/currency.rate_silent))),0, ".", ","),
+                              standar_tot : accounting.formatNumber((item.quantity * product.standard_price),0, ".", ","),
+                              utility : accounting.formatNumber((((item.quantity * (item.price_unit * (CurrencyBase.rate_silent/currency.rate_silent))) - (item.quantity * product.standard_price))/x),0, ".", ","),
+                              quantity_tot : (item.quantity),
+                              price_tot_tot : ((item.quantity * (item.price_unit *(CurrencyBase.rate_silent/currency.rate_silent)))),
+                              standar_tot_tot : ((item.quantity * product.standard_price)),
+                              utility_tot : ((((item.quantity * (item.price_unit * (CurrencyBase.rate_silent/currency.rate_silent))) - (item.quantity * product.standard_price)))/x),
+                              date_create : moment(invoice.date_invoice).format("DD/MM/YYYY"),
+                              date_invoice : (invoice.date_invoice),
+                              partner_id : invoice.partner_id[0],
+                              partner_name : invoice.partner_id[1],
+                              category_name : product.categ_id.complete_name,
+                              category_id : product.categ_id.id,
+                              attribute_ids : product.attribute_ids,
+                              attribute_value_ids : product.atribute_value_ids,
+                              user_id : self.valorNull(invoice.user_id[0]),
+                              user_name : invoice.user_id[1],
+                              store_id : store_id[0].store_ids[0],
+                          });
+                      }
+                  }
+
+            }
+            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 attribute = self.$el.find('#current-attribute').val();
+              var attribute_value = self.$el.find('#current-attribute-value').val();
+              var desde =this.$el.find('#from').val();
+              var hasta =this.$el.find('#to').val();
+              var store = this.$el.find('#current-store').val();
+              var journal = this.$el.find('#current-journal').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 (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(store != 9999999){
+                  content =_.filter(content, function (inv){
+                      return inv.store_id == store;
+                  });
+              }
+
+              if(journal != 9999999){
+                  content =_.filter(content, function (inv){
+                      return inv.journal_id == journal;
+                  });
+              }
+
+              if (user != ""){
+                  content = _.filter(content, function(inv){
+                      return inv.user_id == user[0];
+                  });
+              }
+
+              if(attribute && attribute != 9999999 && attribute_value == 9999999){
+                  content = _.filter(content,function (inv) {
+                      return _.contains(inv.attribute_ids, parseInt(attribute));
+                  });
+              }
+
+              if(attribute_value && attribute_value != 9999999){
+                  content = _.filter(content,function (inv) {
+                      return _.contains(inv.attribute_value_ids, parseFloat(attribute_value));
+                  });
+              }
+
+              var quantity_tot_total = _.reduce(_.map(content,function(map){
+                  return(map.quantity_tot);
+              }),function(memo, num){
+                  return memo + num;
+              },0);
+
+              var price_total_total = _.reduce(_.map(content,function(map){
+                  return(map.price_tot_tot);
+              }),function(memo, num){
+                  return memo + num;
+              },0);
+
+              var standar_total_total = _.reduce(_.map(content,function(map){
+                  return(map.standar_tot_tot);
+              }),function(memo, num){
+                  return memo + num;
+              },0);
+
+              var amount_total_total = _.reduce(_.map(content,function(map){
+                  return(map.utility_tot);
+              }),function(memo, num){
+                  return memo + num;
+              },0);
+
+              content.push({
+                  number: "Totales:",
+                  quantity: accounting.formatNumber((quantity_tot_total),0,".",","),
+                  price_tot: accounting.formatNumber((price_total_total),0,".",","),
+                  standar_tot: accounting.formatNumber((standar_total_total),0,".",","),
+                  utility: accounting.formatNumber((amount_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)
+              }
+              if (action === 'chart'){
+                  var suc = this.$el.find('#current-journal').val();
+                  if (suc == 9999999){
+                      self.fectCharFilter();
+                  }else{
+                      $("#dialog" ).dialog({
+                          autoOpen: true,
+                          resizable: false,
+                          modal: true,
+                          title: 'Atención',
+                          open: function() {
+                              $(this).html('Para Generar el Gráfico debes Seleccionar todas las Sucursales');
+                          },
+                          show: {
+                              effect: "shake",
+                              duration: 300
+                          },
+                          hide: {
+                              effect: "fade",
+                              duration: 300
+                          },
+                          buttons: {
+                              Aceptar: function() {
+                                  $(this).dialog('close');
+                              }
+                          }
+                      });
+                  }
+              }
+          },
+
+          drawPDF: function (getColumns,rows) {
+              var self = this;
+              var rowsPdf=[];
+              var sucusal = this.sucDescrip = this.$el.find('#current-journal option:selected').text();
+              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: {
+                                number: {columnWidth: 23},
+                                date_create :{columnWidth: 17},
+                                partner_name:{columnWidth: 20},
+                                ean13:{columnWidth: 12},
+                                product_name :{columnWidth: 45},
+                                category_name : {columnWidth: 33},
+                                quantity :{halign:'right',columnWidth: 8},
+                                price_unity : {halign:'right',columnWidth: 18},
+                                standar_price : {halign:'right',columnWidth: 18},
+                                price_tot : {halign:'right' ,columnWidth: 18},
+                                standar_tot : {halign:'right' ,columnWidth: 19},
+                                utility : {halign:'right',columnWidth: 17},
+                                user_name : {columnWidth: 15},
+                            },
+                  margin: { top: 16, horizontal: 7},
+                  addPageContent: function (data) {
+                      pdfDoc.setFontSize(12);
+                      pdfDoc.setFontStyle('bold');
+                      pdfDoc.setTextColor(40);
+                      pdfDoc.text('Análisis de facturas de venta ', 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 facturas de venta.pdf')
+          },
+      });
+  }

+ 131 - 0
static/src/reports/report_saledecorart_utility_analytic.xml

@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<template xml:space="preserve">
+    <t t-name="ReportSaleDecorartUtilityAnalytic">
+        <div class="report_view">
+      <div class="reporting_page_header">
+        <h1>Análisis de utilidad por línea de ventas</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="current-store">Sucursal: </label>
+                                <select id="current-store" class="form-control ui-autocomplete-input" name="store"></select>
+                            </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">
+                                <label>Atributo</label>
+                                <select id="current-attribute" class="form-control form-control-sm">
+                                </select>
+                            </div>
+                            <div class="form-group">
+                                <label>Valor del Atributo</label>
+                                <select id="current-attribute-value" class="form-control form-control-sm">
+                                </select>
+                            </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="number" data-sortable="true">Factura</th>
+            <th data-field="date_create">Fecha</th>
+            <th data-field="partner_name" data-sortable="true">Cliente</th>
+            <th data-field="ean13" data-sortable="true">Cod. Barra</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="standar_price" data-sortable="true" data-align="right">Precio Costo</th>
+            <th data-field="price_tot" data-sortable="true" data-align="right">Total Venta</th>
+            <th data-field="standar_tot" data-sortable="true" data-align="right">Total Costo</th>
+            <th data-field="utility" data-sortable="true"  data-align="right">Utilidad</th>
+            <th data-field="user_name" data-sortable="true">Vendedor</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_decorart_assets" inherit_id="eiru_assets.assets">
+      <xpath expr="." position="inside">
+        <link rel="stylesheet" href="/eiru_reports_decorart/static/src/css/custom.css"/>
+
+        <!-- configuration < main > -->
+        <script type="text/javascript" src="/eiru_reports_decorart/static/src/js/main.js"/>
+        <script type="text/javascript" src="/eiru_reports_decorart/static/src/js/reporting_base.js"/>
+
+
+        <!--============================= Analisis de presupuestos ==============================-->
+        <script type="text/javascript" src="/eiru_reports_decorart/static/src/js/reports/report_saledecorart_utility_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="saledecorart_analytic_action" model="ir.actions.client">
+			 <field name="name">Análisis de Utilidad por Línea de Venta</field>
+			 <field name="tag">eiru_reports_decorart.saledecorart_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="saledecorart_analytic_menu" parent="eiru_reports.sale_parent_menu" name="Análisis de Utilidad por Línea de Ventas" action="saledecorart_analytic_action" sequence="3"/>
+
+
+  </data>
+</openerp>