Browse Source

[ADD] ventas por ciudad

Rodney Elpidio Enciso Arias 6 years ago
parent
commit
6247d250b3

+ 77 - 0
models.py

@@ -16,6 +16,11 @@ class ResPartner(models.Model):
 				'ruc': partner.ruc,
 				'street': partner.street,
 				'city': partner.city,
+				'state_id': {
+					'id':partner.state_id.id,
+					'name':partner.state_id.name,
+					'complete_name':partner.state_id.complete_name,
+				},
 				'phone': partner.phone,
 				'mobile': partner.mobile,
 				'email': partner.email,
@@ -32,3 +37,75 @@ class ResPartner(models.Model):
 			})
 
 		return values
+
+
+class AccountInvoice(models.Model):
+	_inherit = 'account.invoice'
+
+	@api.model
+	def getAccountInvoiceOdontoimagen(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,
+				'number': invoice.number,
+				'date_invoice': invoice.date_invoice,
+				'journal_id':{
+					'id': invoice.journal_id.id,
+					'name': invoice.journal_id.name,
+				},
+				'partner_id':{
+					'id':invoice.partner_id.id,
+					'name':invoice.partner_id.name,
+					'ruc':invoice.partner_id.ruc,
+				},
+				'amount_currency': round(invoice.amount_total * (invoice.company_id.currency_id.rate / invoice.currency_id.rate),decimal_precision),
+			})
+
+		return values
+
+	@api.model
+	def getPosOrderOdontoimagen(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,
+				'number': order.name,
+				'date_order': order.date_order,
+				'sale_journal':{
+					'id': order.sale_journal.id,
+					'name': order.sale_journal.name,
+				},
+				'partner_id':{
+					'id': order.partner_id.id,
+					'name': order.partner_id.name,
+					'ruc': order.partner_id.ruc,
+				},
+				'amount_currency': round(order.amount_total * (order.company_id.currency_id.rate / order.pricelist_id.currency_id.rate),decimal_precision),
+			})
+
+		return values
+
+class ResCountryState(models.Model):
+	_inherit = 'res.country.state'
+
+	@api.model
+	def getResCountryState(self,domain):
+		ResCountryState = self.env['res.country.state'].search(domain)
+		values = []
+		for state in ResCountryState:
+			values.append({
+				'id': state.id,
+				'name': state.name,
+				'complete_name':state.complete_name,
+				'parent_id':{
+					'id': state.parent_id.id,
+					'name': state.parent_id.name,
+				},
+			})
+
+		return values

BIN
models.pyc


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

@@ -7,9 +7,11 @@ openerp.eiru_reports_odontoimagen = function (instance) {
 
     try {
         report_doctor_ranking(reporting);
+        report_sale_by_city(reporting);
     } catch (e) {
         // ignorar error
     }
 
     instance.web.client_actions.add('eiru_reports_odontoimagen.doctor_ranking_action', 'instance.eiru_reports_odontoimagen.ReportDoctorRankingWidget');
+    instance.web.client_actions.add('eiru_reports_odontoimagen.sale_by_city_action', 'instance.eiru_reports_odontoimagen.ReportSaleByCityWidget');
 }

+ 920 - 0
static/src/js/reports/report_sale_by_city.js

@@ -0,0 +1,920 @@
+function report_sale_by_city(reporting){
+    "use strict";
+
+    var model = openerp;
+
+    reporting.ReportSaleByCityWidget = reporting.Base.extend({
+        template: 'ReportSaleByCity',
+        rowsData : [],
+        content : [],
+        Order: '',
+        modules: ['point_of_sale'],
+
+        events:{
+            'click #toolbar > button' : 'clickOnAction',
+            'click #generate' : 'fetchGenerate',
+            'change #current-company' : 'updateSelections',
+            'change #current-attribute' : 'updateAttributeSelections',
+            'change #current-store' : 'updateJournalSelections',
+            'change #current-date' : 'ShowDateRange',
+            'change #current-period' : 'updatePeriodSelections',
+        },
+
+        init : function(parent){
+            this._super(parent);
+        },
+
+        start: function () {
+            var self = this;
+            var table = this.$el.find('#xtable');
+            table.bootstrapTable({
+                data : self.rowsData,
+                onExpandRow: function (index, row, $detail) {
+                    self.expandTable($detail,row.id);
+                }
+            });
+            var date = new model.eiru_reports.ReportDatePickerWidget(self);
+            date.fecthFecha();
+            this.fetchInitial();
+        },
+
+        valorNull:function(dato){
+            var valor = "";
+            if (dato){
+                valor = dato;
+            }
+            return valor;
+        },
+
+        checkModel : function(model){
+            var self = this;
+            return _.filter(self.IrModuleModule,function(item){
+                return item.name === model
+            });
+        },
+
+        ShowDateRange : function(){
+            var self = this;
+            var date = self.$el.find('#current-date').val();
+            if(date == 'range'){
+                self.$el.find('.datepicker').css('display','block');
+            }
+            if(date != 'range'){
+                self.$el.find('.datepicker').css('display','none');
+            }
+
+        },
+
+        fetchInitial: function () {
+            var self = this;
+            self.fecthIrModuleModule().then(function (IrModuleModule) {
+                return IrModuleModule;
+            }).then(function(IrModuleModule) {
+                self.IrModuleModule = IrModuleModule;
+                return self.fetchResUser();
+            }).then(function (ResUser) {
+                self.ResUser = ResUser;
+                self.fecthCheckType();
+                return self.fetchResCompany();
+            }).then(function(ResCompany){
+                self.ResCompany = ResCompany;
+                if(ResCompany.length > 1){
+                    self.$el.find('#current-company').append('<option value="9999999">Todas las empresas</option>');
+                    _.each(ResCompany,function(item){
+                        self.$el.find('#current-company').append('<option value="' + item.id + '">' + item.name + '</option>');
+                    });
+                }else{
+                    self.$el.find('.company').css('display','none');
+                }
+                return self.fetchResStore();
+            }).then(function(ResStore){
+                self.ResStore = ResStore;
+                if(ResStore.length > 1){
+                    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>');
+                    });
+                }else{
+                    self.$el.find('.store').css('display','none');
+                }
+                return self.fetchAccountJournal();
+            }).then(function(AccountJournal){
+                self.AccountJournal = AccountJournal;
+                if(AccountJournal.length > 1){
+                    self.$el.find('#current-journal').append('<option value="9999999">Todas las facturas</option>');
+                    _.each(AccountJournal,function(item){
+                        self.$el.find('#current-journal').append('<option value="' + item.id + '">' + item.name + '</option>');
+                    });
+                }else{
+                    self.$el.find('.journal').css('display','none');
+                }
+                return self.fetchAccountPeriod();
+            }).then(function(AccountPeriod){
+                self.AccountPeriod = AccountPeriod;
+                self.$el.find('#current-period').append('<option value="9999999">Todas los periodos</option>');
+                _.each(AccountPeriod,function(item){
+                    self.$el.find('#current-period').append('<option value="' +  item.id + '">' + item.name + '</option>');
+                });
+                return self.fetchResCurrency();
+            }).then(function(ResCurrency){
+                self.ResCurrency = ResCurrency;
+            });
+            self.$el.find('#generate').css('display','inline');
+            return;
+        },
+
+        fetchGenerate: function () {
+            var self = this;
+            self.$el.find('.search-form').block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+            self.$el.find('.report-form').block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+
+            this.fetchAccountInvoice().then(function(AccountInvoice) {
+                return AccountInvoice;
+            }).then(function (AccountInvoice) {
+                self.AccountInvoice = AccountInvoice;
+                return self.fetchPosOrder();
+            }).then(function (PosOrder){
+                self.PosOrder = PosOrder;
+                return self.fetchResPartner();
+            }).then(function (ResPartner){
+                self.ResPartner = ResPartner;
+                return self.fetchResCountryState();
+            }).then(function (ResCountryState){
+                self.ResCountryState = ResCountryState;
+                return self.BuildTable();
+            });
+        },
+
+        /*=====================================================================
+            IR MODULE
+        =====================================================================*/
+        fecthIrModuleModule: function(){
+            var self = this;
+            var defer = $.Deferred();
+            var fields = ['name','id'];
+            var domain=[['state','=','installed'],['name','in',self.modules]];
+            var IrModuleModule = new model.web.Model('ir.module.module');
+            IrModuleModule.query(fields).filter(domain).all().then(function(results){
+                defer.resolve(results);
+            })
+            return defer;
+        },
+
+        /*=====================================================================
+            Check type
+        =====================================================================*/
+        fecthCheckType: function(){
+            var self = this;
+            var modules = self.checkModel('point_of_sale');
+            if(modules.length == 0){
+                self.$el.find('.type').css('display','none');
+            }
+        },
+
+        /*=====================================================================
+            USER
+        =====================================================================*/
+        fetchResUser: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var fields = ['id','name','store_id'];
+            var domain = [['id','=',self.session.uid]];
+            var ResUser = new model.web.Model('res.users');
+            ResUser.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+            return defer;
+        },
+
+        /*====================================================================
+            RES COMPANY
+        ====================================================================*/
+        fetchResCompany: function(){
+            var self = this;
+            var defer = $.Deferred();
+            var currency = new model.web.Model('res.company');
+            var field=['id','name','currency_id','logo'];
+            currency.query(field).filter().all().then(function(results){
+                defer.resolve(results);
+            });
+            return defer;
+        },
+
+        /*====================================================================
+            RES STORE
+        ====================================================================*/
+        fetchResStore: function(){
+            var self = this;
+            var defer = $.Deferred();
+            var field = ['id','name','company_id'];
+            var ResStore = new model.web.Model('res.store');
+            ResStore.query(field).all().then(function(results){
+                defer.resolve(results);
+            });
+            return defer;
+        },
+
+        /*====================================================================
+            ACCOUNT JOURNAL
+        ====================================================================*/
+        fetchAccountJournal: function(){
+            var self = this;
+            var domain = [['active','=',true],['type','=','sale']];
+            var AccountJournal = new model.web.Model('account.journal');
+            return AccountJournal.call('getAccountJournal',[domain], {
+                context: new model.web.CompoundContext()
+            });
+        },
+
+        /*=====================================================================
+            ACCOUNT PERIOD
+        =====================================================================*/
+        fetchAccountPeriod: function () {
+            var self = this;
+            var defer = $.Deferred();
+            var domain = [['special','=',false]];
+            var field =['id', 'name', 'date_start','date_stop','company_id'];
+            var AccountPeriod = new model.web.Model('account.period');
+            AccountPeriod.query(field).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+            return defer;
+        },
+
+        /*====================================================================
+            RES CURRENCY
+        ====================================================================*/
+        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;
+        },
+
+        /*====================================================================
+            ACCOUNT INVOICE
+        ====================================================================*/
+        fetchAccountInvoice: function () {
+            var self = this;
+            var store = self.$el.find('#current-store').val();
+            var period = self.$el.find('#current-period').val();
+            var company = self.$el.find('#current-company').val();
+            var journal = self.$el.find('#current-journal').val();
+            var date = self.$el.find('#current-date').val();
+            var desde = self.$el.find('#from').val();
+            var hasta = self.$el.find('#to').val();
+
+            if(store && store != 9999999){
+                var journal_ids = _.map(_.filter(self.AccountJournal,function (item) {
+                    return item.store_ids == store;
+                }), function(map){
+                    return map.id;
+                });
+            }else{
+                var journal_ids = _.flatten(_.map(self.AccountJournal, function (item) {
+                    return item.id;
+                }));
+            }
+
+            var domain = [
+                ['state', 'in',['open','paid']],
+                ['type', '=', 'out_invoice'],
+                ['journal_id','in',journal_ids],
+            ];
+
+            if(company && company != 9999999){
+                domain.push(['company_id','=',parseInt(company)]);
+            }
+
+            if(journal && journal != 9999999){
+                domain.push(['journal_id','=',parseInt(journal)]);
+            }
+
+            if(period && period != 9999999){
+                domain.push(['period_id','=',parseInt(period)]);
+            }
+
+            if(date && date != 9999999){
+
+                if(desde){
+                    var date = desde.split('/')
+                    date = (date[2]+"-"+date[1]+"-"+date[0]);
+                    domain.push(['date_invoice','>=',date]);
+                }
+
+                if(hasta){
+                    var date = hasta.split('/')
+                    date = (date[2]+"-"+date[1]+"-"+date[0]);
+                    domain.push(['date_invoice','<=',date]);
+                }
+
+                if(date == 'today'){
+                    var today = moment().format('YYYY-MM-DD');
+                    domain.push(['date_invoice','=',today]);
+                }
+
+                if(date == 'yesterday'){
+                    var yesterday = moment().add(-1,'days').format('YYYY-MM-DD');
+                    domain.push(['date_invoice','=',yesterday]);
+                }
+
+                if(date == 'currentMonth'){
+                    var currentMonth = moment().format('YYYY-MM');
+                    domain.push(['date_invoice','like',currentMonth]);
+                }
+
+                if(date == 'lastMonth'){
+                    var lastMonth = moment().add(-1,'months').format('YYYY-MM');
+                    domain.push(['date_invoice','like',lastMonth]);
+                }
+            }
+
+            var AccountInvoice = new model.web.Model('account.invoice');
+            return AccountInvoice.call('getAccountInvoiceOdontoimagen',[domain], {
+                context: new model.web.CompoundContext()
+            });
+        },
+
+        /*====================================================================
+            POS ORDER
+        ====================================================================*/
+        /*
+            TO DO
+            **************************************************
+            Mejorar los filtros de fechas en el modelo POS ORDER - Actualmente
+            es necesario filtrar al momento de hacer la consulta para reducir
+            la carga de la consulta y la segunda vez que se filtra es para
+            analizar los datos con la zona horaria.
+        */
+        fetchPosOrder: function () {
+            var self = this;
+            var type = $('#current-type').val();
+            var modules = self.checkModel('point_of_sale');
+            if (type && modules.length > 0){
+                if(type != 'sale'){
+                    var store = self.$el.find('#current-store').val();
+                    var company = self.$el.find('#current-company').val();
+                    var journal = self.$el.find('#current-journal').val();
+                    var date = self.$el.find('#current-date').val();
+                    var desde = self.$el.find('#from').val();
+                    var hasta = self.$el.find('#to').val();
+
+                    if(store && store != 9999999){
+                        var journal_ids = _.map(_.filter(self.AccountJournal,function (item) {
+                            return item.store_ids == store;
+                        }), function(map){
+                            return map.id;
+                        });
+                    }else{
+                        var journal_ids = _.flatten(_.map(self.AccountJournal, function (item) {
+                            return item.id;
+                        }));
+                    }
+
+                    var domain = [
+                        ['state', 'not in',['draft','cancel']],
+                        ['sale_journal','in',journal_ids],
+                    ];
+
+                    if(company && company != 9999999){
+                        domain.push(['company_id','=',parseInt(company)]);
+                    }
+
+                    if(journal && journal != 9999999){
+                        domain.push(['sale_journal','=',parseInt(journal)]);
+                    }
+
+                    if(date && date != 9999999){
+
+                        if(desde){
+                            var date = desde.split('/')
+                            date = (date[2]+"-"+date[1]+"-"+date[0]);
+                            domain.push(['date_order','>=',date]);
+                        }
+
+                        if(hasta){
+                            var date = hasta.split('/')
+                            date = (date[2]+"-"+date[1]+"-"+date[0]);
+                            domain.push(['date_order','<=',date]);
+                        }
+
+                        if(date == 'today'){
+                            var today = moment().format('YYYY-MM-DD 00:00:00');
+                            domain.push(['date_order','>=',today]);
+                        }
+
+                        if(date == 'yesterday'){
+                            var yesterday = moment().add(-1,'days').format('YYYY-MM-DD 00:00:00');
+                            domain.push(['date_order','>=',yesterday]);
+                        }
+
+                        if(date == 'currentMonth'){
+                            var currentMonth = moment().format('YYYY-MM');
+                            domain.push(['date_order','like',currentMonth]);
+                        }
+
+                        if(date == 'lastMonth'){
+                            var lastMonth = moment().add(-1,'months').format('YYYY-MM');
+                            domain.push(['date_order','like',lastMonth]);
+                        }
+                    }
+                    var PosOrder = new model.web.Model('account.invoice');
+                    return PosOrder.call('getPosOrderOdontoimagen',[domain], {
+                        context: new model.web.CompoundContext()
+                    });
+                }
+            }else{
+                var PosOrder = [];
+                return PosOrder;
+            }
+        },
+
+        /*====================================================================
+            RES PARTNER
+        ====================================================================*/
+        fetchResPartner: function(){
+            var self = this;
+            self.Order = self.getPosOrder();
+            var invoice_partner_ids = _.flatten(_.map(self.AccountInvoice, function (item) {
+                return item.partner_id.id;
+            }));
+            var pos_partner_ids = _.flatten(_.map(self.Order, function (item) {
+                return item.partner_id.id;
+            }));
+            var ids = _.union(invoice_partner_ids,pos_partner_ids);
+            var domain = [
+                ['id','in',ids],
+            ];
+            var ResPartner = new model.web.Model('res.partner');
+            return ResPartner.call('getResPartnerMedic',[domain], {
+                context: new model.web.CompoundContext()
+            });
+        },
+
+        fetchResCountryState: function(){
+            var self = this;
+            var domain = [];
+            var ResCountryState = new model.web.Model('res.country.state');
+            return ResCountryState.call('getResCountryState',[domain], {
+                context: new model.web.CompoundContext()
+            });
+        },
+
+        /*====================================================================
+            UPDATE SELECTIONS
+        ====================================================================*/
+        updateSelections: function () {
+            var self = this;
+            var company = self.$el.find('#current-company').val();
+            if(company != 9999999){
+                /*===================
+                    STORE SELECTION
+                ===================*/
+                var store = self.$el.find('#current-store').empty();
+                self.$el.find('#current-store').append('<option value="9999999">Todas las sucursales</option>');
+                _.each(self.ResStore,function(item){
+                    if(parseFloat(company) == item.company_id[0]){
+                        self.$el.find('#current-store').append('<option value="' + item.id + '">' + item.name + '</option>');
+                    }
+                });
+                /*====================
+                    PERIOD SELECTION
+                ====================*/
+                var period = self.$el.find('#current-period').empty();
+                self.$el.find('#current-period').append('<option value="9999999">Todos los periodos</option>');
+                _.each(self.AccountPeriod,function(item){
+                    if(parseFloat(company) == item.company_id[0]){
+                        self.$el.find('#current-period').append('<option value="' + item.id + '">' + item.name + '</option>');
+                    }
+                });
+            }else{
+                /*===================
+                    STORE SELECTION
+                ===================*/
+                var store = self.$el.find('#current-store').empty();
+                self.$el.find('#current-store').append('<option value="9999999">Todas las sucursales</option>');
+                _.each(self.ResStore,function(item){
+                    self.$el.find('#current-store').append('<option value="' + item.id + '">' + item.name + '</option>');
+                });
+                /*====================
+                    PERIOD SELECTION
+                ====================*/
+                var period = self.$el.find('#current-period').empty();
+                self.$el.find('#current-period').append('<option value="9999999">Todas los periodos</option>');
+                _.each(self.AccountPeriod,function(item){
+                    self.$el.find('#current-period').append('<option value="' + item.id + '">' + item.name + '</option>');
+                });
+            }
+        },
+
+        updateJournalSelections: function () {
+            var self = this;
+            var store = self.$el.find('#current-store').val();
+            if(store != 9999999){
+                /*=============================
+                    ACCOUNT JOURNAL SELECTION
+                =============================*/
+                var journal = self.$el.find('#current-journal').empty();
+                self.$el.find('#current-journal').append('<option value="9999999">Todas las facturas</option>');
+                _.each(self.AccountJournal,function(item){
+                    if(parseFloat(store) == item.store_ids){
+                        self.$el.find('#current-journal').append('<option value="' + item.id + '">' + item.name + '</option>');
+                    }
+                });
+            }else{
+                /*=============================
+                    ACCOUNT JOURNAL SELECTION
+                =============================*/
+                var journal = self.$el.find('#current-journal').empty();
+                self.$el.find('#current-journal').append('<option value="9999999">Todas las facturas</option>');
+                _.each(self.AccountJournal,function(item){
+                    self.$el.find('#current-journal').append('<option value="' + item.id + '">' + item.name + '</option>');
+                });
+            }
+        },
+
+        updatePeriodSelections: function () {
+            var self = this;
+            var period = self.$el.find('#current-period').val();
+            if(period != 9999999){
+                self.$el.find('#current-date').val(9999999);
+                self.$el.find('#current-date').prop('disabled','disabled');
+                self.$el.find('.datepicker').css('display','none');
+            }else{
+                self.$el.find('#current-date').prop('disabled',false);
+            }
+        },
+
+        getResCompany: function (id) {
+            var self = this;
+            return _.filter(self.ResCompany,function (item) {
+                return item.id == id;
+            })
+        },
+
+        getResCurrency: function (id) {
+            var self = this;
+            return _.filter(self.ResCurrency,function (item) {
+                return item.id === id;
+            })
+        },
+
+        getPosOrder: function () {
+            var self = this;
+            var content = self.PosOrder;
+            var period = self.$el.find('#current-period').val();
+            var date = self.$el.find('#current-date').val();
+            var desde = self.$el.find('#from').val();
+            var hasta = self.$el.find('#to').val();
+            /*
+            =================================================
+                FILTRAR PERIODO
+            =================================================
+            */
+            if(period && period != 9999999){
+                var periodo = _.flatten(_.filter(self.AccountPeriod,function (item) {
+                    return item.id == period;
+                }));
+                content = _.flatten(_.filter(content,function (item) {
+                    var utc = moment.utc(item.date_order,'YYYY-MM-DD h:mm:ss A');
+                    return moment(utc._d).format('YYYY-MM') === moment(periodo[0].date_start).format('YYYY-MM');
+                }));
+            }
+            /*
+            =================================================
+                FILTRAR POR FECHAS
+            =================================================
+            */
+            if(date && date != 9999999){
+
+                if(desde){
+                    var date = desde.split('/')
+                    date = (date[2]+"-"+date[1]+"-"+date[0]);
+                    content = _.flatten(_.filter(content,function (item) {
+                        var utc = moment.utc(item.date_order,'YYYY-MM-DD h:mm:ss A');
+                        return moment(utc._d).format('YYYY-MM-DD') >= date;
+                    }));
+                }
+
+                if(hasta){
+                    var date = hasta.split('/')
+                    date = (date[2]+"-"+date[1]+"-"+date[0]);
+                    content = _.flatten(_.filter(content,function (item) {
+                        var utc = moment.utc(item.date_order,'YYYY-MM-DD h:mm:ss A');
+                        return moment(utc._d).format('YYYY-MM-DD') <= date;
+                    }));
+                }
+
+                if(date == 'today'){
+                    var today = moment().format('YYYY-MM-DD');
+                    content = _.flatten(_.filter(content,function (item) {
+                        var utc = moment.utc(item.date_order,'YYYY-MM-DD h:mm:ss A');
+                        return moment(utc._d).format('YYYY-MM-DD') == today;
+                    }));
+                }
+
+                if(date == 'yesterday'){
+                    var yesterday = moment().add(-1,'days').format('YYYY-MM-DD');
+                    content = _.flatten(_.filter(content,function (item) {
+                        var utc = moment.utc(item.date_order,'YYYY-MM-DD h:mm:ss A');
+                        return moment(utc._d).format('YYYY-MM-DD') == yesterday;
+                    }));
+                }
+
+                if(date == 'currentMonth'){
+                    var currentMonth = moment().format('YYYY-MM');
+                    content = _.flatten(_.filter(content,function (item) {
+                        var utc = moment.utc(item.date_order,'YYYY-MM-DD h:mm:ss A');
+                        return moment(utc._d).format('YYYY-MM') == currentMonth;
+                    }));
+                }
+
+                if(date == 'lastMonth'){
+                    var lastMonth = moment().add(-1,'months').format('YYYY-MM');
+                    content = _.flatten(_.filter(content,function (item) {
+                        var utc = moment.utc(item.date_order,'YYYY-MM-DD h:mm:ss A');
+                        return moment(utc._d).format('YYYY-MM') == lastMonth;
+                    }));
+
+                }
+            }
+
+            return content;
+        },
+
+        getInvoiceDetails: function (id) {
+            var self = this;
+            return _.flatten(_.filter(self.AccountInvoice,function (item) {
+                return _.contains(id, item.partner_id.id);
+            }));
+        },
+
+        getPosDetails: function (id) {
+            var self = this;
+            return _.flatten(_.filter(self.Order,function (item) {
+                return _.contains(id, item.partner_id.id);
+            }));
+        },
+
+        getPartnerQty: function (id) {
+            var self = this;
+            var state_ids = _.map(_.filter(self.ResCountryState,function (item) {
+                return item.id == id || item.parent_id.id == id;
+            }), function(map){
+                return map.id;
+            });
+            return _.map(_.filter(self.ResPartner,function (item) {
+                return  _.contains(state_ids, item.state_id.id);
+            }), function(map){
+                return map.id;
+            });
+        },
+
+        getAmount: function (ids) {
+            var self = this;
+            var invoice = _.reduce(_.map(self.AccountInvoice,function(item) {
+                if(_.contains(ids, item.partner_id.id)){
+                    return item.amount_currency;
+                }else{
+                    return 0;
+                }
+            }),function(memo, num) {
+                return memo + num;
+            },0);
+            var pos = _.reduce(_.map(self.Order,function(item) {
+                if(_.contains(ids, item.partner_id.id)){
+                    return item.amount_currency;
+                }else{
+                    return 0;
+                }
+            }),function(memo, num){
+                return memo + num;
+            },0);
+            var total = invoice + pos;
+            return total;
+        },
+
+        BuildTable: function(){
+            var self = this;
+            var data = [];
+            var type = $('#current-type').val();
+            var company = $('#current-company').val();
+
+            if(company && company != 9999999){
+                var ResCompany = self.getResCompany(company).shift();
+                var CurrencyBase = self.getResCurrency(ResCompany.currency_id[0]).shift();
+            }else{
+                var CurrencyBase = self.getResCurrency(self.ResCompany[0].currency_id[0]).shift();
+            };
+            _.each(self.ResCountryState,function(item) {
+                if(item.parent_id.id == false){
+                    var partner_ids = self.getPartnerQty(item.id);
+                    var amount = self.getAmount(partner_ids);
+                    data.push({
+                        id: item.id,
+                        name: item.name,
+                        quantity: partner_ids.length,
+                        amount: accounting.formatMoney(amount, '', CurrencyBase.decimal_places, CurrencyBase.thousands_separator, CurrencyBase.decimal_separator),
+                        amount_float: amount,
+                    });
+                };
+            });
+            self.content = data;
+            self.loadTable(data);
+            self.$el.find('.report-form').css('display','block');
+            self.$el.find('.search-form').unblock();
+            self.$el.find('.report-form').unblock();
+        },
+
+        expandTable: function($detail,id) {
+            var self = this;
+            self.BuildSubTable($detail.html('<table data-detail-view = "true" data-classes="table table-condensed"></table>').find('table'),id);
+        },
+
+        BuildSubTable: function($el,id) {
+            var self = this;
+            var columns = [];
+            var data = [];
+            columns.push({
+                field: 'id',
+                title: 'ID',
+                visible: false,
+            });
+            columns.push({
+                field: 'name',
+                title: 'Nombre',
+            });
+            columns.push({
+                field: 'quantity',
+                title: 'Cantidad de clientes',
+                align:'right',
+                with:'15%',
+            });
+            columns.push({
+                field:'amount',
+                title:'Valor',
+                align:'right',
+                with:'15%',
+            });
+            var company = $('#current-company').val();
+            if(company && company != 9999999){
+                var ResCompany = self.getResCompany(company).shift();
+                var CurrencyBase = self.getResCurrency(ResCompany.currency_id[0]).shift();
+            }else{
+                var CurrencyBase = self.getResCurrency(self.ResCompany[0].currency_id[0]).shift();
+            };
+            _.each(self.ResCountryState,function(item) {
+                if(item.parent_id.id == id){
+                    var partner_ids = self.getPartnerQty(item.id);
+                    var amount = self.getAmount(partner_ids);
+                    data.push({
+                        id: item.id,
+                        name: item.name,
+                        quantity: partner_ids.length,
+                        amount: accounting.formatMoney(amount, '', CurrencyBase.decimal_places, CurrencyBase.thousands_separator, CurrencyBase.decimal_separator),
+                    });
+                };
+            });
+            $el.bootstrapTable({
+                columns: columns,
+                data: data,
+                onExpandRow: function (index, row, $detail) {
+                    self.expandSubTable($detail,row.id);
+                }
+            });
+        },
+
+        expandSubTable: function($detail,id) {
+            var self = this;
+            self.BuildSubSubTable($detail.html('<table data-detail-view="true" data-classes="table table-condensed"></table>').find('table'),id);
+        },
+
+        BuildSubSubTable: function($el,id) {
+            var self = this;
+            var columns = [];
+            var data = [];
+            columns.push({
+                field: 'id',
+                title: 'ID',
+                visible: false,
+            });
+            columns.push({
+                field: 'ruc',
+                title: 'RUC',
+                with:'15%',
+            });
+            columns.push({
+                field: 'name',
+                title: 'Nombre',
+            });
+            columns.push({
+                field: 'amount',
+                title: 'Valor',
+                align:'right',
+                with:'15%',
+            });
+            var company = $('#current-company').val();
+            if(company && company != 9999999){
+                var ResCompany = self.getResCompany(company).shift();
+                var CurrencyBase = self.getResCurrency(ResCompany.currency_id[0]).shift();
+            }else{
+                var CurrencyBase = self.getResCurrency(self.ResCompany[0].currency_id[0]).shift();
+            };
+            _.each(self.ResPartner,function(item) {
+                if(item.state_id.id == id){
+                    var amount = self.getAmount([item.id]);
+                    data.push({
+                        'id': item.id,
+                        'ruc': self.valorNull(item.ruc),
+                        'name': item.name,
+                        'amount': accounting.formatMoney(amount, '', CurrencyBase.decimal_places, CurrencyBase.thousands_separator, CurrencyBase.decimal_separator),
+                    });
+                };
+            });
+            $el.bootstrapTable({
+                columns: columns,
+                data: data,
+                onExpandRow: function (index, row, $detail) {
+                    self.expandSubSubTable($detail,row.id);
+                }
+            });
+        },
+
+        expandSubSubTable: function($detail,id) {
+            var self = this;
+            self.BuildSubSubSubTable($detail.html('<table data-classes="table table-condensed"></table>').find('table'),id);
+        },
+
+        BuildSubSubSubTable: function($el,id) {
+            var self = this;
+            var columns = [];
+            var data = [];
+            columns.push({
+                field: 'date',
+                title: 'Fecha',
+                with:'15%',
+            });
+            columns.push({
+                field: 'number',
+                title: 'Factura',
+            });
+            columns.push({
+                field: 'amount',
+                title: 'Valor',
+                align:'right',
+                with:'15%',
+            });
+            var company = $('#current-company').val();
+            if(company && company != 9999999){
+                var ResCompany = self.getResCompany(company).shift();
+                var CurrencyBase = self.getResCurrency(ResCompany.currency_id[0]).shift();
+            }else{
+                var CurrencyBase = self.getResCurrency(self.ResCompany[0].currency_id[0]).shift();
+            };
+            var invoice = self.getInvoiceDetails([id]);
+            _.each(invoice,function(index) {
+                data.push({
+                    'date': moment(index.date_invoice).format('DD/MM/YYYY'),
+                    'number': index.number,
+                    'amount': accounting.formatMoney(index.amount_currency, '', CurrencyBase.decimal_places, CurrencyBase.thousands_separator, CurrencyBase.decimal_separator),
+                });
+            });
+            var pos = self.getPosDetails([id]);
+            _.each(pos,function(index) {
+                var utc = moment.utc(index.date_order,'YYYY-MM-DD h:mm:ss A');
+                data.push({
+                    'date': moment(utc._d).format('DD/MM/YYYY'),
+                    'number': index.number,
+                    'amount': accounting.formatMoney(index.amount_currency, '', CurrencyBase.decimal_places, CurrencyBase.thousands_separator, CurrencyBase.decimal_separator),
+                });
+            });
+            $el.bootstrapTable({
+                columns: columns,
+                data: data,
+            });
+        },
+
+        loadTable:function(rowsTable){
+            var self = this;
+            self.rowsData = rowsTable;
+            var table = this.$el.find('#xtable');
+            table.bootstrapTable('load', rowsTable);
+        },
+
+    });
+}

+ 120 - 0
static/src/reports/report_sale_by_city.xml

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<template xml:space="preserve">
+    <t t-name="ReportSaleByCity">
+        <div class="report_view">
+            <div class="reporting_page_header">
+                <h1 class="report_title">Ventas por ciudad</h1>
+            </div>
+            <div class="container search-form" style="border-bottom:1px solid #eee; width:95%;">
+                <div class="row">
+                    <div class="col-lg-3 company filter-style">
+                        <label>Empresa</label>
+                        <select id="current-company" class="form-control form-control-sm"></select>
+                    </div>
+                    <div class="col-lg-3 store filter-style">
+                        <label>Sucursal</label>
+                        <select id="current-store" class="form-control form-control-sm">
+                        </select>
+                    </div>
+                    <div class="col-lg-3 journal filter-style">
+                        <label>Factura</label>
+                        <select id="current-journal" class="form-control form-control-sm">
+                        </select>
+                    </div>
+                    <div class="col-lg-3 type filter-style">
+                        <label>Tipo de Venta</label>
+                        <select id="current-type" class="form-control form-control-sm">
+                            <option value="9999999">Todos los Tipos</option>
+                            <option value="tpv">Terminal</option>
+                            <option value="sale">Normal</option>
+                        </select>
+                    </div>
+                    <div class="col-lg-3 filter-style">
+                        <label>Periodo</label>
+                        <select id="current-period" class="form-control form-control-sm">
+                        </select>
+                    </div>
+                    <div class="col-lg-3 filter-style">
+                        <label>Fechas</label>
+                        <select id="current-date" class="form-control form-control-sm">
+                            <option value="9999999">Sin fechas</option>
+                            <option value="today">Hoy</option>
+                            <option value="yesterday">Ayer</option>
+                            <option value="currentMonth">Mes Actual</option>
+                            <option value="lastMonth">Mes Pasado</option>
+                            <option value="range">Busqueda Avanzada</option>
+                        </select>
+                    </div>
+                </div>
+                <div class="row" >
+                    <div class="datepicker" style="display:none;">
+                        <div class="col-lg-3 filter-style col-md-offset-3">
+                            <div class="input-group">
+                                <span class="input-group-addon" id="basic-addon1">Desde</span>
+                                <input type="text" id="from" class="form-control" aria-describedby="basic-addon1"/>
+                            </div>
+                        </div>
+                        <div class="col-lg-3 filter-style">
+                            <div class="input-group">
+                                <span class="input-group-addon" id="basic-addon1">Hasta</span>
+                                <input type="text" id="to" class="form-control" aria-describedby="basic-addon1"/>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="row">
+                    <div class="text-center" style="padding-top:20px;">
+                        <button id="generate" class="myButton" aria-label="Left Align">
+                            Generar
+                        </button>
+                    </div>
+                    <br/>
+                </div>
+            </div>
+
+            <div class="report-form" style="display:none;">
+                <!-- <div id="toolbar">
+                    <button class="oe_button myButton" value="pdf">Imprimir Informe</button>
+                </div> -->
+                <div class="container" style="width:95%;">
+                    <table
+                        id = "xtable"
+                        data-detail-view = "true"
+                        data-classes="table table-condensed table-no-bordered"
+                        data-search="true"
+                        data-search-on-enter-key="true"
+                        data-toolbar="#toolbar"
+                        data-buttons-class="oe_button myButton"
+                        data-show-footer="true"
+                        data-footer-style="footerStyle"
+                        >
+                        <thead style="background:none;">
+                        <tr>
+                            <th data-field="id" data-visible="false">ID</th>
+                            <th data-field="name">Name</th>
+                            <th data-field="quantity" data-align="right" data-width="15%">Cantidad de clientes</th>
+                            <th data-field="amount" data-align="right" data-width="15%" data-footer-formatter="AmountFooter">Valor</th>
+                        </tr>
+                        </thead>
+                    </table>
+                </div>
+            </div>
+            <script>
+                function AmountFooter(rowsTable) {
+                    var quantity =  _.reduce(_.map(rowsTable,function(item){
+                        return (item.amount_float);
+                    }), function(memo, num){
+                    return memo + num; },0)
+                    return accounting.formatNumber(quantity,0,'.',',');
+                }
+                function footerStyle(row, index) {
+                    return {
+                        css: {
+                          "font-weight": "bold"
+                        }
+                    };
+                };
+            </script>
+        </div>
+    </t>
+</template>

+ 1 - 0
templates.xml

@@ -9,6 +9,7 @@
                 <script type="text/javascript" src="/eiru_reports_odontoimagen/static/src/js/reporting_base.js" />
                 <!-- Ranking de Doctores -->
                 <script type="text/javascript" src="/eiru_reports_odontoimagen/static/src/js/reports/report_doctor_ranking.js"/>
+                <script type="text/javascript" src="/eiru_reports_odontoimagen/static/src/js/reports/report_sale_by_city.js"/>
 
             </xpath>
         </template>

+ 5 - 0
views/actions.xml

@@ -7,5 +7,10 @@
             <field name="tag">eiru_reports_odontoimagen.doctor_ranking_action</field>
         </record>
 
+		<record id="sale_by_city_action" model="ir.actions.client">
+            <field name="name">Ventas por ciudad</field>
+            <field name="tag">eiru_reports_odontoimagen.sale_by_city_action</field>
+        </record>
+
     </data>
 </openerp>

+ 6 - 0
views/menus.xml

@@ -13,5 +13,11 @@
             action="doctor_ranking_action"
             sequence="3"/>
 
+        <menuitem id="sale_by_city_menu"
+            parent="welcome_odontoimagen_parent_menu"
+            name="Ventas por ciudad"
+            action="sale_by_city_action"
+            sequence="3"/>
+
     </data>
 </openerp>