Explorar el Código

commit inicial

Rodney Elpidio Enciso Arias hace 7 años
commit
5e19db61ce
Se han modificado 49 ficheros con 4327 adiciones y 0 borrados
  1. 1 0
      __init__.py
  2. BIN
      __init__.pyc
  3. 20 0
      __openerp__.py
  4. 5 0
      controllers/widget_controller.py
  5. BIN
      static/description/icon.png
  6. BIN
      static/img/handshake.png
  7. BIN
      static/img/user.png
  8. 257 0
      static/src/css/configuration.css
  9. 134 0
      static/src/css/dashboard.css
  10. 140 0
      static/src/js/configuration.js
  11. 70 0
      static/src/js/dashboard.js
  12. 38 0
      static/src/js/main.js
  13. 60 0
      static/src/js/widget_base.js
  14. 287 0
      static/src/js/widgets/expired_account_counters.js
  15. 261 0
      static/src/js/widgets/expired_account_counters_now.js
  16. 229 0
      static/src/js/widgets/invoice_history.js
  17. 105 0
      static/src/js/widgets/invoice_today_counters.js
  18. 110 0
      static/src/js/widgets/missing_product.js
  19. 203 0
      static/src/js/widgets/monthly_expenses.js
  20. 204 0
      static/src/js/widgets/monthly_purchases.js
  21. 168 0
      static/src/js/widgets/payments_today_counters.js
  22. 104 0
      static/src/js/widgets/pos_order_today_counters.js
  23. 236 0
      static/src/js/widgets/ranking_pos_orders_partner.js
  24. 265 0
      static/src/js/widgets/ranking_pos_orders_product.js
  25. 237 0
      static/src/js/widgets/ranking_pos_orders_salesman.js
  26. 222 0
      static/src/js/widgets/ranking_sales_partner.js
  27. 276 0
      static/src/js/widgets/ranking_sales_product.js
  28. 168 0
      static/src/js/widgets/voucher_today_counters.js
  29. 29 0
      static/src/lib/jquery.timeago.es.js
  30. 57 0
      static/src/xml/configuration.xml
  31. 9 0
      static/src/xml/dashboard.xml
  32. 11 0
      static/src/xml/widget_base.xml
  33. 60 0
      static/src/xml/widgets/eiru_dashboard_modal.xml
  34. 23 0
      static/src/xml/widgets/expired_account_counters.xml
  35. 23 0
      static/src/xml/widgets/expired_account_counters_now.xml
  36. 19 0
      static/src/xml/widgets/invoice_history.xml
  37. 23 0
      static/src/xml/widgets/invoice_today_counters.xml
  38. 23 0
      static/src/xml/widgets/missing_product.xml
  39. 23 0
      static/src/xml/widgets/monthly_expenses.xml
  40. 23 0
      static/src/xml/widgets/monthly_purchases.xml
  41. 23 0
      static/src/xml/widgets/payments_today_counters.xml
  42. 23 0
      static/src/xml/widgets/pos_order_today_counters.xml
  43. 18 0
      static/src/xml/widgets/ranking_pos_orders_partner.xml
  44. 17 0
      static/src/xml/widgets/ranking_pos_orders_product.xml
  45. 18 0
      static/src/xml/widgets/ranking_pos_orders_salesman.xml
  46. 18 0
      static/src/xml/widgets/ranking_sales_partner.xml
  47. 19 0
      static/src/xml/widgets/ranking_sales_product.xml
  48. 23 0
      static/src/xml/widgets/voucher_today_counters.xml
  49. 45 0
      templates.xml

+ 1 - 0
__init__.py

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

BIN
__init__.pyc


+ 20 - 0
__openerp__.py

@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+{
+    'name': "Eiru Reporting Dashboard",
+    'author': "Eiru",
+    'website': "http://www.yourcompany.com",
+    'category': 'Uncategorized',
+    'version': '0.1',
+    'depends': ['base', 'sale', 'eiru_assets','currency_utility'],
+    'data': [
+        'templates.xml',
+        # 'views/customer.xml',
+        # 'views/products.xml',
+        # 'views/actions.xml',
+        # 'views/menus.xml'
+    ],
+    'qweb': [
+        # 'static/src/xml/*.xml',
+        'static/src/xml/widgets/*.xml'
+    ]
+}

+ 5 - 0
controllers/widget_controller.py

@@ -0,0 +1,5 @@
+class WidgetController(openerp.http.Controller):
+
+    @route('/web/widget/<string:widget_name>', type='json', auth='user')
+    def widget_handler(self):
+        pass

BIN
static/description/icon.png


BIN
static/img/handshake.png


BIN
static/img/user.png


+ 257 - 0
static/src/css/configuration.css

@@ -0,0 +1,257 @@
+/* layout */
+.configuration_container {
+    width: 100%;
+    height: 100%;
+    padding: 16px;
+}
+
+.configuration_dashboard {
+    width: 100%;
+    height: calc(100% - 53px);
+    display: table;
+}
+
+.configuration_dashboard > div {
+    display: table-row;
+}
+
+.configuration_dashboard > div > div {
+    display: table-cell;
+    vertical-align: top;
+    padding: 0;
+    height: 100%;
+}
+
+.configuration_dashboard > div > div:nth-child(1) {
+    width: 150px;
+    background: #f0eeee;
+    border: 1px solid #d3d3d3;
+}
+
+.configuration_dashboard > div > div:nth-last-child(1) {
+    width: 200px;
+    background: #f0eeee;
+    border: 1px solid #d3d3d3;
+}
+
+/* users list */
+.user_selectable_area {
+    width: 100%;
+    height: 100%;
+    overflow-y: auto;
+}
+
+.user_wrapper {
+    width: 120px;
+    height: 120px;
+    margin: 10px auto;
+}
+
+.user_wrapper > .user_photo {
+    width: 85px;
+    height: 85px;
+    border-radius: 50%;
+    background: #a8a4d2;
+    margin: 0 auto;
+    position: relative;
+}
+
+.user_wrapper > .user_photo > img {
+    width: inherit;
+    height: inherit;
+    border-radius: inherit;
+}
+
+.user_wrapper:hover {
+    cursor: pointer;
+}
+
+.user_wrapper:hover > .user_photo {
+    animation: 0.5s photo-bubble 1;
+}
+
+.user_photo:before {
+    content: '';
+    position: absolute;
+    top: 50%;
+    right: 0;
+    margin-top: -15px;
+    border-style: solid;
+    border-width: 15px 0 15px 15px;
+    border-color: transparent transparent transparent #a8a4d2;
+    transition-duration: 0.3s;
+}
+
+.user_wrapper.user_selected > .user_photo:before {
+    right: -12px;
+}
+
+.user_wrapper > h2 {
+    font-size: 12px;
+    text-align: center;
+    margin: 10px 0 0 0;
+    user-select: none;
+}
+
+.user_wrapper > h3 {
+    font-size: 10px;
+    margin: 0;
+
+}
+
+/* widget droppable area */
+.widgets_droppable_area {
+    width: calc(100% - 10px);
+    height: 100%;
+    margin: 0 5px;
+    background: linear-gradient(90deg, #d3d3d3 50%, transparent 50%), linear-gradient(90deg, #d3d3d3 50%, transparent 50%), linear-gradient(0deg, #d3d3d3 50%, transparent 50%), linear-gradient(0deg, #d3d3d3 50%, transparent 50%);
+    background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
+    background-size: 10px 1px, 10px 1px, 1px 10px, 1px 10px;
+    background-position: 0px 0px, 200px 100%, 0px 100px, 100% 0px;
+    padding: 10px;
+}
+
+.widgets_droppable_area > div {
+    width: 100% !important;
+    height: 100% !important;
+    overflow-y: auto;
+}
+
+.widgets_droppable_area.dancing_border {
+    animation: border-dance 4s infinite linear;
+}
+
+.widgets_droppable_area > p {
+    font-size: 16pt;
+    font-weight: bolder;
+    text-align: center;
+    color: #d3d3d3;
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translateX(-50%) translateY(-50%);
+}
+
+/* widgets dragable area */
+.widgets_draggable_area {
+    width: 100%;
+    height: 100%;
+    text-align: center;
+}
+
+.ui-state-disabled {
+    opacity: 1;
+}
+
+.widgets_draggable_area.vertical_scrollable {
+    overflow-y: auto;
+}
+
+.widgets_draggable_area > input {
+    width: 180px;
+    height: 30px !important;
+    margin: 10px auto;
+}
+
+.widget_wrapper {
+    width: 180px;
+    height: 100px;
+    border: 1px solid #d3d3d3;
+    background-color: #fff;
+    box-shadow: 1px 1px 3px #d3d3d3, -1px -1px 3px #d3d3d3;
+    transition-duration: 0.3s;
+}
+
+.widget_wrapper > h2 {
+    text-align: center;
+    font-size: 14pt;
+}
+
+.widget_wrapper > p {
+    text-align: center;
+}
+
+.widget_action {
+    width: 25px;
+    height: 25px;
+    position: absolute;
+    top: 0;
+    right: 0;
+    border-radius: 0 0 0 90%;
+    transition-duration: 0.3s;
+}
+
+.widget_action.widget_add {
+    background: #4caf50;
+}
+
+.widget_action.widget_trash {
+    background: #f44336;
+    display: none;
+}
+
+.widget_action:hover {
+    box-shadow: -2px 2px 4px #d3d3d3;
+    cursor: default;
+    -webkit-cursor: default;
+    -moz-cursor: default;
+}
+
+.widget_action > i {
+    position: absolute;
+    top: 5px;
+    right: 5px;
+    color: #fff;
+}
+
+.widget_action:hover i {
+    animation: 0.5s trash-bell 1;
+}
+
+.widget_wrapper:hover {
+    cursor: pointer;
+    box-shadow: 3px 3px 6px #d3d3d3, -3px -3px 6px #d3d3d3;
+}
+
+.widget_wrapper:active {
+    cursor: move;
+    cursor: -moz-move;
+    cursor: -webkit-move;
+}
+
+/* keyframes */
+@keyframes photo-bubble {
+    30% {
+        transform: scaleX(1.25) scaleY(0.75);
+    }
+    40% {
+        transform: scaleX(0.75) scaleY(1.25);
+    }
+    60% {
+        transform: scaleX(1.15) scaleY(0.85);
+    }
+}
+
+@keyframes border-dance {
+    0% {
+        background-position: 0px 0px, 300px 100%, 0px 150px, 100% 0px;
+    }
+    100% {
+        background-position: 300px 0px, 0px 100%, 0px 0px, 100% 150px;
+    }
+}
+
+@keyframes trash-bell {
+    0% {
+        transform: rotate(30deg);
+    }
+    25% {
+        transform: rotate(-30deg);
+    }
+    50% {
+        transform: rotate(30deg);
+    }
+    75% {
+        transform: rotate(-30deg);
+    }
+}

+ 134 - 0
static/src/css/dashboard.css

@@ -0,0 +1,134 @@
+.container {
+    width: 100%;
+    height: 100%;
+    padding: 30px 20px;
+}
+
+.grid-stack.dashboard {
+    width: 100%;
+    height: 100%;
+}
+
+.grid-stack-item-content.dashboard {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    padding: 1em;
+    border-bottom: 3px solid #7c7bad;
+    background-color: #f0eeee;
+    overflow-y: hidden !important;
+}
+
+.grid-stack-item-content.dashboard:hover {
+    cursor: grab;
+    cursor: -moz-grab;
+    cursor: -webkit-grab;
+    box-shadow: 5px 5px 2px #d3d3d3;
+}
+
+.grid-stack-item-content.dashboard:active {
+    cursor: move;
+    cursor: -moz-move;
+    cursor: -webkit-move;
+    box-shadow: 3px 3px 2px #d3d3d3;
+    transform: translateY(2px);
+}
+
+.grid-stack-item-content.dashboard > .widget-title {
+    font-size: 12pt;
+    font-weight: bold;
+    margin: 0 !important;
+}
+
+.grid-stack-item-content.dashboard > .widget-content {
+    flex-grow: 1;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+.widget-content.widget-loading {
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    color : #000;
+}
+
+.grid-stack-item-content.dashboard > .widget-content > a {
+    font-size: 24pt;
+    font-weight: bold;
+}
+
+.grid-stack-item-content.dashboard > .widget-footer > a {
+    font-size: 12pt;
+}
+
+.grid-stack-item-content.dashboard > .widget-content > a:hover, .widget-footer > a:hover {
+    cursor: pointer;
+}
+
+
+/*.table_paint_first_row > tbody > tr > td:nth-child(1):hover{*/
+.expired-account-modal .table-row-select {
+     background: #d4e2f3  !important;
+}
+
+.expired-account-modal {
+    width: 100%;
+    height: 100%;
+    display: flex;
+}
+
+@media (min-width: 768px) {
+    .expired-account-modal .modal-lg {
+            width: 900px !important;
+    }
+}
+
+.expired-account-modal .table-model{
+    width: 868px;
+    height: 300px;
+    margin: auto;
+    position: relative;
+}
+
+.expired-account-modal table tbody tr td:nth-child(1){
+    display: none;
+}
+
+.expired-account-modal table thead tr th:nth-child(1){
+    display: none;
+}
+
+.expired-account-modal table tbody tr td:nth-child(2){
+    width: 279px;
+}
+
+.expired-account-modal table thead tr th:nth-child(2){
+    width: 270px;
+}
+
+.expired-account-modal table tbody tr td:nth-child(3){
+    width: 279px;
+}
+
+.expired-account-modal table thead tr th:nth-child(3){
+    width: 270px;
+}
+
+.expired-account-modal table tbody tr td:nth-child(4){
+    width: 200px;
+}
+
+.expired-account-modal table tbody tr td:nth-child(5){
+    width: 110px;
+}
+
+.expired-account-modal .modal-head-wrapper{
+    width: 100%;
+}
+
+.expired-account-modal .modal-items-wrapper{
+    width: 100%;
+    height: 80%;
+    overflow-y: auto;
+}

+ 140 - 0
static/src/js/configuration.js

@@ -0,0 +1,140 @@
+function configuration_widget (instance, widget) {
+    "use strict";
+
+    var QWeb = instance.web.qweb;
+
+    widget.DashboardConfigurationWidget = instance.Widget.extend({
+        template: 'ConfigurationTmpl',
+        events: {
+            'click .user_wrapper': 'selectUser',
+            'dragstart .grid-stack': 'onDragWidget',
+            'dragstop .grid-stack': 'onDropWidget',
+            'added .grid-stack': 'onDropWidget',
+            'click .widget_action': 'onClickWidgetAction',
+        },
+        init: function (parent) {
+            this._super(parent);
+        },
+        start: function () {
+            this.renderUsersArea();
+            this.renderWidgetsAsignedArea();
+            this.renderWidgetsArea();
+
+            this.isBorderDancing = false;
+        },
+        getUsers: function () {
+            var User = new instance.web.Model('res.users');
+            var fields = ['name', 'display_name', 'image_medium'];
+            var domain = [['active', '=', true]];
+            return User.query(fields).filter(domain).order_by(['id']).all();
+        },
+        renderUsersArea: function () {
+            var self = this;
+
+            self.getUsers().then(function (users) {
+                this.users = users;
+
+                var usersAreaHtml = QWeb.render('ConfigurationUsersTmpl', { users: users });
+                self.$el.find('.user_selectable_area').html(usersAreaHtml);
+            });
+        },
+        renderWidgetsAsignedArea: function () {
+            this.$el.find('.widgets_droppable_area > div').gridstack({
+                cellHeight: 100,
+                animate: true,
+                acceptWidgets: true,
+                disableResize: true,
+                minWidth: 100,
+                width: 4
+            });
+        },
+        renderWidgetsArea: function () {
+            var widgets = [
+                {
+                    id: "w_01",
+                    name: 'Widget 1',
+                    description: 'Description 1'
+                },
+                {
+                    id: "w_02",
+                    name: 'Widget 2',
+                    description: 'Description 2'
+                },
+                {
+                    id: "w_03",
+                    name: 'Widget 3',
+                    description: 'Description 3'
+                },
+                {
+                    id: "w_04",
+                    name: 'Widget 4',
+                    description: 'Description 4'
+                },
+                {
+                    id: "w_05",
+                    name: 'Widget 5',
+                    description: 'Description 5'
+                }
+            ];
+            var element = this.$el.find('.widgets_draggable_area');
+            var widgetsAreaHtml = QWeb.render('ConfigurationWidgetsTmpl', { widgets: widgets });
+            element.html(widgetsAreaHtml);
+            element.find('.grid-stack').gridstack({
+                cellHeight: 100,
+                animate: true,
+                disableResize: true,
+                width: 1
+            });
+        },
+        selectUser: function (e) {
+            this.$el.find('.user_wrapper').removeClass('user_selected');
+
+            var element = $(e.target).closest('.user_wrapper');
+            element.addClass('user_selected');
+        },
+        borderDance: function (e) {
+            this.isBorderDancing = !this.isBorderDancing;
+
+            if (this.isBorderDancing) {
+                this.$el.find('.widgets_draggable_area').removeClass('vertical_scrollable');
+                this.$el.find('.widgets_droppable_area').addClass('dancing_border');
+            } else {
+                this.$el.find('.widgets_draggable_area').addClass('vertical_scrollable')
+                this.$el.find('.widgets_droppable_area').removeClass('dancing_border');
+            }
+        },
+        onDragWidget: function (e, ui) {
+            this.borderDance(e);
+        },
+        onDropWidget: function (e, ui) {
+            this.borderDance(e);
+
+            if (e.type === 'added') {
+                var el = ui.shift().el;
+                var trash = el.find('.widget_trash');
+                var add = el.find('.widget_add');
+                var display = trash.css('display');
+
+                trash.css('display', add.css('display'));
+                add.css('display', display);
+            }
+        },
+        onClickWidgetAction: function (e) {
+            var gridOrigin = $(e.target).closest('.grid-stack').data('gridstack');
+            var gridDest = null;
+            var el = $(e.target).closest('.grid-stack-item');
+            var action = $(e.target).closest('.widget_action').data('action');
+
+            if (action === 'add') {
+                gridDest = this.$el.find('.widgets_droppable_area > .grid-stack').data('gridstack');
+            } else {
+                gridDest = this.$el.find('.widgets_draggable_area > .grid-stack').data('gridstack');
+            }
+
+            this.borderDance();
+
+            gridOrigin.removeWidget(el);
+            gridDest.addWidget(el);
+        }
+    });
+}

+ 70 - 0
static/src/js/dashboard.js

@@ -0,0 +1,70 @@
+function dashboard_widget (instance, widget) {
+    "use strict";
+
+    var widgets = widget;
+    var InstalledModule = 0;
+    
+
+    widget.DashboardWidget = instance.Widget.extend({
+        template: 'DashboardTmpl',
+        widgets: [
+            {
+                title: 'Clientes',
+                name: 'CustomerCounterWidget'
+            }
+        ],
+
+        grid: {},
+        start: function () {
+            this.$el.find('.grid-stack.dashboard').gridstack({
+                animate: true,
+            });
+            this.grid = this.$el.find('.grid-stack.dashboard').data('gridstack');
+            this.renderWidgets();
+        },
+        renderWidgets: function () { 
+            var self = this; 
+            var wExpiredAccount = new widgets.ExpiredAccountCountersWidget(self);          
+            wExpiredAccount.fecthIrModuleModule().then(function(modules){
+                return modules;
+            }).then(function(modules){
+                if(modules.length == 0){
+                    //Ranking de Ventas de Producto por Mes
+                    var wRankingProduct = new widgets.RankingSalesProductWidget(self);
+                    wRankingProduct.renderElement();
+                    wRankingProduct.start();
+                    self.grid.addWidget(wRankingProduct.$el, 0, 0, wRankingProduct.size.width,  wRankingProduct.size.height, true);
+                    //Ranking de clientes que mas compra
+                    var wRankingPartner = new widgets.RankingSalesPartnerWidget(self);
+                    wRankingPartner.renderElement();
+                    wRankingPartner.start();
+                    self.grid.addWidget(wRankingPartner.$el, 0, 0, wRankingPartner.size.width,  wRankingPartner.size.height, true);
+                }else{
+                    //Invoice History
+                    var wInvoiceHistory = new widgets.InvoiceHistoryWidget(self);
+                    wInvoiceHistory.renderElement();
+                    wInvoiceHistory.start();
+                    self.grid.addWidget(wInvoiceHistory.$el, 0, 0, wInvoiceHistory.size.width,  wInvoiceHistory.size.height, true);
+                    
+                    //Ranking pos orders Salesman
+                    var wRankingPosOrderSalesman = new widgets.RankingPosOrdersSalesmanWidget(self);
+                    wRankingPosOrderSalesman.renderElement();
+                    wRankingPosOrderSalesman.start();
+                    self.grid.addWidget(wRankingPosOrderSalesman.$el, 0, 0, wRankingPosOrderSalesman.size.width,  wRankingPosOrderSalesman.size.height, true);
+
+                    // Ranking de clientes
+                    var wRankingPosOrderPartner = new widgets.RankingPosOrdersPartnerWidget(self);
+                    wRankingPosOrderPartner.renderElement();
+                    wRankingPosOrderPartner.start();
+                    self.grid.addWidget(wRankingPosOrderPartner.$el, 0, 0, wRankingPosOrderPartner.size.width,  wRankingPosOrderPartner.size.height, true);
+                    
+                    //Ranking de Ventas de Producto por Mes - Point Of Sale
+                    var wRankingPosOrderProduct = new widgets.RankingPosOrdersProductWidget(self);
+                    wRankingPosOrderProduct.renderElement();
+                    wRankingPosOrderProduct.start();
+                    self.grid.addWidget(wRankingPosOrderProduct.$el, 0, 0, wRankingPosOrderProduct.size.width,  wRankingPosOrderProduct.size.height, true);                    
+                }
+            }); 
+        }
+    });
+}

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

@@ -0,0 +1,38 @@
+openerp.eiru_reporting_dashboard = function (instance) {
+    "use strict";
+
+    instance.eiru_reporting_dashboard = {};
+    instance.eiru_reporting_dashboard.reports = {};
+
+    var dashboard = instance.eiru_reporting_dashboard;
+
+    widget_base(instance, dashboard);
+    dashboard_widget(instance, dashboard);
+    configuration_widget(instance, dashboard);
+    // Widgets
+    try{
+        expired_account_counters(dashboard);
+        // expired_account_counters_now(dashboard);
+        // voucher_today_counters(dashboard);
+        // invoice_today_counters(dashboard);
+        ranking_sales_product(dashboard);
+        ranking_sales_partner(dashboard);
+        // monthly_expenses(dashboard);
+        // monthly_purchases(dashboard);
+        // missing_product(dashboard); 
+        // payments_today_counters(dashboard);
+        // pos_order_today_counters(dashboard);
+        ranking_pos_orders_partner(dashboard);
+        ranking_pos_orders_product(dashboard);
+        invoice_history(dashboard);
+        ranking_pos_orders_salesman(dashboard);
+    }catch(e){
+        // error
+    }
+    
+
+    // Action
+    instance.web.client_actions.add('eiru_reporting_dashboard.action_dashboard', 'instance.eiru_reporting_dashboard.DashboardWidget');
+    instance.web.client_actions.add('eiru_reporting_dashboard.action_dashboard_sale', 'instance.eiru_reporting_dashboard.SaleWidget');
+    instance.web.client_actions.add('eiru_reporting_dashboard.action_dashboard_configuration', 'instance.eiru_reporting_dashboard.DashboardConfigurationWidget');
+}

+ 60 - 0
static/src/js/widget_base.js

@@ -0,0 +1,60 @@
+function widget_base (instance, widget) {
+    "use strict";
+
+    widget.Base = instance.Widget.extend({
+        size: {
+            width: 0,
+            height: 0
+        },
+        position: {
+            x: 0,
+            y: 0
+        },
+        init: function (parent, size, position) {
+            this._super(parent);
+            this.size = size || this.size;
+            this.position = position || this.position;
+        },
+        start: function () {
+            console.log('Widget started');
+        },
+        getSize: function () {
+            return this.size;
+        },
+        getWidth: function () {
+            return this.getSize().width;
+        },
+        getHeight: function () {
+            return this.getSize().height;
+        },
+        getPosition: function () {
+            return this.position;
+        },
+        getPositionX: function () {
+            return this.getPosition().x;
+        },
+        getPositionY: function () {
+            return this.getPosition().y;
+        },
+        setSize: function (width, height) {
+            this.size.width = width;
+            this.size.height = height;
+        },
+        setWidth: function (width) {
+            this.size.width = width;
+        },
+        setHeight: function (height) {
+            this.size.height = height;
+        },
+        setPosition: function (x, y) {
+            this.position.x = x;
+            this.position.y = y;
+        },
+        setPositionX: function (x) {
+            this.position.x = x;
+        },
+        setPositionY: function (y) {
+            this.position.y = y;
+        }
+    });
+}

+ 287 - 0
static/src/js/widgets/expired_account_counters.js

@@ -0,0 +1,287 @@
+function expired_account_counters (widget) {
+    "use strict";
+
+    var model = openerp;
+    var Qweb = openerp.web.qweb;
+
+    widget.ExpiredAccountCountersWidget = widget.Base.extend({
+        template: 'ExpiredAccountCounters',
+        moveLine: [],
+        resCompany: [],
+        resCurrecy: [],
+        modelId: [],
+        accountInvoice: [],
+        module_list: ['point_of_sale'],
+        newModule: [],
+
+        events: {
+            'click a': 'showCustomers',
+            'click h2': 'showCustomers',
+        },
+
+        init: function (parent) {
+            var self = this;
+            this._super(parent, {
+                width: 3,
+                height: 2,
+            });
+        },
+
+        start: function () {
+            var self = this;
+            self.fetchInitial();
+        },
+
+        // Consulta Inicial
+        fetchInitial: function() {
+            var self = this;
+            self.$el.find('.grid-stack-item-content dashboard').block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+
+            self.$el.find('.widget-content.widget-loading').css('display','flex');
+            self.fecthIrModuleModule().then(function(modules){
+                self.modules = modules;
+                return modules;
+            }).then(function(modules){
+                return self.fetchMoveLine()
+            }).then(function (moveLine) {
+                return moveLine;
+            }).then(function (moveLine) {
+                self.moveLine = _.filter(moveLine, function(item) {
+                    return item.amount_residual > 0;
+                });
+                return self.fetchInvoice(moveLine);
+            }).then(function(accountInvoice) {
+                self.accountInvoice = accountInvoice;
+                return self.fetchResCompany();
+            }).then(function (resCompany) {
+                self.resCompany = resCompany;
+                return self.fetchResCurrecy();
+            }).then(function (resCurrecy) {
+                self.resCurrecy = resCurrecy;
+                return self.fetchGetModelId();
+            }).then(function(modelId) {
+                self.modelId= modelId;
+                return self.fetchReduceMoveLine();
+            });
+        },        
+
+        // Verificar Modelos Instalados
+        fecthIrModuleModule: function(){
+            var self = this;
+            var defer = $.Deferred();
+            var fields = ['name','id'];
+            var domain=[['state','=','installed'],['name','in',self.module_list]];
+            var irModule = new model.web.Model('ir.module.module');
+            irModule.query(fields).filter(domain).all().then(function(results){
+                defer.resolve(results);
+            })                       
+            return defer;
+        },
+
+        // getModelId
+        fetchGetModelId: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var irModelData = new model.web.Model('ir.model.data');
+            var getObtjectReference = irModelData.get_func('get_object_reference');
+
+            this.alive(getObtjectReference('account', 'invoice_form')).then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Move line
+        fetchMoveLine: function () {
+            var self = this;
+            var hoy = moment().format('YYYY-MM-DD');
+            var defer = $.Deferred();
+            var field = ['id', 'partner_id', 'amount_residual', 'credit', 'debit', 'date_maturity', 'invoice', 'ref', 'invoice', 'amount_residual_currency','state'];
+            var domain = [['credit', '<=', 0], ['date_maturity', '<', hoy]];
+            var moveLine = new model.web.Model('account.move.line');
+
+            moveLine.query(field).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // invoice
+        fetchInvoice: function(moveline) {
+            var self = this ;
+            var defer = $.Deferred()
+            var ref = _.map(moveline, function(map) {
+                return map.invoice[0];
+            });
+            var fields = ['id', 'currency_id', 'number', 'currency_id'];
+            var domain = [['id', 'in', ref]];
+            var accountInvoice = new model.web.Model('account.invoice');
+            accountInvoice.query(fields).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        //Comapnia
+        fetchResCompany: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var fields = ['id','name', 'currency_id', 'logo'];
+            var domain = [['id', '=', 1]];
+            var resCompanyIds = new model.web.Model('res.company');
+
+            resCompanyIds.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Res currecy
+        fetchResCurrecy : 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 resCurrecy = new model.web.Model('res.currency');
+
+            resCurrecy.query(fields).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Obtener moneda
+        getCurrency: function (id) {
+            var self = this;
+            return _.filter(self.resCurrecy,function (item) {
+                return item.id === id;
+            });
+        },
+        // Moneda de la factura
+        getInvoiceCurrency: function(id) {
+            var self = this;
+            var  currency_invoice = _.filter(self.accountInvoice, function(filter) {
+                return filter.id === id;
+            }).shift();
+            return self.getCurrency(currency_invoice.currency_id[0]);
+        },
+        // Reduce Move line
+        fetchReduceMoveLine: function () {
+            var self = this;
+            var newmoveLine = [];
+            var inteMove;
+            var residual = 0;
+            var currencyInvoice;
+            var company = self.resCompany.shift();
+            var currencyBase = self.getCurrency(company.currency_id[0]).shift();
+
+            for (var i = 0; i < self.moveLine.length; i++) {
+                inteMove = self.moveLine[i];
+
+                currencyInvoice = self.getInvoiceCurrency(inteMove.invoice[0]).shift();
+
+                if(!currencyInvoice) {
+                    currencyInvoice = {};
+                    currencyInvoice.rate=currencyBase.rate_silent;
+                }
+
+                newmoveLine.push({
+                    amount_residual: inteMove.amount_residual,
+                    amount_residual_currency: (inteMove.amount_residual_currency * (currencyBase.rate_silent / currencyInvoice.rate_silent))
+                });
+            }
+
+            if (newmoveLine.length > 0) {
+                residual = _.reduce(_.map(newmoveLine, function (map) {
+                    return map.amount_residual_currency;
+                }), function (memo, num) {
+                    return memo + num;
+                });
+            }
+
+            self.$el.find('.widget-content.widget-loading').css('display','none');
+            self.$el.find('.widget-content').find('a').text(accounting.formatMoney(residual, currencyBase.symbol, currencyBase.decimal_places, currencyBase.thousands_separator, currencyBase.decimal_separator));
+            self.$el.find('.grid-stack-item-content dashboard').unblock();
+        },
+
+        showCustomers: function (e) {
+            var self = this;
+            if (self.moveLine <=0) {
+                model.web.notification.do_warn("Atención","Sin datos");
+                return
+            }
+
+            var moneda = self.resCurrecy.shift();
+            var newmoveLine = self.moveLine;
+            var titleData = [
+                {
+                    title: "Deudas atrasadas"
+                }
+            ];
+            var headerModal = [
+                {
+                    title: "id"
+                },
+                {
+                    title: "Cliente"
+                },
+                {
+                    title: "Numero de Factura"
+                },
+                {
+                    title: "Vencimiento"
+                },
+                {
+                    title: "Monto "
+                }
+            ];
+
+            var modal = Qweb.render('ExpiredAccountCountersModal', {
+                data: newmoveLine,
+                dataThead: headerModal,
+                modalTitle: titleData
+            });
+
+            $('.openerp_webclient_container').after(modal);
+            $('.expired-account-modal').modal()
+            $('.expired-account-modal').on('hidden.bs.modal', function (e) {
+                self.removeModal(e);
+            })
+
+            var contenido = $('.expired-account-modal').find('.table-tbody');
+            contenido.click(function (e) {
+                $(contenido).find('tr').removeClass('table-row-select');
+                $(e.target).closest('tr').addClass('table-row-select');
+                var chirdren_id =$(e.target).closest('tr').children()[0].textContent;
+                self.renderForm(chirdren_id);
+            });
+        },
+        // Remover <Modal></Modal>
+        removeModal: function (e) {
+            $('.expired-account-modal').remove();
+            $('.modal-backdrop').remove();
+        },
+        // Llamar form
+        renderForm: function(id){
+            var self = this;
+            id = parseInt(id);
+
+            this.do_action({
+                type: "ir.actions.act_window",
+                res_model: "account.invoice",
+                views: [[self.modelId[1], 'form']],
+                target: 'current',
+                domain: [['id', '=', id]],
+                context: {},
+                res_id: id,
+            }).then(function() {
+                self.removeModal();
+            });
+        }
+    });
+}

+ 261 - 0
static/src/js/widgets/expired_account_counters_now.js

@@ -0,0 +1,261 @@
+function expired_account_counters_now (widget) {
+    "use strict";
+
+    var model = openerp;
+    var Qweb = openerp.web.qweb;
+
+    widget.ExpiredAccountCountersNowWidget = widget.Base.extend({
+        template: 'ExpiredAccountCountersNow',
+        moveLine: [],
+        resCompany: [],
+        resCompany: [],
+        modelId: [],
+        accountInvoice: [],
+
+        events: {
+            'click a': 'showCustomers',
+            'click h2': 'showCustomers',
+        },
+        init: function (parent) {
+            this._super(parent, {
+                width: 3,
+                height: 2
+            });
+        },
+        start: function () {
+            var self = this;
+            self.fetchInitial();
+        },
+        fetchInitial: function () {
+            var self = this;
+            self.$el.find('#morosidad').block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+            self.$el.find('.widget-content.widget-loading').css('display','flex');
+
+            self.fetchMoveLine().then(function(moveLine) {
+                return moveLine;
+            }).then(function(moveLine) {
+                self.moveLine= _.filter(moveLine, function(item) {
+                    return item.amount_residual  > 0
+                });
+                return self.fetchInvoice(moveLine);
+            }).then(function(accountInvoice) {
+                self.accountInvoice = accountInvoice
+                return self.fetchResCompany();
+            }).then(function(resCompany) {
+                self.resCompany=resCompany;
+                return self.fetchResCurrecy();
+            }).then(function(resCurrecy) {
+                self.resCurrecy= resCurrecy;
+                return self.fetchGetModelId();
+            }).then(function(modelId) {
+                self.modelId = modelId;
+                return self.fetchReduceMoveLine();
+            });
+        },
+        // getModelId
+        fetchGetModelId: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var irModelData = new model.web.Model('ir.model.data');
+            var getObtjectReference = irModelData.get_func('get_object_reference');
+
+            this.alive(getObtjectReference('account', 'invoice_form')).then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Move line
+        fetchMoveLine: function () {
+            var self = this;
+            var hoy = moment().format('YYYY-MM-DD');
+            var defer = $.Deferred();
+            var field = ['id', 'partner_id', 'amount_residual', 'credit', 'debit', 'date_maturity', 'invoice','ref', 'invoice', 'amount_residual_currency', 'currency_id'];
+            var domain = [['credit', '<=', 0], ['date_maturity', '=', hoy]];
+            var moveLine = new model.web.Model('account.move.line');
+
+            moveLine.query(field).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // invoice
+        fetchInvoice: function(moveline) {
+            var self = this ;
+            var defer = $.Deferred()
+            var ref = _.map(moveline, function(map) {
+                return map.invoice[0];
+            });
+            var fields = ['id', 'currency_id', 'number', 'currency_id'];
+            var domain = [['id', 'in', ref]];
+            var accountInvoice = new model.web.Model('account.invoice');
+            accountInvoice.query(fields).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        //Comapnia
+        fetchResCompany: function () {
+            var self = this;
+            var defer = $.Deferred();
+            var fields = ['id','name', 'currency_id','logo'];
+            var domain = [['id', '=', 1]];
+            var resComapy = new model.web.Model('res.company');
+
+            resComapy.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer ;
+        } ,
+        // Res currecy
+        fetchResCurrecy : 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 resCurrecy = new model.web.Model('res.currency');
+
+            resCurrecy.query(fields).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Reduce Move line
+        fetchReduceMoveLine: function () {
+            var self = this;
+            var newmoveLine = [];
+            var inteMove;
+            var residual = 0;
+            var currencyInvoice;
+            var company = self.resCompany.shift();
+            var currencyBase = self.getCurrency(company.currency_id[0]).shift();
+
+            for (var i = 0; i < self.moveLine.length; i++) {
+                inteMove = self.moveLine[i];
+
+                currencyInvoice = self.getInvoiceCurrency(inteMove.invoice[0]).shift();
+
+                if(!currencyInvoice) {
+                    currencyInvoice = {};
+                    currencyInvoice.rate=currencyBase.rate_silent;
+                }
+
+                newmoveLine.push({
+                    amount_residual: inteMove.amount_residual,
+                    amount_residual_currency: (inteMove.amount_residual_currency * (currencyBase.rate_silent / currencyInvoice.rate_silent))
+                });
+            }
+
+            if (newmoveLine.length > 0) {
+                residual = _.reduce(_.map(newmoveLine, function (map) {
+                    return map.amount_residual_currency;
+                }), function (memo, num) {
+                    return memo + num;
+                });
+            }
+
+            self.$el.find('.widget-content.widget-loading').css('display','none');
+            self.$el.find('.widget-content').find('a').text(accounting.formatMoney(residual, currencyBase.symbol, currencyBase.decimal_places, currencyBase.thousands_separator, currencyBase.decimal_separator));
+            self.$el.find('#morosidad').unblock();
+        },
+        // Obtener moneda
+        getCurrency: function (id) {
+            var self = this;
+            return _.filter(self.resCurrecy,function (item) {
+                return item.id === id;
+            });
+        },
+        // Moneda de la factura
+        getInvoiceCurrency: function(id){
+            var self = this;
+            var  currency_invoice = _.filter(self.accountInvoice, function(filter) {
+                return filter.id === id;
+            }).shift();
+            return self.getCurrency(currency_invoice.currency_id[0]);
+        },
+        showCustomers: function (e) {
+            var self = this;
+            if (self.moveLine.length <= 0) {
+                model.web.notification.do_warn("Atención","Sin datos");
+                return
+            }
+
+            var moneda = self.resCurrecy.shift();
+            var newmoveLine = [];
+            newmoveLine = self.moveLine;
+            var titleData = [
+                {
+                    title: "Deudas con vencimiento en el día de hoy"
+                }
+            ];
+            var headerModal = [
+                {
+                    title: "id"
+                },
+                {
+                    title: "Cliente"
+                },
+                {
+                    title: "Numero de Factura"
+                },
+                {
+                    title: "Vencimiento"
+                },
+                {
+                    title: "Monto "
+                }
+            ];
+
+            var modal = Qweb.render('ExpiredAccountCountersModal', {
+                data: newmoveLine,
+                dataThead: headerModal,
+                modalTitle: titleData
+            });
+
+            $('.openerp_webclient_container').after(modal);
+            $('.expired-account-modal').modal();
+            $('.expired-account-modal').on('hidden.bs.modal', function (e) {
+                self.removeModal(e);
+            })
+
+            var contenido = $('.expired-account-modal').find('.table-tbody');
+            contenido.click(function (e) {
+                $(contenido).find('tr').removeClass('table-row-select');
+                $(e.target).closest('tr').addClass('table-row-select');
+                var chirdren_id =$(e.target).closest('tr').children()[0].textContent;
+                self.renderForm(chirdren_id);
+            });
+        },
+        // Remover <Modal></Modal>
+        removeModal: function (e) {
+            $('.expired-account-modal').remove();
+            $('.modal-backdrop').remove();
+        },
+        // Llamar form
+        renderForm: function(id) {
+            var self = this;
+            id = parseInt(id);
+
+            this.do_action({
+                type: "ir.actions.act_window",
+                res_model: "account.invoice",
+                views: [[self.modelId[1], 'form']],
+                target: 'current',
+                domain: [['id', '=', id]],
+                context: {},
+                res_id: id,
+            }).then(function() {
+                self.removeModal();
+            });
+        }
+    });
+}

+ 229 - 0
static/src/js/widgets/invoice_history.js

@@ -0,0 +1,229 @@
+function invoice_history (widget) {
+    "use strict";
+
+    var model = openerp;
+
+    widget.InvoiceHistoryWidget = widget.Base.extend({
+        template: 'InvoiceHistory',
+        data: [],
+        countPosOrder: [],
+        resPartner: [],
+        modelId: [],
+
+        events: {
+            // 'click canvas': 'showCustomers'
+        },
+        init: function (parent) {
+            this._super(parent, {
+                width: 6,
+                height: 4
+            });
+        },
+        start: function () {
+            var self = this;
+            self.fetchInitial();
+        },
+        fetchInitial:function() {
+            var self = this;
+            self.$el.block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+
+            self.$el.find('.widget-content.widget-loading').css('display','flex');
+
+            self.fecthAccountInvoice().then(function (AccountInvoice) {
+                return AccountInvoice;
+            }).then(function (AccountInvoice) {
+                self.AccountInvoice = AccountInvoice;
+                return self.fetchGetModelId();
+            }).then(function(modelId) {
+                self.modelId = modelId;
+                return self.BuildChart();
+            });
+        },
+
+        // getModelId
+        fetchGetModelId: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var irModelData = new model.web.Model('ir.model.data');
+            var getObtjectReference = irModelData.get_func('get_object_reference');
+
+            this.alive(getObtjectReference('base', 'view_partner_form')).then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Obtener Pedidos
+        fecthAccountInvoice: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var fields = ['id','date_invoice','partner_id','amount_total','number','type'];
+            var domain = [['state','in',['paid','open']]];
+            var AccountInvoice = new model.web.Model('account.invoice');
+            AccountInvoice.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+
+        // Obtener facturas por cada proveedores
+        getInAccountInvoice:function(mes) {
+            var self = this;
+            if (mes < 10){
+                var fecha = moment().format('YYYY')+'-'+'0'+mes;    
+            }else{
+                var fecha = moment().format('YYYY')+'-'+mes;    
+            }
+            return _.flatten(_.filter(self.AccountInvoice,function (inv) {
+                return moment(inv.date_invoice).format('YYYY-MM') === fecha & inv.type === 'in_invoice';
+            }));
+        },
+
+        // Obtener facturas de clientes
+        getOutAccountInvoice:function(mes) {
+            var self = this;
+            if (mes < 10){
+                var fecha = moment().format('YYYY')+'-'+'0'+mes;    
+            }else{
+                var fecha = moment().format('YYYY')+'-'+mes;    
+            }
+            return _.flatten(_.filter(self.AccountInvoice,function (inv) {
+                return moment(inv.date_invoice).format('YYYY-MM') === fecha & inv.type === 'out_invoice';
+            }));
+        },
+        
+        // Generar el Ranking
+        BuildChart: function() {
+            var self = this;
+            var invoices;
+            var mes = 0;
+            var dataIn = [];
+            var dataOut = [];
+
+            for (var i = 1; i <= 12; i++) {
+                invoices = self.getInAccountInvoice(i);
+                var total = _.reduce(_.map(invoices,function(item) {
+                    return item.amount_total;
+                }),function(memo, num) {
+                    return memo + num;
+                },0);
+                dataIn.push({
+                    amount_total: accounting.formatNumber(total,0,".",","),
+                })
+            }
+            
+            for (var i = 1; i <= 12; i++) {
+                invoices = self.getOutAccountInvoice(i);
+                var total = _.reduce(_.map(invoices,function(item) {
+                    return item.amount_total;
+                }),function(memo, num) {
+                    return memo + num;
+                },0);
+                dataOut.push({
+                    amount_total: accounting.formatNumber(total,0,".",","),
+                })
+            }
+
+            // self.data = data;
+            self.$el.unblock();
+            self.$el.find('.widget-content.widget-loading').css('display','none');
+            self.$el.find('.widget-title').find('span').text("Historico de Facturas");
+            self.fetchChart(dataIn, dataOut);
+        },
+
+        // Generar Grafico
+        fetchChart: function (dataIn,dataOut) {
+            var self = this;
+            var label = ['Enero', 'Febrero', 'Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'];
+            var bodyIn = [];
+            var bodyOut = [];
+            var item;
+            var rank = 12;
+
+            // InInvoice
+            if (dataIn.length < rank && dataIn.length > 0){
+                rank= ranking.length;
+            }
+            for (var i = 0; i < rank; i++) {
+                if (dataIn[i]) {
+                    item = dataIn[i];
+                }
+                if (dataIn.length === 0) {
+                    item = {};
+                    item.amount_total = 0;
+                }
+                bodyIn.push(item.amount_total);
+            }
+
+
+            // OutInvoice
+            if (dataOut.length < rank && dataOut.length > 0){
+                rank= ranking.length;
+            }
+            for (var i = 0; i < rank; i++) {
+                if (dataOut[i]) {
+                    item = dataOut[i];
+                }
+                if (dataOut.length === 0) {
+                    item = {};
+                    item.amount_total = 0;
+                }
+                bodyOut.push(item.amount_total);
+            } 
+
+            // Global method for setting Y axis number format.
+            Chart.scaleService.updateScaleDefaults('linear', {
+              ticks: {
+                callback: function(tick) {
+                    return tick.toLocaleString('de-DE');
+                }
+              }
+            });
+            Chart.defaults.global.tooltips.callbacks.label = function(tooltipItem, data) {
+                var dataset = data.datasets[tooltipItem.datasetIndex];
+                var datasetLabel = dataset.label || '';
+                return datasetLabel +  dataset.data[tooltipItem.index].toLocaleString('de-DE');
+            };
+            var chart = new Chart(this.$el.find(".widget-content").find('canvas'), {
+                type: 'line',
+                data: {
+                    labels: label,
+                    datasets: [
+                        {
+                            label: 'Facturas de clientes  ',
+                            data: bodyOut,
+                            backgroundColor: '#e3f2fd',
+                            borderColor: '#64b5f6',
+                            borderWidth: 2,
+                            fill: false,
+                        },
+                        {
+                            label: 'Facturas de proveedor  ',                            
+                            data: bodyIn,
+                            backgroundColor: '#c8e6c9',
+                            borderColor: '#66bb6a',
+                            borderWidth: 2,
+                            fill: false,
+                        }
+                    ]
+                },
+                options: {
+                    responsive: true,
+                    title: {
+                        display: true,
+                    },
+                    hover: {
+                        mode: 'nearest',
+                        intersect: true
+                    },
+                }
+            });
+        },
+    });
+}

+ 105 - 0
static/src/js/widgets/invoice_today_counters.js

@@ -0,0 +1,105 @@
+function invoice_today_counters (widget) {
+    "use strict";
+
+    var model = openerp;
+
+    widget.InvoiceTodayCountersWidget = widget.Base.extend({
+        template: 'InvoiceTodayCounters',
+        irModelData: [],
+        accountInvoice: [],
+
+        events: {
+            'click a': 'showCustomers',
+            'click h2': 'showCustomers',
+        },
+        init: function (parent) {
+            this._super(parent, {
+                width : 3,
+                height: 2
+            });
+        },
+        start: function () {
+            var self = this;
+            self.fetchInitial();
+        },
+        fetchInitial: function() {
+            var self = this;
+            self.$el.find('#morosidad').block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+            self.$el.find('.widget-content.widget-loading').css('display','flex');
+
+            self.fetchAccountInvoice().then(function (accountInvoice) {
+                return accountInvoice;
+            }).then(function (accountInvoice) {
+                self.accountInvoice=accountInvoice;
+                return self.fetchGetModelId();
+            }).then(function(irModelData) {
+                self.irModelData=irModelData;
+                return self.fetchReduceInvoice(self.accountInvoice);
+            });
+        },
+        // getModelId
+        fetchGetModelId: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var irModelData = new model.web.Model('ir.model.data');
+            var getObtjectReference = irModelData.get_func('get_object_reference');
+
+            getObtjectReference('account', 'invoice_form').then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Invoice
+        fetchAccountInvoice: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var hoy = moment().format('YYYY-MM-DD');
+            var fields = ['id', 'residual'];
+            var domain = [['type', '=', 'out_invoice'], ['state', 'in', ['open','paid']], ['date_invoice', '=', hoy]];
+            var accountInvoice = new model.web.Model('account.invoice');
+
+            accountInvoice.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        fetchReduceInvoice: function (accountInvoice) {
+            var self = this;
+            var fecha = new Date();
+            var cat = 0;
+
+            if (accountInvoice.length > 0) {
+                cat = accountInvoice.length;
+            }
+
+            self.$el.find('.widget-content.widget-loading').css('display','none');
+            self.$el.find('.widget-content').find('a').text(accounting.formatNumber(cat, ".", ","));
+            self.$el.find('#morosidad').unblock();
+        },
+        showCustomers: function (e) {
+            var self = this;
+            if (self.accountInvoice.length === 0) {
+                model.web.notification.do_warn("Atención","Sin datos");
+                return
+            }
+            var hoy = moment().format('YYYY-MM-DD');
+
+            this.do_action({
+                name: "Facturas realizadas hoy",
+                type: 'ir.actions.act_window',
+                res_model: "account.invoice",
+                views: [[false, 'list'],[self.irModelData[1],'form']],
+                target: 'current',
+                domain: [['type', '=', 'out_invoice'], ['state', 'in', ['open','paid']], ['date_invoice', '=', hoy]],
+                context: {},
+            });
+        }
+    });
+}

+ 110 - 0
static/src/js/widgets/missing_product.js

@@ -0,0 +1,110 @@
+function missing_product (widget) {
+    "use strict";
+
+    var model = openerp;
+
+    widget.MissingProductWidget = widget.Base.extend({
+        template: 'MissingProduct',
+        stockQuant: [],
+        productProduct: [],
+        modelId: [],
+
+        events: {
+            'click a': 'showCustomers',
+            'click h2': 'showCustomers',
+        },
+        init: function (parent) {
+            this._super(parent, {
+                width: 3,
+                height: 2
+            });
+        },
+        start: function () {
+            var self = this;
+            self.fetchInitial();
+        },
+        fetchInitial: function () {
+            var self = this;
+            self.$el.find('#morosidad').block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+            self.$el.find('.widget-content.widget-loading').css('display','flex');
+            // Iniciar Consultas
+            self.fetchProductProduct().then(function(productProduct) {
+                return productProduct;
+            }).then(function(productProduct) {
+                self.productProduct = productProduct;
+                return self.fetchGetModelId();
+            }).then(function(modelId) {
+                self.modelId = modelId;
+                return self.fetchReduceProduct();
+            });
+        },
+        // getModelId
+        fetchGetModelId: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var irModelData = new model.web.Model('ir.model.data');
+            var getObtjectReference = irModelData.get_func('get_object_reference');
+
+            this.alive(getObtjectReference('product', 'product_normal_form_view')).then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        fetchProductProduct : function(stockQaunt) {
+            var self = this;
+            var defer = $.Deferred();
+            var product_id = _.map(stockQaunt,function(map) {
+                return map.product_id[0];
+            });
+            var fields = ['id', 'name_template', 'qty_available'];
+            var domain = [['qty_available', '<=', 0],['type', '=', 'product'],['active','=',true]];
+            var productProduct = new model.web.Model('product.product');
+            productProduct.query(fields).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // // Reduce Move line
+        fetchReduceProduct: function () {
+            var self = this;
+            var cantidad;
+            cantidad = _.countBy(_.map(self.productProduct,function(map) {
+                return map.id;
+            }),function(num) {
+                return num ? 'even': 'odd';
+            });
+
+            if (!cantidad.even) {
+                cantidad = {};
+                cantidad.even = 0;
+            }
+
+            self.$el.find('.widget-content.widget-loading').css('display','none');
+            self.$el.find('.widget-content').find('a').text(cantidad.even);
+            self.$el.find('#morosidad').unblock();
+        },
+        showCustomers: function (e) {
+            var self = this;
+            if (self.productProduct.length === 0 ) {
+                model.web.notification.do_warn("Atención","Sin datos");
+                return
+            }
+            this.do_action({
+                name: "Listado de productos faltan-tes",
+                type: 'ir.actions.act_window',
+                res_model: "product.product",
+                views: [[false, 'list'],[self.modelId[1],'form']],
+                target: 'current',
+                domain: [['type', '=', 'product'],['qty_available','<=',0]],
+                context: {},
+            });
+        }
+    });
+}

+ 203 - 0
static/src/js/widgets/monthly_expenses.js

@@ -0,0 +1,203 @@
+function monthly_expenses(widget) {
+    "use strict";
+
+    var model = openerp;
+
+    widget.MonthlyExpensesWidget = widget.Base.extend({
+        template: 'MonthlyExpenses',
+        accountVoucher: [],
+        accountInvoice: [],
+        resCurrecy: [],
+        resCompany: [],
+
+        events: {
+            'click a': 'showCustomers',
+            'click h2': 'showCustomers',
+        },
+
+        init: function (parent) {
+            this._super(parent, {
+                width: 3,
+                height: 2
+            });
+        },
+
+        start: function () {
+            var self = this;
+            self.fetchInitial();
+        },
+
+        fetchInitial: function(){
+            var self = this;
+            self.$el.find('#morosidad').block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+            self.$el.find('.widget-content.widget-loading').css('display','flex');
+
+            self.fetchAccountVoucher().then(function (accountVoucher) {
+                return accountVoucher;
+            }).then(function (accountVoucher) {
+                self.accountVoucher = accountVoucher;
+                return self.fetchAccountInvoice(accountVoucher);
+            }).then(function(accountInvoice) {
+                self.accountInvoice = accountInvoice;
+                return self.fetchResCompany();
+            }).then(function(resCompany) {
+                self.resCompany = resCompany;
+                return self.fetchResCurrecy();
+            }).then(function(resCurrecy) {
+                self.resCurrecy = resCurrecy;
+                return self.fetchReduceVoucher();
+            });
+        },
+        // voucher pagos a proveedor  rango de fecha um mes
+        fetchAccountVoucher: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var desde = moment().format('YYYY-MM-01');
+            var hasta = moment().add(1,'months').format('YYYY-MM-01');
+            var fields = ['id', 'amount', 'currency_id', 'payment_rate_currency_id', 'reference'];
+            var domain = [['type', '=', 'payment'],['state', '=', 'posted'],['date', '>=',desde],['date','<',hasta]];
+            var accountVoucher = new model.web.Model('account.voucher');
+
+            accountVoucher.query(fields).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // invoice -> origin === false
+        fetchAccountInvoice:function(voucher) {
+            var self = this;
+            var defer = $.Deferred();
+            var number = _.map(voucher,function(map){return map.reference});
+            var fields = ['id','number','date_invoice','origin'];
+            var domain = [['type', '=', 'in_invoice'],['origin', '=', false ],['number', 'in', number]];
+            var accountInvoice = new model.web.Model('account.invoice');
+
+            accountInvoice.query(fields).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        //Comapnia
+        fetchResCompany: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var fields = ['id','name', 'currency_id'];
+            var domain = [['id', '=', 1]];
+            var resCompany = new model.web.Model('res.company');
+
+            resCompany.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Moneda
+        fetchResCurrecy : 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 resCurrecy = new model.web.Model('res.currency');
+
+            resCurrecy.query(fields).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+
+        fetchReduceVoucher: function () {
+            var self = this
+            var voucher = [];
+            var newVoucher = self.getVoucherInvoice();
+            var itemVoucher;
+            var currencyVoucher;
+            var cat = 0;
+            var company = self.resCompany.shift();
+            var currencyBase = self.getCurrency(company.currency_id[0]).shift();
+
+            for (var i = 0; i < newVoucher.length; i++) {
+                itemVoucher = newVoucher[i];
+                currencyVoucher = self.getCurrency(itemVoucher.payment_rate_currency_id[0]).shift();
+
+                if(!currencyVoucher){
+                    currencyVoucher = {};
+                    currencyVoucher.rate = currencyBase.rate_silent;
+                }
+                voucher.push({
+                    ammount: itemVoucher.amount,
+                    amount_rate: (itemVoucher.amount* (currencyBase.rate_silent/currencyVoucher.rate_silent))
+                });
+            }
+
+            if (voucher.length > 0) {
+                cat = _.reduce(_.map(voucher, function (map) {
+                    return map.amount_rate;
+                }), function (memo, num) {
+                    return memo + num;
+                });
+            }
+
+            self.$el.find('.widget-content.widget-loading').css('display','none');
+            self.$el.find('.widget-content').find('a').text(accounting.formatMoney(cat, currencyBase.symbol, currencyBase.decimal_places, currencyBase.thousands_separator, currencyBase.decimal_separator))
+            self.$el.find('#morosidad').unblock();
+        },
+        // Obtener la moneda
+        getCurrency: function (id) {
+            var self = this;
+            return _.filter(self.resCurrecy,function (item) {
+                return item.id === id;
+            })
+        },
+        // Obtener los pagos de las factura sim origin
+        getVoucherInvoice:function() {
+            var self = this;
+            var number = _.map(self.accountInvoice, function(map) {
+                return map.number;
+            });
+
+            return  _.flatten(_.filter(self.accountVoucher,function(item) {
+                return _.contains(number,item.reference);
+            }));
+        },
+        // Modal
+        showCustomers: function (e) {
+            var self = this;
+            if (self.accountVoucher.length === 0) {
+                model.web.notification.do_warn("Atención","Sin datos");
+                return
+            }
+            var hoy = moment().format('YYYY-MM-DD');
+            var desde = moment().format('YYYY-MM-01');
+            var hasta = moment().add(1,'months').format('YYYY-MM-01');
+            var number = _.map(self.accountInvoice,function(map) {
+                return map.number;
+            });
+
+            this.do_action({
+                name: "Listado de gastos del mes",
+                type: 'ir.actions.act_window',
+                res_model: "account.voucher",
+                views: [[false, 'list'],[false,'form']],
+                target: 'new',
+                domain: [['type', '=', 'payment'],['state', '=', 'posted'],['date', '>=',desde],['date','<',hasta],['reference','in',number]],
+                context: {},
+                flags: {
+                    'form': {
+                        'action_buttons': false,
+                        'options': {
+                            'mode': 'view'
+                        }
+                    }
+                },
+            });
+        }
+    });
+}

+ 204 - 0
static/src/js/widgets/monthly_purchases.js

@@ -0,0 +1,204 @@
+function monthly_purchases(widget) {
+    "use strict";
+
+    var model = openerp;
+
+    widget.MonthlyPurchasesWidget = widget.Base.extend({
+        template: 'MonthlyPurchases',
+        accountVoucher: [],
+        accountInvoice: [],
+        resCurrecy: [],
+        resCompany: [],
+
+        events: {
+            'click a': 'showCustomers',
+            'click h2': 'showCustomers',
+        },
+
+        init: function (parent) {
+            this._super(parent, {
+                width: 3,
+                height: 2
+            });
+        },
+
+        start: function () {
+            var self = this;
+            self.fetchInitial();
+        },
+
+        fetchInitial: function() {
+            var self = this;
+            self.$el.find('#morosidad').block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+
+            self.$el.find('.widget-content.widget-loading').css('display','flex');
+
+            self.fetchAccountVoucher().then(function (accountVoucher) {
+                return accountVoucher;
+            }).then(function (accountVoucher) {
+                self.accountVoucher = accountVoucher;
+                return self.fetchAccountInvoice(accountVoucher);
+            }).then(function(accountInvoice) {
+                self.accountInvoice = accountInvoice;
+                return self.fetchResCompany();
+            }).then(function(resCompany) {
+                self.resCompany = resCompany;
+                return self.fetchResCurrecy();
+            }).then(function(resCurrecy) {
+                self.resCurrecy = resCurrecy;
+                return self.fetchReduceVoucher();
+            });
+        },
+        // Account Voucher Pagos a facturas Proveedores
+        fetchAccountVoucher: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var desde = moment().format('YYYY-MM-01');
+            var hasta = moment().add(1,'months').format('YYYY-MM-01');
+            var fields = ['id', 'amount', 'currency_id', 'payment_rate_currency_id', 'reference'];
+            var domain = [['type', '=', 'payment'],['state', '=', 'posted'],['date', '>=',desde],['date','<',hasta]];
+            var accountVoucher = new model.web.Model('account.voucher');
+
+            accountVoucher.query(fields).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // invoice
+        fetchAccountInvoice:function(voucher) {
+            var self = this;
+            var defer = $.Deferred();
+            var number = _.map(voucher,function(map) {
+                return map.reference;
+            });
+            var fields = ['id','number','date_invoice','origin'];
+            var domain = [['type', '=', 'in_invoice'],['origin', '!=', false ],['number', 'in', number]];
+            var accountInvoice = new model.web.Model('account.invoice');
+
+            accountInvoice.query(fields).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        //Comapnia
+        fetchResCompany: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var fields = ['id','name', 'currency_id', 'logo'];
+            var domain = [['id', '=', 1]];
+            var resCompany = new model.web.Model('res.company');
+
+            resCompany.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Res currecy
+        fetchResCurrecy : 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 resCurrecy = new model.web.Model('res.currency');
+
+            resCurrecy.query(fields).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+
+        fetchReduceVoucher: function () {
+            var self = this
+            var voucher = [];
+            var newVoucher = self.getVoucherInvoice();
+            var itemVoucher;
+            var currencyVoucher;
+            var cat = 0;
+            var company = self.resCompany.shift();
+            var currencyBase = self.getCurrency(company.currency_id[0]).shift();
+
+            for (var i = 0; i < newVoucher.length; i++) {
+                itemVoucher = newVoucher[i];
+                currencyVoucher = self.getCurrency(itemVoucher.payment_rate_currency_id[0]).shift();
+
+                if(!currencyVoucher) {
+                    currencyVoucher = {};
+                    currencyVoucher.rate = currencyBase.rate_silent;
+                }
+                voucher.push({
+                    ammount: itemVoucher.amount,
+                    amount_rate: (itemVoucher.amount* (currencyBase.rate_silent/currencyVoucher.rate_silent))
+                });
+            }
+
+            if (voucher.length > 0) {
+                cat = _.reduce(_.map(voucher, function (map) {
+                    return map.amount_rate;
+                }), function (memo, num) {
+                    return memo + num;
+                });
+            }
+
+            self.$el.find('.widget-content.widget-loading').css('display','none');
+            self.$el.find('.widget-content').find('a').text(accounting.formatMoney(cat, currencyBase.symbol, currencyBase.decimal_places, currencyBase.thousands_separator, currencyBase.decimal_separator));
+            self.$el.find('#morosidad').unblock();
+        },
+        // Obtener la moneda
+        getCurrency: function (id) {
+            var self = this;
+            return _.filter(self.resCurrecy,function (item) {
+                return item.id === id
+            })
+        },
+        // obtneer los pagos con origin
+        getVoucherInvoice:function() {
+            var self = this;
+            var number = _.map(self.accountInvoice, function(map) {
+                return map.number;
+            });
+            return  _.flatten(_.filter(self.accountVoucher,function(item) {
+                return _.contains(number,item.reference);
+            }));
+        },
+        // modal
+        showCustomers: function (e) {
+            var self = this;
+
+            if (self.accountInvoice.length === 0) {
+                model.web.notification.do_warn("Atención","Sin datos");
+                return
+            }
+            var hoy = moment().format('YYYY-MM-DD');
+            var desde = moment().format('YYYY-MM-01');
+            var hasta = moment().add(1,'months').format('YYYY-MM-01');
+            var number = _.map(self.accountInvoice,function(map){return map.number});
+
+            this.do_action({
+                name: "Listado de compras del mes",
+                type: 'ir.actions.act_window',
+                res_model: "account.voucher",
+                views: [[false, 'list'],[false,'form']],
+                target: 'new',
+                domain: [['type', '=', 'payment'],['state', '=', 'posted'],['date', '>=',desde],['date','<',hasta],['reference','in',number]],
+                context: {},
+                flags: {
+                    'form': {
+                        'action_buttons': false,
+                        'options': {
+                            'mode': 'view'
+                        }
+                    }
+                },
+            });
+        }
+    });
+}

+ 168 - 0
static/src/js/widgets/payments_today_counters.js

@@ -0,0 +1,168 @@
+function payments_today_counters (widget) {
+    "use strict";
+
+    var model = openerp;
+
+    widget.PaymentsTodayCountersWidget = widget.Base.extend({
+        template: 'PaymentsTodayCounters',
+        accountVoucher: [],
+        resCompany: [],
+        resCurrecy: [],
+
+        events: {
+            'click a': 'showCustomers',
+            'click h2': 'showCustomers',
+        },
+
+        init: function (parent) {
+            this._super(parent, {
+                width: 3,
+                height: 2
+            });
+        },
+
+        start: function () {
+            var self = this;
+            self.fetchInitial();
+        },
+
+        fetchInitial: function () {
+            var self = this;
+            self.$el.find('#morosidad').block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+
+            self.$el.find('.widget-content.widget-loading').css('display','flex');
+
+            self.fetchAccountVoucher().then(function (accountVoucher) {
+                return accountVoucher;
+            }).then(function (accountVoucher) {
+                self.accountVoucher = accountVoucher;
+                return self.fetchResCompany();
+            }).then(function (resCompany) {
+                self.resCompany = resCompany;
+                return self.fetchResCurrecy(resCompany);
+            }).then(function(resCurrecy) {
+                self.resCurrecy = resCurrecy;
+                return self.fetchVoucherCurrency();
+            });
+        },
+        // Account Voucher
+        fetchAccountVoucher: function () {
+            var self = this;
+            var defer = $.Deferred();
+            var hoy = moment().format('YYYY-MM-DD');
+            var fields = ['id', 'amount', 'currency_id', 'payment_rate_currency_id'];
+            var domain = [['state', '=', 'posted'], ['type', '=', 'payment'], ['date', '=', hoy]];
+            var accountVoucher = new model.web.Model('account.voucher');
+
+            accountVoucher.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        //Comapnia
+        fetchResCompany: function () {
+            var self = this;
+            var defer = $.Deferred();
+            var fields = ['id','name', 'currency_id','logo'];
+            var domain = [['id', '=', 1]];
+            var resCompany = new model.web.Model('res.company');
+
+            resCompany.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Moneda
+        fetchResCurrecy : 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 resCurrecy = new model.web.Model('res.currency');
+
+            resCurrecy.query(fields).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        //   voucherCurrencyRate
+        fetchVoucherCurrency: function () {
+            var self = this;
+            var newVoucher = [];
+            var itemVoucher;
+            var residual = 0;
+            var company = self.resCompany.shift();
+            var currencyBase = self.getCutrrency(company.currency_id[0]).shift();
+            var currencyVoucher;
+
+            for (var i = 0; i < self.accountVoucher.length; i++) {
+                itemVoucher = self.accountVoucher[i];
+
+                currencyVoucher =  self.getCutrrency(itemVoucher.payment_rate_currency_id[0]).shift();
+                if(!currencyVoucher){
+                    currencyVoucher = {};
+                    currencyVoucher.rate_silent = currencyBase.rate_silent;
+                }
+
+                newVoucher.push({
+                    amount: itemVoucher.amount,
+                    amount_rate: (itemVoucher.amount * (currencyBase.rate_silent / currencyVoucher.rate_silent))
+                });
+            }
+
+            if (newVoucher.length > 0) {
+                residual = _.reduce(_.map(newVoucher, function (map) {
+                    return map.amount_rate;
+                }), function (memo, num) {
+                    return memo + num;
+                });
+            }
+
+            self.$el.find('.widget-content.widget-loading').css('display','none');
+            self.$el.find('.widget-content').find('a').text(accounting.formatMoney(residual, currencyBase.symbol, currencyBase.decimal_places, currencyBase.thousands_separator, currencyBase.decimal_separator))
+            self.$el.find('#morosidad').unblock();
+        },
+        // Obtener la moneda
+        getCutrrency: function (id) {
+            var self = this;
+            return _.filter(self.resCurrecy,function (item) {
+                return item.id === id
+            })
+        },
+        // modal
+        showCustomers: function (e) {
+            var self = this;
+            if (self.accountVoucher.length === 0) {
+                model.web.notification.do_warn("Atención","Sin datos");
+                return
+            }
+            var hoy =moment().format('YYYY-MM-DD');
+
+            this.do_action({
+                name: "Listado de pagos realizados hoy",
+                type: 'ir.actions.act_window',
+                res_model: "account.voucher",
+                views: [[false, 'list'],[false, 'form']],
+                target: 'new',
+                domain: [['state', '=', 'posted'], ['type', '=', 'payment'], ['date', '=', hoy]],
+                context: {},
+                flags: {
+                    'form': {
+                        'action_buttons': false,
+                        'options': {
+                            'mode': 'view'
+                        }
+                    }
+                },
+            });
+        }
+    });
+}

+ 104 - 0
static/src/js/widgets/pos_order_today_counters.js

@@ -0,0 +1,104 @@
+function pos_order_today_counters(widget) {
+    "use strict";
+
+    var model = openerp;
+
+    widget.PosOrderTodayCountersWidget = widget.Base.extend({
+        template: 'PosOrderTodayCounters',
+        irModelData: [],
+        accountInvoice: [],
+
+        events: {
+            'click a': 'showCustomers',
+            'click h2': 'showCustomers',
+        },
+        init: function (parent) {
+            this._super(parent, {
+                width : 3,
+                height: 2
+            });
+        },
+        start: function () {
+            var self = this;
+            self.fetchInitial();
+        },
+        fetchInitial: function() {
+            var self = this;
+            self.$el.find('#morosidad').block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+            self.$el.find('.widget-content.widget-loading').css('display','flex');
+
+            self.fetchPosOrder().then(function (PosOrder) {
+                return PosOrder;
+            }).then(function (PosOrder) {
+                self.PosOrder=PosOrder;
+                return self.fetchGetModelId();
+            }).then(function(irModelData) {
+                self.irModelData=irModelData;
+                return self.fetchReducePosOrder(self.PosOrder);
+            });
+        },
+        // getModelId
+        fetchGetModelId: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var irModelData = new model.web.Model('ir.model.data');
+            var getObtjectReference = irModelData.get_func('get_object_reference');
+
+            getObtjectReference('point_of_sale', 'view_pos_pos_form').then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Invoice
+        fetchPosOrder: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var hoy = moment().format('YYYY-MM-DD h:mm:ss');
+            // console.log(hoy)
+            var fields = ['id', 'name','date_order'];
+            var domain = [['state', 'in', ['paid','done','invoiced']],['date_order', '>=', hoy]];
+            var PosOrder = new model.web.Model('pos.order');
+
+            PosOrder.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+            return defer;
+        },
+        fetchReducePosOrder: function (PosOrder) {
+            var self = this;
+            var fecha = new Date();
+            var cat = 0;
+
+            if (PosOrder.length > 0) {
+                cat = PosOrder.length;
+            }
+
+            self.$el.find('.widget-content.widget-loading').css('display','none');
+            self.$el.find('.widget-content').find('a').text(accounting.formatNumber(cat, ".", ","));
+            self.$el.find('#morosidad').unblock();
+        },
+        showCustomers: function (e) {
+            var self = this;
+            if (self.PosOrder.length === 0) {
+                model.web.notification.do_warn("Atención","Sin datos");
+                return
+            }
+            var hoy = moment().format('YYYY-MM-DD 00:00:00');
+            this.do_action({
+                name: "Pedidos realizados hoy",
+                type: 'ir.actions.act_window',
+                res_model: "pos.order",
+                views: [[false, 'list'],[self.irModelData[1],'form']],
+                target: 'current',
+                domain: [['state', 'in', ['paid','done','invoiced']],['date_order', '>=', hoy]],
+                context: {},
+            });
+        }
+    });
+}

+ 236 - 0
static/src/js/widgets/ranking_pos_orders_partner.js

@@ -0,0 +1,236 @@
+function ranking_pos_orders_partner (widget) {
+    "use strict";
+
+    var model = openerp;
+
+    widget.RankingPosOrdersPartnerWidget = widget.Base.extend({
+        template: 'RankingPosOrdersPartner',
+        data: [],
+        countPosOrder: [],
+        resPartner: [],
+        modelId: [],
+
+        events: {
+            'click canvas': 'showCustomers'
+        },
+        init: function (parent) {
+            this._super(parent, {
+                width: 6,
+                height: 4
+            });
+        },
+        start: function () {
+            var self = this;
+            self.fetchInitial();
+        },
+        fetchInitial:function() {
+            var self = this;
+            self.$el.block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+
+            self.$el.find('.widget-content.widget-loading').css('display','flex');
+
+            self.fecthPosOrder().then(function (PosOrder) {
+                return PosOrder;
+            }).then(function (PosOrder) {
+                self.PosOrder = PosOrder;
+                return self.fecthPartner(PosOrder);
+            }).then(function (resPartner) {
+                self.resPartner = resPartner;
+                return self.fetchGetModelId();
+            }).then(function(modelId) {
+                self.modelId = modelId;
+                return self.fetchProductRanking();
+            });
+        },
+        // getModelId
+        fetchGetModelId: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var irModelData = new model.web.Model('ir.model.data');
+            var getObtjectReference = irModelData.get_func('get_object_reference');
+
+            this.alive(getObtjectReference('base', 'view_partner_form')).then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Obtener Pedidos
+        fecthPosOrder: function() {
+            var self = this;
+            var desde = moment().format('YYYY-MM-01 00:00:00');
+            var hasta = moment().add(1,'months').format('YYYY-MM-01 00:00:00');
+            var defer = $.Deferred();
+            var fields = ['id','date_order','partner_id','amount_total'];
+            var domain = [['state', 'in', ['paid','done','invoiced']], ['partner_id', '!=', false], ['date_order', '>=', desde], ['date_order', '<', hasta]];
+            var PosOrder = new model.web.Model('pos.order');
+            PosOrder.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Consultar Clientes
+        fecthPartner: function(PosOrder) {
+            var self = this;
+            var defer = $.Deferred();
+            var partner_id = _.map(PosOrder,function(map){
+                return map.partner_id[0];
+            });
+            var fields = ['id', 'name'];
+            var domain = [['id', 'in', partner_id],['active', '=', true],['customer','=',true]];
+            var resPartner = new model.web.Model('res.partner');
+            resPartner.query(fields).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Obtener facturas por cada clientes
+        getPosOrder:function(partner_id) {
+            var self = this;
+            return _.flatten(_.filter(self.PosOrder,function (inv) {
+                return inv.partner_id[0] === partner_id;
+            }));
+        },
+        // Generar el Ranking
+        fetchProductRanking: function() {
+            var self = this;
+            var itemPartner;
+            var itemPosOrder;
+            var countPosOrder = 0
+            var ranking = [];
+
+            for (var i = 0; i < self.resPartner.length; i++) {
+                itemPartner = self.resPartner[i];
+                itemPosOrder = self.getPosOrder(itemPartner.id);
+
+                var quantity = _.reduce(_.map(itemPosOrder,function(item) {
+                    return item.amount_total;
+                }),function(memo, num) {
+                    return memo + num;
+                },0);
+
+                ranking.push({
+                    id: itemPartner.id,
+                    name: itemPartner.name,
+                    countPosOrder: quantity
+                });
+            }
+            ranking.sort(function (a, b) {
+                return b.countPosOrder - a.countPosOrder
+            });
+            self.ranking = ranking;
+
+            self.$el.unblock();
+            self.$el.find('.widget-content.widget-loading').css('display','none');
+            self.$el.find('.widget-title').find('span').text("Ranking de clientes con más compras en el mes");
+            self.fetchChart(ranking);
+        },
+        // Generar Grafico
+        fetchChart: function (ranking) {
+            var self = this;
+            var label = [];
+            var body = [];
+            var item;
+            var rank = 5;
+
+            if (ranking.length < rank && ranking.length > 0 )
+                rank= ranking.length;
+
+            for (var i = 0; i < rank; i++) {
+                if (ranking[i]) {
+                    item = ranking[i];
+                }
+                if (ranking.length === 0) {
+                    item = {};
+                    item.name = "N/A";
+                    item.countPosOrder = 0;
+                }
+                label.push(item.name);
+                body.push(item.countPosOrder);
+            }
+            console.log(body);
+            // Global method for setting Y axis number format.
+            Chart.scaleService.updateScaleDefaults('linear', {
+              ticks: {
+                callback: function(tick) {
+                    return tick.toLocaleString('de-DE');
+                }
+              }
+            });
+            Chart.defaults.global.tooltips.callbacks.label = function(tooltipItem, data) {
+                var dataset = data.datasets[tooltipItem.datasetIndex];
+                var datasetLabel = dataset.label || '';
+                return datasetLabel +  dataset.data[tooltipItem.index].toLocaleString('de-DE');
+            };
+            var chart = new Chart(this.$el.find(".widget-content").find('canvas'), {
+                type: 'line',
+                data: {
+                    labels: label,
+                    datasets: [
+                        {
+                            label: 'Ranking  ',
+                            backgroundColor: '#e3f2fd',
+                            borderColor: '#64b5f6',
+                            borderWidth: 2,
+                            // fill: false,
+                            data: body,
+                        }
+                    ]
+                },
+                options: {
+                    responsive: true,
+                    // title: {
+                    //     display: false,
+                    // },
+                    hover: {
+                        mode: 'nearest',
+                        intersect: true
+                    },
+                   // scales: {
+                   //     xAxes: [{ stacked: true }],
+                   //     yAxes: [{ stacked: true }],
+                   // },
+                   // legend: {
+                   //     display: false,
+                   // },
+                    layout: {
+                        padding: {
+                            top: 20,
+                            bottom: 0,
+                            left : 0,
+                            rigth: 0,
+                        }
+                    },
+                }
+            });
+        },
+        // llamar a la lista
+        showCustomers: function (e) {
+            var self = this;
+            if (self.ranking.length === 0 ) {
+                model.web.notification.do_warn("Atención","Sin datos");
+                return
+            }
+            var hoy = moment().format('YYYY-MM-DD');
+            var partner_id = _.map(self.ranking,function(map){
+                return map.id;
+            })
+            this.do_action({
+                name: "Listado de clientes con más compras",
+                type: 'ir.actions.act_window',
+                res_model: "res.partner",
+                views: [[false,'list'],[self.modelId[1],'form']],
+                target: 'current',
+                domain: [['id', 'in', partner_id]],
+                context: {},
+            });
+        }
+    });
+}

+ 265 - 0
static/src/js/widgets/ranking_pos_orders_product.js

@@ -0,0 +1,265 @@
+function ranking_pos_orders_product (widget) {
+    "use strict";
+
+    var model = openerp;
+
+    widget.RankingPosOrdersProductWidget = widget.Base.extend({
+        template: 'RankingPosOrdersProduct',
+        data: [],
+        accountInvoice: [],
+        invoiceLine: [],
+        productProduct: [],
+        ranking: [],
+        modelId: [],
+
+        events: {
+            // 'click canvas': 'showCustomers'
+            'click h2': 'showCustomers'
+        },
+        init: function (parent) {
+            this._super(parent, {
+                width: 6,
+                height: 4
+            });
+        },
+        start: function () {
+            var self = this;
+            self.fetchInitial();
+        },
+        fetchInitial: function() {
+            var self = this;
+            self.$el.block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+            self.$el.find('.widget-content.widget-loading').css('display','flex');
+
+            self.fecthPosOrder().then(function (PosOrder) {
+                return PosOrder;
+            }).then(function (PosOrder) {
+                self.PosOrder = PosOrder;
+                return self.fecthPosOrderLine(PosOrder);
+            }).then(function (PosOrderLine) {
+                self.PosOrderLine = PosOrderLine;
+                return self.fecthProductProduct(PosOrderLine);
+            }).then(function(productProduct){
+                self.productProduct = productProduct;
+                return self.fetchGetModelId();
+            }).then(function(modelId){
+                self.modelId = modelId;
+                return self.fetchProductRanking();
+            });
+        },
+        // getModelId
+        fetchGetModelId: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var irModelData = new model.web.Model('ir.model.data');
+            var getObtjectReference = irModelData.get_func('get_object_reference');
+
+            this.alive(getObtjectReference('product', 'product_normal_form_view')).then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Obtener Pedido
+        fecthPosOrder: function() {
+            var self = this;
+            var desde = moment().format('YYYY-MM-01 00:00:00');
+            var hasta = moment().add(1,'months').format('YYYY-MM-01 00:00:00');
+            var defer = $.Deferred();
+            var fields = ['id', 'lines', 'date_order'];
+            var domain = [['date_order', '>=', desde], ['date_order', '<', hasta], ['state', 'in', ['paid','done','invoiced']]];
+            var PosOrder = new model.web.Model('pos.order');
+            PosOrder.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Obtener linea de la factura
+        fecthPosOrderLine: function(PosOrder) {
+            var self = this;
+            var defer = $.Deferred();
+            var lines = _.flatten(_.map(PosOrder, function (item) {
+                return item.lines;
+            }));
+            var fields = ['id', 'product_id', 'qty'];
+            var domain = [['id','in', lines]];
+            var PosOrderLine = new model.web.Model('pos.order.line');
+            PosOrderLine.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Obtener Productos
+        fecthProductProduct: function (PosOrderLine) {
+            var self = this;
+            var defer = $.Deferred();
+            var product_id = _.flatten(_.map(PosOrderLine,function (item) {
+                return item.product_id[0];
+            }));
+            var fields = ['id', 'name_template', 'type','attribute_str'];
+            var domain = [['id', 'in', product_id]];
+            var ProductProduct = new model.web.Model('product.product');
+            ProductProduct.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // get line
+        getPosOrderLine: function (product_id) {
+            var self = this;
+            return _.flatten(_.filter(self.PosOrderLine,function (item) {
+                return item.product_id[0] === product_id
+            }));
+        },
+        // Generear el ranking
+        fetchProductRanking: function() {
+            var self = this;
+            var itemProduct;
+            var itemLine;
+            var ranking = [];
+            var cat = 0;
+            var attribute;
+            var lineUnik;
+            for (var i = 0; i < self.productProduct.length; i++) {
+                itemProduct = self.productProduct[i];
+                itemLine = self.getPosOrderLine(itemProduct.id);
+                if (itemLine.length > 0) {
+                    cat = _.reduce(_.map(itemLine, function (map) {
+                        return map.qty
+                    }), function (meno,num) {
+                        return meno + num
+                    }, 0);
+
+                    lineUnik = itemLine.shift();
+
+                    if(itemProduct.attribute_str){
+                        attribute = '*' + itemProduct.attribute_str;
+                    }else{
+                        attribute = ' ';
+                    }
+                    ranking.push({
+                        product: itemProduct.name_template + ' ' + attribute,
+                        qty: cat,
+                        id: lineUnik.product_id[0],
+                        type: itemProduct.type
+                    });
+                }
+            }
+            ranking.sort(function(a, b) {
+                return b.qty - a.qty
+            });
+            self.$el.unblock();
+            self.$el.find('.widget-content.widget-loading').css('display','none');
+            var fecha = new Date();
+            var meses = new Array ("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre");
+            self.$el.find('.widget-title').find('span').text("Ranking de productos y servicios del mes de " + meses[fecha.getMonth()]);
+            // self.$el.find('.widget-title').find('span').text("Ranking de productos más vendidos del mes de " + meses[fecha.getMonth()]);
+            self.ranking = ranking;
+            self.fetchChart(ranking);
+        },     
+        // Generar Grafico
+        fetchChart: function (ranking){
+            var self = this;
+            var label = [];
+            var bodyProducto = [];
+            var labelService = [];
+            var bodyService = [];
+            var rank = 7;
+            var item;
+
+            for (var i = 0; i < rank; i++) {
+                if (ranking[i]){
+                    item = ranking[i];
+                }else{
+                    item = {};
+                    item.product = "N/A";
+                    item.qty = 0;
+                }
+                var name = item.product.split('*');
+                if (name.length === 1) {
+                        label.push(name[0]);
+                }else{
+                    label.push(name[0]+"("+name[name.length-1]+")");
+                }
+                if (item.type === 'product'){
+                    bodyService.push(0);
+                    bodyProducto.push(item.qty);
+                }
+                if (item.type === 'service'){
+                    bodyService.push(item.qty);
+                    bodyProducto.push(0);
+                }
+            }
+
+            var chart = new Chart(this.$el.find(".widget-content").find('canvas'), {
+                type: 'line',
+                data: {
+                    labels: label,
+                    datasets: [
+                        {
+                            label: 'Productos ',
+                            borderWidth: 2,
+                            backgroundColor: '#e3f2fd',
+                            borderColor: '#64b5f6',
+                            data: bodyProducto,
+                            fill: false,
+                        },
+                        {
+                            label: 'Servicios ',
+                            borderWidth: 2,
+                            backgroundColor: '#c8e6c9',
+                            borderColor: '#66bb6a',
+                            borderDash: [5, 5],
+                            data: bodyService,
+                            fill: false,
+                        }
+                    ]
+                },
+                options: {
+                    responsive: true,
+                    hover: {
+                        mode: 'nearest',
+                        intersect: true
+                    },
+                    layout: {
+                        padding: {
+                            top: 20,
+                            bottom: 0,
+                            left: 0,
+                            rigth: 0,
+                        }
+                    },
+                }
+            });
+        },
+        showCustomers: function (e) {
+            var self = this;
+            if (self.ranking.length === 0){
+                model.web.notification.do_warn("Atención","Sin datos");
+                return
+            }
+            var hoy = moment().format('YYYY-MM-DD');
+
+            var product_id = _.map(self.ranking,function(map){
+                return map.id;
+            })
+            this.do_action({
+                name:"Listado de productos más vendidos",
+                type: 'ir.actions.act_window',
+                res_model: "product.product",
+                views: [[false, 'list'],[self.modelId[1],'form']],
+                target: 'current',
+                domain: [['id', 'in', product_id]],
+                context: {},
+            });
+        }
+    });
+}

+ 237 - 0
static/src/js/widgets/ranking_pos_orders_salesman.js

@@ -0,0 +1,237 @@
+function ranking_pos_orders_salesman (widget) {
+    "use strict";
+
+    var model = openerp;
+
+    widget.RankingPosOrdersSalesmanWidget = widget.Base.extend({
+        template: 'RankingPosOrdersSalesman',
+        data: [],
+        countPosOrder: [],
+        resPartner: [],
+        modelId: [],
+
+        events: {
+            // 'click canvas': 'showCustomers'
+        },
+        init: function (parent) {
+            this._super(parent, {
+                width: 6,
+                height: 4
+            });
+        },
+        start: function () {
+            var self = this;
+            self.fetchInitial();
+        },
+        fetchInitial:function() {
+            var self = this;
+            self.$el.block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+
+            self.$el.find('.widget-content.widget-loading').css('display','flex');
+
+            self.fecthPosOrder().then(function (PosOrder) {
+                return PosOrder;
+            }).then(function (PosOrder) {
+                self.PosOrder = PosOrder;
+                return self.fecthResUser();
+            }).then(function (ResUser) {
+                self.ResUser = ResUser;
+                return self.fetchGetModelId();
+            }).then(function(modelId) {
+                self.modelId = modelId;
+                return self.fetchProductRanking();
+            });
+        },
+        // getModelId
+        fetchGetModelId: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var irModelData = new model.web.Model('ir.model.data');
+            var getObtjectReference = irModelData.get_func('get_object_reference');
+
+            this.alive(getObtjectReference('base', 'view_partner_form')).then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Obtener Pedidos
+        fecthPosOrder: function() {
+            var self = this;
+            var desde = moment().format('YYYY-MM-01 00:00:00');
+            var hasta = moment().add(1,'months').format('YYYY-MM-01 00:00:00');
+            var defer = $.Deferred();
+            var fields = ['id','date_order','partner_id','amount_total','user_id'];
+            var domain = [['state', 'in', ['paid','done','invoiced']], ['partner_id', '!=', false], ['date_order', '>=', desde], ['date_order', '<', hasta]];
+            var PosOrder = new model.web.Model('pos.order');
+            PosOrder.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Consultar Clientes
+        fecthResUser: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var user_ids = _.map(self.PosOrder,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;
+        },
+        // Obtener facturas por cada clientes
+        getPosOrder:function(partner_id) {
+            var self = this;
+            return _.flatten(_.filter(self.PosOrder,function (inv) {
+                return inv.user_id[0] === partner_id;
+            }));
+        },
+        // Generar el Ranking
+        fetchProductRanking: function() {
+            var self = this;
+            var itemPartner;
+            var itemPosOrder;
+            var countPosOrder = 0
+            var ranking = [];
+
+            for (var i = 0; i < self.ResUser.length; i++) {
+                itemPartner = self.ResUser[i];
+                itemPosOrder = self.getPosOrder(itemPartner.id);
+
+                var quantity = _.reduce(_.map(itemPosOrder,function(item) {
+                    return item.amount_total;
+                }),function(memo, num) {
+                    return memo + num;
+                },0);
+
+                ranking.push({
+                    id: itemPartner.id,
+                    name: itemPartner.name,
+                    countPosOrder: quantity
+                });
+            }
+            ranking.sort(function (a, b) {
+                return b.countPosOrder - a.countPosOrder
+            });
+            self.ranking = ranking;
+
+            self.$el.unblock();
+            self.$el.find('.widget-content.widget-loading').css('display','none');
+            self.$el.find('.widget-title').find('span').text("Ventas por Vendedor");
+            self.fetchChart(ranking);
+        },
+        // Generar Grafico
+        fetchChart: function (ranking) {
+            var self = this;
+            var label = [];
+            var body = [];
+            var item;
+            var rank = 5;
+
+            if (ranking.length < rank && ranking.length > 0 )
+                rank= ranking.length;
+
+            for (var i = 0; i < rank; i++) {
+                if (ranking[i]) {
+                    item = ranking[i];
+                }
+                if (ranking.length === 0) {
+                    item = {};
+                    item.name = "N/A";
+                    item.countPosOrder = 0;
+                }
+                label.push(item.name);
+                body.push(item.countPosOrder);
+            }
+            // console.log(body);
+            // Global method for setting Y axis number format.
+            Chart.scaleService.updateScaleDefaults('linear', {
+              ticks: {
+                callback: function(tick) {
+                    return tick.toLocaleString('de-DE');
+                }
+              }
+            });
+            Chart.defaults.global.tooltips.callbacks.label = function(tooltipItem, data) {
+                var dataset = data.datasets[tooltipItem.datasetIndex];
+                var datasetLabel = dataset.label || '';
+                return datasetLabel +  dataset.data[tooltipItem.index].toLocaleString('de-DE');
+            };
+            var chart = new Chart(this.$el.find(".widget-content").find('canvas'), {
+                type: 'horizontalBar',
+                data: {
+                    labels: label,
+                    datasets: [
+                        {
+                            label: 'Ventas  ',
+                            backgroundColor: '#e3f2fd',
+                            borderColor: '#64b5f6',
+                            hoverBackgroundColor: '#c8e6c9',
+                            hoverBorderColor: '#66bb6a',
+                            borderWidth: 2,
+                            data: body,
+                        }
+                    ]
+                },
+                options: {
+                    responsive: true,
+                    // title: {
+                    //     display: false,
+                    // },
+                    hover: {
+                        mode: 'nearest',
+                        intersect: true
+                    },
+                   // scales: {
+                   //     xAxes: [{ stacked: true }],
+                   //     yAxes: [{ stacked: true }],
+                   // },
+                   // legend: {
+                   //     display: false,
+                   // },
+                    layout: {
+                        padding: {
+                            top: 20,
+                            bottom: 0,
+                            left : 0,
+                            rigth: 0,
+                        }
+                    },
+                }
+            });
+        },
+        // llamar a la lista
+        // showCustomers: function (e) {
+        //     var self = this;
+        //     if (self.ranking.length === 0 ) {
+        //         model.web.notification.do_warn("Atención","Sin datos");
+        //         return
+        //     }
+        //     var hoy = moment().format('YYYY-MM-DD');
+        //     var partner_id = _.map(self.ranking,function(map){
+        //         return map.id;
+        //     })
+        //     this.do_action({
+        //         name: "Listado de clientes con más compras",
+        //         type: 'ir.actions.act_window',
+        //         res_model: "res.partner",
+        //         views: [[false,'list'],[self.modelId[1],'form']],
+        //         target: 'current',
+        //         domain: [['id', 'in', partner_id]],
+        //         context: {},
+        //     });
+        // }
+    });
+}

+ 222 - 0
static/src/js/widgets/ranking_sales_partner.js

@@ -0,0 +1,222 @@
+function ranking_sales_partner (widget) {
+    "use strict";
+
+    var model = openerp;
+
+    widget.RankingSalesPartnerWidget = widget.Base.extend({
+        template: 'RankingSalesPartner',
+        data: [],
+        accountInvoice: [],
+        resPartner: [],
+        modelId: [],
+
+        events: {
+            'click canvas': 'showCustomers'
+        },
+        init: function (parent) {
+            this._super(parent, {
+                width: 6,
+                height: 4
+            });
+        },
+        start: function () {
+            var self = this;
+            self.fetchInitial();
+        },
+        fetchInitial:function() {
+            var self = this;
+            self.$el.block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+
+            self.$el.find('.widget-content.widget-loading').css('display','flex');
+
+            self.fecthInvoice().then(function (accountInvoice) {
+                return accountInvoice;
+            }).then(function (accountInvoice) {
+                self.accountInvoice = accountInvoice;
+                return self.fecthPartner(accountInvoice);
+            }).then(function (resPartner) {
+                self.resPartner = resPartner;
+                return self.fetchGetModelId();
+            }).then(function(modelId) {
+                self.modelId = modelId;
+                return self.fetchProductRanking();
+            });
+        },
+        // getModelId
+        fetchGetModelId: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var irModelData = new model.web.Model('ir.model.data');
+            var getObtjectReference = irModelData.get_func('get_object_reference');
+
+            this.alive(getObtjectReference('base', 'view_partner_form')).then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Obtener factura
+        fecthInvoice: function() {
+            var self = this;
+            var desde = moment().format('YYYY-MM-01');
+            var hasta = moment().add(1,'months').format('YYYY-MM-01');
+            var defer = $.Deferred();
+            var fields = ['id', 'invoice_line', 'date_invoice','partner_id','amount_total'];
+            var domain = [['type', '=', 'out_invoice'], ['date_invoice', '>=', desde], ['date_invoice', '<', hasta], ['state', 'in', ['open','paid']]];
+            var invoice = new model.web.Model('account.invoice');
+            invoice.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Partner
+        fecthPartner: function(invoice) {
+            var self = this;
+            var defer = $.Deferred();
+            var partner_id = _.map(invoice,function(map){
+                return map.partner_id[0];
+            });
+            var fields = ['id', 'name'];
+            var domain = [['id', 'in', partner_id],['active', '=', true],['customer','=',true]];
+            var resPartner = new model.web.Model('res.partner');
+            resPartner.query(fields).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Obtener facturas por cada clientes
+        getAccountInvoice:function(id_partner) {
+            var self = this;
+            return _.flatten(_.filter(self.accountInvoice,function (inv) {
+                return inv.partner_id[0] === id_partner;
+            }));
+        },
+        fetchProductRanking: function() {
+            var self = this;
+            var itemPartner;
+            var itemInvoice;
+            var countInvoice = 0
+            var ranking = [];
+
+            for (var i = 0; i < self.resPartner.length; i++) {
+                itemPartner = self.resPartner[i];
+                itemInvoice = self.getAccountInvoice(itemPartner.id);
+
+                var quantity = _.reduce(_.map(itemInvoice,function(item) {
+                    return item.amount_total;
+                }),function(memo, num) {
+                    return memo + num;
+                },0);
+
+                ranking.push({
+                    id: itemPartner.id,
+                    name: itemPartner.name,
+                    countInvoice: quantity
+                });
+            }
+            ranking.sort(function (a, b) {
+                return b.countInvoice - a.countInvoice
+            });
+            self.ranking = ranking;
+
+            self.$el.unblock();
+            self.$el.find('.widget-content.widget-loading').css('display','none');
+            self.$el.find('.widget-title').find('span').text("Ranking de clientes con más compras en el mes");
+            self.fetchChart(ranking);
+        },
+        // Generar Grafico
+        fetchChart: function (ranking) {
+            var self = this;
+            var label = [];
+            var body = [];
+            var item;
+            var rank = 5;
+
+            if (ranking.length < rank && ranking.length > 0 )
+                rank= ranking.length;
+
+            for (var i = 0; i < rank; i++) {
+                if (ranking[i]) {
+                    item = ranking[i];
+                }
+                if (ranking.length === 0) {
+                    item = {};
+                    item.name = "N/A";
+                    item.countInvoice = 0;
+                }
+                label.push(item.name);
+                body.push(item.countInvoice);
+            }
+            // Global method for setting Y axis number format.
+            Chart.scaleService.updateScaleDefaults('linear', {
+              ticks: {
+                callback: function(tick) {
+                    return tick.toLocaleString('de-DE');
+                }
+              }
+            });
+            Chart.defaults.global.tooltips.callbacks.label = function(tooltipItem, data) {
+                var dataset = data.datasets[tooltipItem.datasetIndex];
+                var datasetLabel = dataset.label || '';
+                return datasetLabel +  dataset.data[tooltipItem.index].toLocaleString('de-DE');
+            };
+            var chart = new Chart(this.$el.find(".widget-content").find('canvas'), {
+                type: 'bar',
+                data: {
+                    labels: label,
+                    datasets: [
+                        {
+                            backgroundColor: ['#EF5350', '#F06292', '#AB47BC', '#7E57C2', '#5C6BC0', '#42A5F5', '#26C6DA', '#26A69A', '#66BB6A', '#9CCC65'],
+                            data: body,
+                        }
+                    ]
+                },
+                options: {
+                   scales: {
+                       xAxes: [{ stacked: true }],
+                       yAxes: [{ stacked: true }],
+                   },
+                   legend: {
+                       display: false,
+                   },
+                    layout: {
+                        padding: {
+                            top: 20,
+                            bottom: 0,
+                            left : 0,
+                            rigth: 0,
+                        }
+                    },
+                }
+            });
+        },
+        // llamar a la lista
+        showCustomers: function (e) {
+            var self = this;
+            if (self.ranking.length === 0 ) {
+                model.web.notification.do_warn("Atención","Sin datos");
+                return
+            }
+            var hoy = moment().format('YYYY-MM-DD');
+            var partner_id = _.map(self.ranking,function(map){
+                return map.id;
+            })
+            this.do_action({
+                name: "Listado de clientes con más compras",
+                type: 'ir.actions.act_window',
+                res_model: "res.partner",
+                views: [[false,'list'],[self.modelId[1],'form']],
+                target: 'current',
+                domain: [['id', 'in', partner_id]],
+                context: {},
+            });
+        }
+    });
+}

+ 276 - 0
static/src/js/widgets/ranking_sales_product.js

@@ -0,0 +1,276 @@
+function ranking_sales_product (widget) {
+    "use strict";
+
+    var model = openerp;
+
+    widget.RankingSalesProductWidget = widget.Base.extend({
+        template: 'RankingSalesProductTmpl',
+        data: [],
+        accountInvoice: [],
+        invoiceLine: [],
+        productProduct: [],
+        ranking: [],
+        modelId: [],
+
+        events: {
+            // 'click canvas': 'showCustomers'
+            'click h2': 'showCustomers'
+        },
+        init: function (parent) {
+            this._super(parent, {
+                width: 6,
+                height: 4
+            });
+        },
+        start: function () {
+            var self = this;
+            self.fetchInitial();
+        },
+        fetchInitial: function() {
+            var self = this;
+            self.$el.block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+            self.$el.find('.widget-content.widget-loading').css('display','flex');
+
+            self.fecthInvoice().then(function (accountInvoice) {
+                return accountInvoice;
+            }).then(function (accountInvoice) {
+                self.accountInvoice = accountInvoice;
+                return self.fecthInvoiceLine(accountInvoice);
+            }).then(function (invoiceLine) {
+                self.invoiceLine = invoiceLine;
+                return self.fecthProductProduct(invoiceLine);
+            }).then(function(productProduct){
+                self.productProduct = productProduct;
+                return self.fetchGetModelId();
+            }).then(function(modelId){
+                self.modelId = modelId;
+                return self.fetchProductRanking();
+            });
+        },
+        // getModelId
+        fetchGetModelId: function() {
+            var self = this;
+            var defer = $.Deferred();
+            var irModelData = new model.web.Model('ir.model.data');
+            var getObtjectReference = irModelData.get_func('get_object_reference');
+
+            this.alive(getObtjectReference('product', 'product_normal_form_view')).then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Obtener factura
+        fecthInvoice: function() {
+            var self = this;
+            var desde = moment().format('YYYY-MM-01');
+            var hasta = moment().add(1,'months').format('YYYY-MM-01');
+            var defer = $.Deferred();
+            var fields = ['id', 'invoice_line', 'date_invoice'];
+            var domain = [['type', '=', 'out_invoice'], ['date_invoice', '>=', desde], ['date_invoice', '<', hasta], ['state', 'in', ['open','paid']]];
+            var invoice = new model.web.Model('account.invoice');
+            invoice.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Obtener linea de la factura
+        fecthInvoiceLine: function(accountInvoice) {
+            var self = this;
+            var defer = $.Deferred();
+            var invoice_line = _.flatten(_.map(accountInvoice, function (item) {
+                return item.invoice_line;
+            }));
+            var fields = ['id', 'product_id', 'quantity'];
+            var domain = [['id','in', invoice_line]];
+            var invoiceLine = new model.web.Model('account.invoice.line');
+            invoiceLine.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Obtener Prodcutos
+        fecthProductProduct: function (invoiceLine) {
+            var self = this;
+            var defer = $.Deferred();
+            var product_id = _.flatten(_.map(invoiceLine,function (item) {
+                return item.product_id[0];
+            }));
+            var fields = ['id', 'name_template', 'type'];
+            var domain = [['id', 'in', product_id]];
+            var product = new model.web.Model('product.product');
+
+            product.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        fetchProductRanking: function() {
+            var self = this;
+            var itemProduct;
+            var itemLine;
+            var ranking = [];
+            var cat = 0;
+            var lineUnik;
+            for (var i = 0; i < self.productProduct.length; i++) {
+                itemProduct = self.productProduct[i];
+                itemLine = self.getInvoiceLine(itemProduct.id);
+
+                // if (itemProduct.type === 'product') {
+                if (itemLine.length > 0) {
+                    cat = _.reduce(_.map(itemLine, function (map) {
+                        return map.quantity
+                    }), function (meno,num) {
+                        return meno + num
+                    }, 0);
+
+                    lineUnik = itemLine.shift();
+
+                    ranking.push({
+                        product: itemProduct.name_template,
+                        qty: cat,
+                        id: lineUnik.product_id[0],
+                        type: itemProduct.type
+                    });
+                }
+                // }
+            }
+            ranking.sort(function(a, b) {
+                return b.qty - a.qty
+            });
+
+            self.$el.unblock();
+            self.$el.find('.widget-content.widget-loading').css('display','none');
+            var fecha = new Date();
+            var meses = new Array ("Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre");
+
+            self.$el.find('.widget-title').find('span').text("Ranking de productos y servicios del mes de " + meses[fecha.getMonth()]);
+            // self.$el.find('.widget-title').find('span').text("Ranking de productos más vendidos del mes de " + meses[fecha.getMonth()]);
+            self.ranking = ranking;
+            self.fetchChart(ranking);
+        },
+        // get line
+        getInvoiceLine: function (product_id) {
+            var self = this;
+            return _.flatten(_.filter(self.invoiceLine,function (line) {
+                return line.product_id[0] === product_id
+            }));
+        },
+        // Generar Grafico
+        fetchChart: function (ranking){
+            var self = this;
+            var label = [];
+            var bodyProducto = [];
+            var labelService = [];
+            var bodyService = [];
+            var rank = 7;
+            var item;
+
+            // if (ranking.length < rank && ranking.length > 0)
+            //     rank= ranking.length;
+
+            for (var i = 0; i < rank; i++) {
+                if (ranking[i]){
+                    item = ranking[i];
+                }else{
+                    item = {};
+                    item.product = "N/A";
+                    item.qty = 0;
+                }
+                // if (ranking.length === 0){
+                    // item = {};
+                    // item.product = "N/A";
+                    // item.qty = 0;
+                // }
+                var name = item.product.split(' ');
+
+                if (name.length === 1) {
+                        label.push(name[0]);
+                }else{
+                    label.push(name[0]+"("+name[name.length-1]+")");
+                }
+                if (item.type === 'product'){
+                    bodyService.push(0);
+                    bodyProducto.push(item.qty);
+                }
+                if (item.type === 'service'){
+                    bodyService.push(item.qty);
+                    bodyProducto.push(0);
+                }
+            }
+
+            var chart = new Chart(this.$el.find(".widget-content").find('canvas'), {
+                // type: 'line',
+                type: 'bar',
+                data: {
+                    labels: label,
+                    datasets: [
+                        {
+                            label: 'Productos ',
+                             borderWidth: 1,
+                            backgroundColor: [  '#EF5350', '#EC407A', '#AB47BC', '#7E57C2', '#5C6BC0', '#42A5F5', '#26C6DA', '#26A69A', '#66BB6A', '#9CCC65'],
+                            data: bodyProducto,
+                        },
+                        {
+                            label: 'Servicios ',
+                             borderWidth: 1,
+                            backgroundColor: [  '#EF5350', '#EC407A', '#AB47BC', '#7E57C2', '#5C6BC0', '#42A5F5', '#26C6DA', '#26A69A', '#66BB6A', '#9CCC65'],
+                            data: bodyService,
+                        }
+                    ]
+                },
+                options: {
+                    tooltips: {
+                       mode: 'index',
+                       intersect: true
+                   },
+                   legend: {
+                       labels: {
+                           boxWidth: 10,
+                           fontSize: 12,
+                       },
+                       position: 'left',
+                   },
+                    layout: {
+                        padding: {
+                            top: 20,
+                            bottom: 0,
+                            left: 0,
+                            rigth: 0,
+                        }
+                    },
+                }
+            });
+        },
+
+        showCustomers: function (e) {
+            var self = this;
+            if (self.ranking.length === 0){
+                model.web.notification.do_warn("Atención","Sin datos");
+                return
+            }
+            var hoy = moment().format('YYYY-MM-DD');
+
+            var product_id = _.map(self.ranking,function(map){
+                return map.id;
+            })
+            this.do_action({
+                name:"Listado de productos más vendidos",
+                type: 'ir.actions.act_window',
+                res_model: "product.product",
+                views: [[false, 'list'],[self.modelId[1],'form']],
+                target: 'current',
+                domain: [['id', 'in', product_id]],
+                context: {},
+            });
+        }
+    });
+}

+ 168 - 0
static/src/js/widgets/voucher_today_counters.js

@@ -0,0 +1,168 @@
+function voucher_today_counters (widget) {
+    "use strict";
+
+    var model = openerp;
+
+    widget.VoucherTodayCountersWidget = widget.Base.extend({
+        template: 'VoucherTodayCounters',
+        accountVoucher: [],
+        resCompany: [],
+        resCurrecy: [],
+
+        events: {
+            'click a': 'showCustomers',
+            'click h2': 'showCustomers',
+        },
+
+        init: function (parent) {
+            this._super(parent, {
+                width: 3,
+                height: 2
+            });
+        },
+
+        start: function () {
+            var self = this;
+            self.fetchInitial();
+        },
+
+        fetchInitial: function () {
+            var self = this;
+            self.$el.find('#morosidad').block({
+                message: null,
+                overlayCSS: {
+                    backgroundColor: '#FAFAFA'
+                }
+            });
+            self.$el.find('.widget-content.widget-loading').css('display','flex');
+
+            self.fetchAccountVoucher().then(function (accountVoucher) {
+                return accountVoucher;
+            }).then(function (accountVoucher) {
+                self.accountVoucher = accountVoucher;
+                return self.fetchResCompany();
+            }).then(function (resCompany) {
+                self.resCompany = resCompany;
+                return self.fetchResCurrecy();
+            }).then(function(resCurrecy) {
+                self.resCurrecy = resCurrecy;
+                return self.fetchVoucherCurrency();
+            });
+        },
+        // Account Voucher
+        fetchAccountVoucher: function () {
+            var self = this;
+            var defer = $.Deferred();
+            var hoy = moment().format('YYYY-MM-DD');
+            var fields = ['id', 'amount', 'currency_id', 'payment_rate_currency_id'];
+            var domain = [['state', '=', 'posted'], ['type', '=', 'receipt'], ['date', '=', hoy]];
+            var accountVoucher = new model.web.Model('account.voucher');
+
+            accountVoucher.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        //Comapnia
+        fetchResCompany: function () {
+            var self = this;
+            var defer = $.Deferred();
+            var fields = ['id','name', 'currency_id','logo'];
+            var domain = [['id', '=', 1]];
+            var resCompany = new model.web.Model('res.company');
+
+            resCompany.query(fields).filter(domain).all().then(function (results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        // Res currecy
+        fetchResCurrecy : 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 resCurrecy = new model.web.Model('res.currency');
+
+            resCurrecy.query(fields).filter(domain).all().then(function(results) {
+                defer.resolve(results);
+            });
+
+            return defer;
+        },
+        //   voucherCurrencyRate
+        fetchVoucherCurrency: function () {
+            var self = this;
+            var newVoucher = [];
+            var itemVoucher;
+            var currencyVoucher;
+            var residual = 0;
+            var company = self.resCompany.shift()
+            var currencyBase = self.getCutrrency(company.currency_id[0]).shift();
+
+            for (var i = 0; i < self.accountVoucher.length; i++) {
+                itemVoucher = self.accountVoucher[i];
+
+                currencyVoucher = self.getCutrrency(itemVoucher.payment_rate_currency_id[0]).shift();
+                if(!currencyVoucher) {
+                    currencyVoucher = {};
+                    currencyVoucher.rate_silent = currencyBase.rate_silent;
+                }
+
+                newVoucher.push({
+                    amount: itemVoucher.amount,
+                    amount_rate: (itemVoucher.amount * (currencyBase.rate_silent / currencyVoucher.rate_silent))
+                });
+            }
+
+            if (newVoucher.length > 0) {
+                residual = _.reduce(_.map(newVoucher, function (map) {
+                    return map.amount_rate;
+                }), function (memo, num) {
+                    return memo + num;
+                });
+            }
+
+            self.$el.find('.widget-content.widget-loading').css('display','none');
+            self.$el.find('.widget-content').find('a').text(accounting.formatMoney(residual, currencyBase.symbol, currencyBase.decimal_places, currencyBase.thousands_separator, currencyBase.decimal_separator));
+            self.$el.find('#morosidad').unblock();
+        },
+        // Obtener la moneda
+        getCutrrency: function (id) {
+            var self = this;
+            return _.filter(self.resCurrecy,function (item) {
+                return item.id === id;
+            });
+        },
+        // modal
+        showCustomers: function (e) {
+            var self = this;
+            if (self.accountVoucher.length === 0) {
+                model.web.notification.do_warn("Atención","Sin datos");
+                return
+            }
+
+            var hoy =moment().format('YYYY-MM-DD');
+
+            this.do_action({
+                name: "Listado de cobros realizado en el día",
+                type: 'ir.actions.act_window',
+                res_model: "account.voucher",
+                views: [[false, 'list'],[false,'form']],
+                target: 'new',
+                domain: [['state', '=', 'posted'], ['type', '=', 'receipt'], ['date', '=', hoy]],
+                context: {},
+                flags: {
+                    'form': {
+                        'action_buttons': false,
+                        'options': {
+                            'mode': 'view'
+                        }
+                    }
+                },
+            });
+        }
+    });
+}

+ 29 - 0
static/src/lib/jquery.timeago.es.js

@@ -0,0 +1,29 @@
+(function (factory) {
+  if (typeof define === 'function' && define.amd) {
+    define(['jquery'], factory);
+  } else if (typeof module === 'object' && typeof module.exports === 'object') {
+    factory(require('jquery'));
+  } else {
+    factory(jQuery);
+  }
+}(function (jQuery) {
+  // Spanish
+  jQuery.timeago.settings.strings = {
+     prefixAgo: "hace",
+     prefixFromNow: "dentro de",
+     suffixAgo: "",
+     suffixFromNow: "",
+     seconds: "menos de un minuto",
+     minute: "un minuto",
+     minutes: "unos %d minutos",
+     hour: "una hora",
+     hours: "%d horas",
+     day: "un día",
+     days: "%d días",
+     month: "un mes",
+     months: "%d meses",
+     year: "un año",
+     years: "%d años"
+  };
+}));
+

+ 57 - 0
static/src/xml/configuration.xml

@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="ConfigurationTmpl">
+        <div class="configuration_container">
+            <div class="oe_horizontal_separator">
+                Configuración del Tablero
+            </div>
+            <div class="configuration_dashboard">
+                <div>
+                    <div>
+                        <div class="user_selectable_area"></div>
+                    </div>
+                    <div>
+                        <div class="widgets_droppable_area">
+                            <div class="grid-stack grid-stack-4"></div>
+                        </div>
+                    </div>
+                    <div>
+                        <div class="widgets_draggable_area vertical_scrollable"></div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </t>
+
+    <t t-name="ConfigurationUsersTmpl">
+        <t t-foreach="users" t-as="user">
+            <div class="user_wrapper" t-att-data-id="user.id">
+                <div class="user_photo">
+                    <img src="/eiru_dashboard/static/img/user.png" />
+                </div>
+                <h2><t t-esc="user.name"/></h2>
+            </div>
+        </t>
+    </t>
+
+    <t t-name="ConfigurationWidgetsTmpl">
+        <input type="text" placeholder="Buscar..." />
+        <div class="grid-stack grid-stack-1">
+            <t t-foreach="widgets" t-as="widget">
+                <div class="grid-stack-item" t-att-data-id="widget.id" data-gs-width="1" data-gs-height="1">
+                    <div class="grid-stack-item-content widget_wrapper">
+                        <h2><t t-esc="widget.name" /></h2>
+                        <p><t t-esc="widget.description" /></p>
+                        <div class="widget_action widget_add" data-action="add">
+                            <i class="fa fa-plus"></i>
+                        </div>
+                        <div class="widget_action widget_trash" data-action="remove">
+                            <i class="fa fa-trash"></i>
+                        </div>
+                    </div>
+                </div>
+            </t>
+        </div>
+    </t>
+</template>

+ 9 - 0
static/src/xml/dashboard.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="DashboardTmpl">
+        <div class="container">
+            <div class="grid-stack dashboard"></div>
+        </div>
+    </t>
+</template>

+ 11 - 0
static/src/xml/widget_base.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="WidgetBaseTmpl">
+        <div>
+            <div class="grid-stack-item-content dashboard">
+                <t t-raw="0" />
+            </div>
+        </div>
+    </t>
+</template>

+ 60 - 0
static/src/xml/widgets/eiru_dashboard_modal.xml

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<template xml:space="preserve">
+    <t t-name="ExpiredAccountCountersModal">
+        <div class="modal in expired-account-modal" tabindex="-1" role="dialog">
+            <div class="modal-dialog modal-lg" role="document">
+                <div class="modal-content openerp">
+                    <!-- title  -->
+                    <div class="modal-header">
+                        <button type="button" class="close" data-dismiss="modal" aria-label="Close" aria-hidden="true">x</button>
+                        <h3 class="modal-title" t-foreach="modalTitle" t-as="title">
+                            <t t-esc="title_value.title"/>
+                        </h3>
+                    </div>
+                    <div class="oe_view_manager_body table-model">
+                        <!-- tabla Head -->
+                        <div class="modal-head-wrapper">
+                            <table class="oe_list_content">
+                                <thead >
+                                    <tr class="oe_list_header_columns" >
+                                        <th t-foreach="dataThead" t-as="head" class="oe_list_header_char oe_sortable">
+                                            <t t-esc="head_value.title"/>
+                                        </th>
+                                    </tr>
+                                </thead>
+                            </table>
+                        </div>
+                        <!-- table body -->
+                        <div class="modal-items-wrapper">
+                            <table class="oe_list_content">
+                                <tbody class="table-tbody">
+                                    <tr t-foreach="data" t-as="field">
+                                        <td><t t-esc="field_value.invoice[0]"/></td>
+                                        <td><t t-esc="field_value.partner_id[1]"/></td>
+                                        <td><t t-esc="field_value.ref"/></td>
+                                        <td>
+                                            <t t-set="vencimiento" t-value="field_value.date_maturity"/>
+                                            <t t-js="ctx">
+                                                ctx.vencimiento = $.timeago(moment(ctx.vencimiento).format("YYYY-DD-MM"));
+                                            </t>
+                                            <t t-esc="vencimiento"/></td>
+                                        <td>
+                                            <t t-set="monto" t-value="field_value.amount_residual"/>
+                                            <t t-js="ctx">
+                                                ctx.monto = accounting.formatNumber(ctx.monto,0,'.',',');
+                                            </t>
+                                            <t t-esc="monto"/>
+                                        </td>
+                                    </tr>
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                    <div class="modal-footer">
+                        <button type="button" class="btn btn-default " data-dismiss="modal">Cerrar</button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </t>
+</template>

+ 23 - 0
static/src/xml/widgets/expired_account_counters.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="ExpiredAccountCounters">
+        <div>
+            <div class="grid-stack-item-content dashboard">
+                <h2 class="widget-title">
+                    <i class="fa fa-money" aria-hidden="true"></i>
+                    Tenés por cobrar
+                </h2>
+                <div class="widget-content">
+                    <a></a>
+                </div>
+                <div class="widget-footer">
+                </div>
+                <div class="widget-content widget-loading">
+                    <i class='fa fa-cog fa-spin fa-3x fa-fw'></i>
+                </div>
+            </div>
+        </div>
+
+    </t>
+</template>

+ 23 - 0
static/src/xml/widgets/expired_account_counters_now.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="ExpiredAccountCountersNow">
+        <div>
+            <div class="grid-stack-item-content dashboard">
+                <h2 class="widget-title">
+                    <i class="fa fa-money" aria-hidden="true"> </i>
+                    Tenés por cobrar 
+                </h2>
+                <div  class="widget-content">
+                    <a></a>
+                </div>
+                <div class="widget-footer">
+                    <span>en el día de hoy</span>
+                </div>
+                <div class="widget-content widget-loading">
+                    <i class='fa fa-cog fa-spin fa-3x fa-fw'></i>
+                </div>
+            </div>
+        </div>
+    </t>
+</template>

+ 19 - 0
static/src/xml/widgets/invoice_history.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="InvoiceHistory">
+        <t t-call="WidgetBaseTmpl">
+            <h2  class="widget-title">
+                <i class="fa fa-bar-chart" aria-hidden="true"></i>
+                <span>Historico de facturas</span>
+            </h2>
+            <div class="widget-content">
+                <br/>
+                <canvas></canvas>
+            </div>
+            <div class="widget-content widget-loading">
+                <i class='fa fa-cog fa-spin fa-3x fa-fw'></i>
+            </div>
+        </t>
+    </t>
+</template>

+ 23 - 0
static/src/xml/widgets/invoice_today_counters.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="InvoiceTodayCounters">
+        <div>
+            <div class="grid-stack-item-content dashboard">
+                <h2 class="widget-title">
+                    <i class="fa fa-files-o" aria-hidden="true"></i>
+                    Has realizado hoy
+                </h2>
+                <div class="widget-content">
+                    <a></a>
+                </div>
+                <div class="widget-footer">
+                    <span>facturas</span>
+                </div>
+                <div class="widget-content widget-loading">
+                    <i class='fa fa-cog fa-spin fa-3x fa-fw'></i>
+                </div>
+            </div>
+        </div>
+    </t>
+</template>

+ 23 - 0
static/src/xml/widgets/missing_product.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="MissingProduct">
+        <div>
+            <div class="grid-stack-item-content dashboard">
+                <h2 class="widget-title">
+                    <i class="fa fa-list-alt" aria-hidden="true"></i>
+                    Tenés faltando
+                </h2>
+                <div class="widget-content">
+                    <a></a>
+                </div>
+                <div class="widget-footer">
+                    <span>productos</span>
+                </div>
+                <div class="widget-content widget-loading">
+                    <i class='fa fa-cog fa-spin fa-3x fa-fw'></i>
+                </div>
+            </div>
+        </div>
+    </t>
+</template>

+ 23 - 0
static/src/xml/widgets/monthly_expenses.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="MonthlyExpenses">
+        <div>
+            <div class="grid-stack-item-content dashboard">
+                <h2 class="widget-title">
+                    <i class="fa fa-money" aria-hidden="true"> </i>
+                    Has hecho este mes
+                </h2>
+                <div class="widget-content">
+                    <a></a>
+                </div>
+                <div class="widget-footer">
+                    <span>en gastos</span>
+                </div>
+                <div class="widget-content widget-loading">
+                    <i class='fa fa-cog fa-spin fa-3x fa-fw'></i>
+                </div>
+            </div>
+        </div>
+    </t>
+</template>

+ 23 - 0
static/src/xml/widgets/monthly_purchases.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="MonthlyPurchases">
+        <div>
+            <div class="grid-stack-item-content dashboard">
+                <h2 class="widget-title">
+                    <i class="fa fa-money" aria-hidden="true"> </i>
+                    Has hecho este mes 
+                </h2>
+                <div class="widget-content">
+                    <a></a>
+                </div>
+                <div class="widget-footer">
+                    <span>en compras</span>
+                </div>
+                <div class="widget-content widget-loading">
+                    <i class='fa fa-cog fa-spin fa-3x fa-fw'></i>
+                </div>
+            </div>
+        </div>
+    </t>
+</template>

+ 23 - 0
static/src/xml/widgets/payments_today_counters.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="PaymentsTodayCounters">
+        <div>
+            <div class="grid-stack-item-content dashboard">
+                <h2 class="widget-title">
+                    <i class="fa fa-money" aria-hidden="true"> </i>
+                    Has hecho hoy
+                </h2>
+                <div class="widget-content">
+                    <a></a>
+                </div>
+                <div class="widget-footer">
+                    <span>en pagos</span>
+                </div>
+                <div class="widget-content widget-loading">
+                    <i class='fa fa-cog fa-spin fa-3x fa-fw'></i>
+                </div>
+            </div>
+        </div>
+    </t>
+</template>

+ 23 - 0
static/src/xml/widgets/pos_order_today_counters.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="PosOrderTodayCounters">
+        <div>
+            <div class="grid-stack-item-content dashboard">
+                <h2 class="widget-title">
+                    <i class="fa fa-files-o" aria-hidden="true"></i>
+                    Has realizado hoy
+                </h2>
+                <div class="widget-content">
+                    <a></a>
+                </div>
+                <div class="widget-footer">
+                    <span>Pedidos</span>
+                </div>
+                <div class="widget-content widget-loading">
+                    <i class='fa fa-cog fa-spin fa-3x fa-fw'></i>
+                </div>
+            </div>
+        </div>
+    </t>
+</template>

+ 18 - 0
static/src/xml/widgets/ranking_pos_orders_partner.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="RankingPosOrdersPartner">
+        <t t-call="WidgetBaseTmpl">
+            <h2  class="widget-title">
+                <i class="fa fa-bar-chart" aria-hidden="true"></i>
+                <span>Ranking de clientes con más compras en el mes</span>
+            </h2>
+            <div class="widget-content">
+                <canvas></canvas>
+            </div>
+            <div class="widget-content widget-loading">
+                <i class='fa fa-cog fa-spin fa-3x fa-fw'></i>
+            </div>
+        </t>
+    </t>
+</template>

+ 17 - 0
static/src/xml/widgets/ranking_pos_orders_product.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<template xml:space="preserve">
+    <t t-name="RankingPosOrdersProduct">
+        <t t-call="WidgetBaseTmpl">
+            <h2  class="widget-title">
+                <i class="fa fa-bar-chart" aria-hidden="true"></i>
+                <span>Ranking de productos y servicios</span>
+            </h2>
+            <div class="widget-content">
+                <canvas></canvas>
+            </div>
+            <div class="widget-content widget-loading">
+                <i class='fa fa-cog fa-spin fa-3x fa-fw'></i>
+            </div>
+        </t>
+    </t>
+</template>

+ 18 - 0
static/src/xml/widgets/ranking_pos_orders_salesman.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="RankingPosOrdersSalesman">
+        <t t-call="WidgetBaseTmpl">
+            <h2  class="widget-title">
+                <i class="fa fa-bar-chart" aria-hidden="true"></i>
+                <span>Ranking de clientes con más compras en el mes</span>
+            </h2>
+            <div class="widget-content">
+                <canvas></canvas>
+            </div>
+            <div class="widget-content widget-loading">
+                <i class='fa fa-cog fa-spin fa-3x fa-fw'></i>
+            </div>
+        </t>
+    </t>
+</template>

+ 18 - 0
static/src/xml/widgets/ranking_sales_partner.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="RankingSalesPartner">
+        <t t-call="WidgetBaseTmpl">
+            <h2  class="widget-title">
+                <i class="fa fa-bar-chart" aria-hidden="true"></i>
+                <span>Ranking de clientes con más compras en el mes</span>
+            </h2>
+            <div class="widget-content">
+                <canvas></canvas>
+            </div>
+            <div class="widget-content widget-loading">
+                <i class='fa fa-cog fa-spin fa-3x fa-fw'></i>
+            </div>
+        </t>
+    </t>
+</template>

+ 19 - 0
static/src/xml/widgets/ranking_sales_product.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="RankingSalesProductTmpl">
+        <t t-call="WidgetBaseTmpl">
+            <h2  class="widget-title">
+                <i class="fa fa-bar-chart" aria-hidden="true"></i>
+                <!-- <span>Ranking de productos más vendidos</span> -->
+                <span>Ranking de productos y servicios</span>
+            </h2>
+            <div class="widget-content">
+                <canvas></canvas>
+            </div>
+            <div class="widget-content widget-loading">
+                <i class='fa fa-cog fa-spin fa-3x fa-fw'></i>
+            </div>
+        </t>
+    </t>
+</template>

+ 23 - 0
static/src/xml/widgets/voucher_today_counters.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="VoucherTodayCounters">
+        <div>
+            <div class="grid-stack-item-content dashboard">
+                <h2 class="widget-title">
+                    <i class="fa fa-money" aria-hidden="true"> </i>
+                    Has hecho hoy
+                </h2>
+                <div class="widget-content">
+                    <a></a>
+                </div>
+                <div class="widget-footer">
+                    <span>en cobros</span>
+                </div>
+                <div class="widget-content widget-loading">
+                    <i class='fa fa-cog fa-spin fa-3x fa-fw'></i>
+                </div>
+            </div>
+        </div>
+    </t>
+</template>

+ 45 - 0
templates.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+    <data>
+        <!-- Templates -->
+        <template id="eiru_reporting_dashboard_assets" inherit_id="eiru_assets.assets">
+            <xpath expr="." position="inside">
+                <!-- Dashboard Style -->
+                <link rel="stylesheet" href="/eiru_reporting_dashboard/static/src/css/dashboard.css" />
+                <link rel="stylesheet" href="/eiru_reporting_dashboard/static/src/css/configuration.css" />
+
+                <!-- Dashboard Widget Base -->
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widget_base.js" />
+                <!-- LIB -->
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/lib/jquery.timeago.es.js" />
+
+                <!-- Dashboard Widgets -->
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widgets/ranking_sales_product.js" />
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widgets/expired_account_counters.js" />
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widgets/expired_account_counters_now.js" />
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widgets/voucher_today_counters.js" />
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widgets/invoice_today_counters.js" />
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widgets/monthly_expenses.js" />
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widgets/monthly_purchases.js" />
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widgets/missing_product.js" />
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widgets/payments_today_counters.js" />
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widgets/ranking_sales_partner.js" />
+
+                <!-- Point Of Sale -->
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widgets/pos_order_today_counters.js" />
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widgets/ranking_pos_orders_partner.js" />
+                 <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widgets/ranking_pos_orders_product.js" />
+
+                <!-- Dashboard Main  -->
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/dashboard.js" />
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/configuration.js" />
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/main.js" />
+
+
+                <!-- new chart -->
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widgets/invoice_history.js" />
+                <script type="text/javascript" src="/eiru_reporting_dashboard/static/src/js/widgets/ranking_pos_orders_salesman.js" />
+            </xpath>
+        </template>
+    </data>
+</openerp>