Browse Source

[ADD] commit inicial

robert2206 7 năm trước cách đây
commit
677b07271c

+ 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_dashboard",
+    'author': "Your Company",
+    'website': "http://www.yourcompany.com",
+    'category': 'Uncategorized',
+    'version': '0.1',
+    'depends': ['base', 'sale', 'eiru_assets'],
+    '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);
+    }
+}

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

@@ -0,0 +1,61 @@
+.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;
+}
+
+.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;
+}

+ 145 - 0
static/src/css/sale.css

@@ -0,0 +1,145 @@
+.dashboard-sale-wrapper {
+    width: 100%;
+    height: 100%;
+    padding: 45px;
+    background: url(/web/static/src/img/form_sheetbg.png);
+}
+
+.dashboard-sale {
+    width: 100%;
+    height: 100%;
+    background: #f5f5f5;
+    box-shadow: 2px 2px 4px #d3d3d3, -2px -2px 4px #d3d3d3;
+    display: flex;
+}
+
+.dashboard-sale-actions {
+    width: 350px;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+}
+
+.dashboard-sale-buttons {
+    flex-grow: 1;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+}
+
+.dashboard-sale-buttons div {
+    width: 80px;
+    height: 80px;
+    margin: 10px 92px;
+    padding: 15px;
+    border-radius: 10% 50%;
+    background: #7c7bad;
+    display: flex;
+}
+
+.dashboard-sale-buttons div  i {
+    margin: auto;
+    font-size: 18pt;
+    color: #fff;
+}
+
+.dashboard-sale-buttons div::before {
+    content: "";
+    width: 0;
+    height: 40px;
+    border-radius: 0 5px 5px 0;
+    position: absolute;
+    margin-top: 5px;
+    margin-left: 55px;
+    text-align: center;
+    line-height: 38px;
+    font-size: 13px;
+    font-weight: bold;
+    color: #fff;
+    background: #7c7bad;
+    transition-duration: 0.2s;
+}
+
+.dashboard-sale-buttons div:hover {
+    cursor: pointer;
+    -webkit-cursor: pointer;
+    -moz-cursor: pointer;
+}
+
+.dashboard-sale-buttons .new-sale:hover::before {
+    content: "Nueva Venta";
+    width: 120px;
+}
+
+.dashboard-sale-buttons .new-budget:hover::before {
+    content: "Nuevo Presupuesto";
+    width: 150px;
+}
+
+.dashboard-sale-actions img {
+    width: 180px;
+    height: 180px;
+    margin: auto;
+    filter: hue-rotate(45deg);
+    animation: 3s handshaking 1;
+}
+
+.dashboard-sale-welcome {
+    width: 100%;
+    height: 100%;
+    padding-left: 65px;
+}
+
+.dashboard-sale-welcome h2 {
+    margin-top: 75px;
+    margin-bottom: 35px;
+    font-family: sans-serif;
+    font-size: 32pt;
+    color: #616161;
+}
+
+.dashboard-sale-welcome div {
+    width: calc(100% - 45px);
+    height: calc(100% - 200px);
+    background: #eeeeee;
+    box-shadow: inset 1px 1px 2px #d3d3d3, inset -1px -1px 2px #d3d3d3;
+    border-radius: 4px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.dashboard-sale-welcome div ul {
+    margin: 0;
+    padding: 0;
+    list-style-type: none;
+    font-family: sans-serif;
+    font-size: 14pt;
+    color: #757575;
+}
+
+.dashboard-sale-welcome div ul li {
+    margin: 10px 0;
+}
+
+.dashboard-sale-welcome div ul li i {
+    margin-right: 15px;
+    font-size: 16pt;
+    color: #7c7bad;
+}
+
+@keyframes handshaking {
+    0% {
+        transform: scale(1);
+    }
+    25% {
+        transform: scale(1.15);
+    }
+    50% {
+        transform: scale(1);
+    }
+    75% {
+        transform: scale(1.15);
+    }
+}

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

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

@@ -0,0 +1,50 @@
+function dashboard_widget (instance, widget) {
+    "use strict";
+
+    var widgets = widget;
+
+    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 () {
+            for (var i = 1; i <= 4; i++) {
+                var widget = new widgets.CustomerCounterWidget(this);
+                widget.renderElement();
+                // widget.start();
+
+                this.grid.addWidget(widget.$el, 0, 0, widget.getWidth(),  widget.getHeight(), true);
+            }
+
+            var w = new widgets.SalesInTheWeekWidget(this);
+            w.renderElement();
+            w.start();
+
+            this.grid.addWidget(w.$el, 0, 0, w.size.width,  w.size.height, true);
+
+            var w2 = new widgets.TopSalesProductWidget(this);
+            w2.renderElement();
+            w2.start();
+
+            this.grid.addWidget(w2.$el, 0, 0, w2.size.width,  w2.size.height, true);
+
+            var w3 = new widgets.SalesInWarehouseByBrandWidget(this);
+            w3.renderElement();
+            w3.start();
+
+            this.grid.addWidget(w3.$el, 0, 0, w3.size.width,  w3.size.height, true);
+        }
+    });
+}

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

@@ -0,0 +1,24 @@
+openerp.eiru_dashboard = function (instance) {
+    "use strict";
+
+    instance.eiru_dashboard = {};
+    instance.eiru_dashboard.reports = {};
+
+    var dashboard = instance.eiru_dashboard;
+
+    widget_base(instance, dashboard);
+    dashboard_widget(instance, dashboard);
+    sale_widget(instance, dashboard)
+    configuration_widget(instance, dashboard);
+
+    // Widgets
+    customer_counter(dashboard);
+    sales_in_the_week(dashboard);
+    top_sales_product(dashboard);
+    sales_in_warehouse_by_brand(dashboard);
+
+    // Action
+    instance.web.client_actions.add('eiru_dashboard.action_dashboard', 'instance.eiru_dashboard.DashboardWidget');
+    instance.web.client_actions.add('eiru_dashboard.action_dashboard_sale', 'instance.eiru_dashboard.SaleWidget');
+    instance.web.client_actions.add('eiru_dashboard.action_dashboard_configuration', 'instance.eiru_dashboard.DashboardConfigurationWidget');
+}

+ 36 - 0
static/src/js/sale.js

@@ -0,0 +1,36 @@
+function sale_widget(instance, widget) {
+    "use strict";
+
+    var QWeb = instance.web.qweb;
+
+    widget.SaleWidget = instance.Widget.extend({
+        template: 'WidgetSaleTmpl',
+        events: {
+            'click .new-sale': 'newSale',
+            'click .new-budget': 'newBudget'
+        },
+        init: function (parent) {
+            this._super(parent)
+        },
+        start: function () {
+        },
+        newSale: function (e) {
+            this.do_action({
+                type: 'ir.actions.act_window',
+                res_model: 'sale.order',
+                views: [[false, 'form']],
+                target: 'current',
+                context: {}
+            });
+        },
+        newBudget: function (e) {
+            this.do_action({
+                type: 'ir.actions.act_window',
+                res_model: 'sale.order',
+                views: [[false, 'form']],
+                target: 'current',
+                context: {}
+            });
+        }
+    })
+}

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

+ 40 - 0
static/src/js/widgets/customer_counter.js

@@ -0,0 +1,40 @@
+function customer_counter (widget) {
+    "use strict";
+
+    widget.CustomerCounterWidget = widget.Base.extend({
+        template: 'CustomerCounterTmpl',
+        events: {
+            'click a': 'showCustomers'
+        },
+        customers: [],
+        fields: ['name'],
+        domain: [['customer', '=', true], ['active', '=', true]],
+        init: function (parent) {
+            this._super(parent, { width: 3, height: 2 });
+        },
+        start: function () {
+            var self = this;
+            this.getCustomers().then(function (customers) {
+                self.customers = customers;
+                self.renderWidget();
+            });
+        },
+        getCustomers: function () {
+            var Customer = new instance.web.Model('res.partner');
+            return Customer.query(this.fields).filter(this.domain).order_by(['id']).all();
+        },
+        renderWidget: function () {
+            console.log(this.customers);
+        },
+        showCustomers: function (e) {
+            this.do_action({
+                type: 'ir.actions.act_window',
+                res_model: "res.partner",
+                views: [[false, 'list']],
+                target: 'new',
+                domain: [['customer', '=', true]],
+                context: {},
+            });
+        }
+    });
+}

+ 50 - 0
static/src/js/widgets/sales_in_the_week.js

@@ -0,0 +1,50 @@
+function sales_in_the_week (widget) {
+    "use strict";
+
+    widget.SalesInTheWeekWidget = widget.Base.extend({
+        template: 'SalesInTheWeekTmpl',
+        data: [],
+        init: function (parent) {
+            this._super(parent, {
+                width: 6,
+                height: 4
+            });
+        },
+        start: function () {
+            var chart = new Chart(this.$el.find('#sales-in-the-week'), {
+                type: 'line',
+                data: {
+                    labels: ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"],
+                    datasets: [
+                        {
+                            fill: false,
+                            lineTension: 0,
+                            backgroundColor: "#7c7bad",
+                            pointBorderColor: "#7c7bad",
+                            pointHoverRadius: 5,
+                            pointHoverBackgroundColor: "#7c7bad",
+                            pointHoverBorderColor: "rgba(220,220,220,1)",
+                            pointHoverBorderWidth: 2,
+                            pointRadius: 1,
+                            pointHitRadius: 10,
+                            data: [65, 59, 80, 81, 56, 55, 40],
+                        }
+                    ]
+                },
+                options: {
+                    maintainAspectRatio: false,
+                    layout: {
+                        padding: 20
+                    },
+                    legend: {
+                        display: false
+                    }
+                }
+            });
+        },
+        getSales: function () {
+            var Sale = new instance.web.Model('sale.order');
+            return Sale.query(['name']).order_by(['id']).all();
+        }
+    });
+}

+ 63 - 0
static/src/js/widgets/sales_in_warehouse_by_brand.js

@@ -0,0 +1,63 @@
+function sales_in_warehouse_by_brand (widget) {
+    "use strict";
+
+    widget.SalesInWarehouseByBrandWidget = widget.Base.extend({
+        template: 'SalesInWarehouseByBrandTmpl',
+        data: [],
+        init: function (parent) {
+            this._super(parent, {
+                width: 6,
+                height: 6
+            });
+        },
+        start: function () {
+            var chart = new Chart(this.$el.find('#sales-in-warehouse-by-brand'), {
+                type: 'radar',
+                data: {
+                    labels: ["Marca 1", "Marca 2", "Marca 3", "Marca 4", "Marca 5", "Marca 6", "Marca 7"],
+                    datasets: [
+                        {
+                            label: "Almacén 1",
+                            backgroundColor: "rgba(179,181,198,0.2)",
+                            borderColor: "rgba(179,181,198,1)",
+                            pointBackgroundColor: "rgba(179,181,198,1)",
+                            pointBorderColor: "#fff",
+                            pointHoverBackgroundColor: "#fff",
+                            pointHoverBorderColor: "rgba(179,181,198,1)",
+                            data: [65, 59, 90, 81, 56, 55, 40]
+                        },
+                        {
+                            label: "Almacén 2",
+                            backgroundColor: "rgba(255,99,132,0.2)",
+                            borderColor: "rgba(255,99,132,1)",
+                            pointBackgroundColor: "rgba(255,99,132,1)",
+                            pointBorderColor: "#fff",
+                            pointHoverBackgroundColor: "#fff",
+                            pointHoverBorderColor: "rgba(255,99,132,1)",
+                            data: [28, 48, 40, 19, 96, 27, 100]
+                        },
+                        {
+                            label: "Almacén 3",
+                            backgroundColor: "rgba(120,99,132,0.2)",
+                            borderColor: "rgba(120,99,132,1)",
+                            pointBackgroundColor: "rgba(120,99,132,1)",
+                            pointBorderColor: "#fff",
+                            pointHoverBackgroundColor: "#fff",
+                            pointHoverBorderColor: "rgba(120,99,132,1)",
+                            data: [30, 22, 85, 36, 44, 5, 63]
+                        }
+                    ]
+                },
+                options: {
+                    maintainAspectRatio: false,
+                    layout: {
+                        padding: 20
+                    },
+                    legend: {
+                        display: true
+                    }
+                }
+            });
+        }
+    });
+}

+ 37 - 0
static/src/js/widgets/top_sales_product.js

@@ -0,0 +1,37 @@
+function top_sales_product (widget) {
+    "use strict";
+
+    widget.TopSalesProductWidget = widget.Base.extend({
+        template: 'TopSalesProductTmpl',
+        data: [],
+        init: function (parent) {
+            this._super(parent, {
+                width: 4,
+                height: 6
+            });
+        },
+        start: function () {
+            var chart = new Chart(this.$el.find('#top-sales-product'), {
+                type: 'horizontalBar',
+                data: {
+                    labels: ["Product 1", "Product 2", "Product 3", "Product 4", "Product 5", "Product 6", "Product 7", "Product 8", "Product 9", "Product 10"],
+                    datasets: [
+                        {
+                            backgroundColor: ['#7c7bad', '#7c7bad', '#7c7bad', '#7c7bad', '#7c7bad', '#7c7bad', '#7c7bad', '#7c7bad', '#7c7bad', '#7c7bad'],
+                            data: [200, 175, 150, 132, 88, 54, 42, 22, 10, 5]
+                        }
+                    ]
+                },
+                options: {
+                    maintainAspectRatio: false,
+                    layout: {
+                        padding: 20
+                    },
+                    legend: {
+                        display: false
+                    }
+                }
+            });
+        }
+    });
+}

+ 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>

+ 40 - 0
static/src/xml/sale.xml

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="WidgetSaleTmpl">
+        <div class="dashboard-sale-wrapper">
+            <div class="dashboard-sale">
+                <div class="dashboard-sale-actions">
+                    <img src="/eiru_dashboard/static/img/handshake.png" />
+                    <div class="dashboard-sale-buttons">
+                        <div class="new-sale">
+                            <i class="fa fa-shopping-cart"></i>
+                        </div>
+                        <div class="new-budget">
+                            <i class="fa fa-calculator"></i>
+                        </div>
+                    </div>
+                </div>
+                <div class="dashboard-sale-welcome">
+                    <h2>Ventas y Presupuestos</h2>
+                    <div>
+                        <ul>
+                            <li>
+                                <i class="fa fa-check-square-o"></i>
+                                Realice ventas controlando sus productos sin preocupaciones.
+                            </li>
+                            <li>
+                                <i class="fa fa-check-square-o"></i>
+                                Cree presupuestos a sus clientes de manera fácil y rápida.
+                            </li>
+                            <li>
+                                <i class="fa fa-check-square-o"></i>
+                                Emita facturas directamente desde la comodidad de su sistema.
+                            </li>
+                        </ul>
+                    </div>
+                </div>
+            </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>

+ 20 - 0
static/src/xml/widgets/customers_counter.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="CustomerCounterTmpl">
+        <div>
+            <div class="grid-stack-item-content dashboard">
+                <h2 class="widget-title">
+                    <span class="glyphicon glyphicon-user" aria-hidden="true"></span>
+                    Clientes
+                </h2>
+                <div class="widget-content">
+                    <a href="#">3.000</a>
+                </div>
+                <div class="widget-footer">
+                    <a href="#">+1%</a> desde la última semana
+                </div>
+            </div>
+        </div>
+    </t>
+</template>

+ 15 - 0
static/src/xml/widgets/sales_in_the_week.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="SalesInTheWeekTmpl">
+        <t t-call="WidgetBaseTmpl">
+            <h2 class="widget-title">
+                <i class="fa fa-line-chart"></i>
+                Ventas en la semana
+            </h2>
+            <div class="widget-content">
+                <canvas id="sales-in-the-week"></canvas>
+            </div>
+        </t>
+    </t>
+</template>

+ 15 - 0
static/src/xml/widgets/sales_in_warehouse_by_brand.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="SalesInWarehouseByBrandTmpl">
+        <t t-call="WidgetBaseTmpl">
+            <h2 class="widget-title">
+                <i class="fa fa-tachometer"></i>
+                Ventas en los almacenes por marca
+            </h2>
+            <div class="widget-content">
+                <canvas id="sales-in-warehouse-by-brand"></canvas>
+            </div>
+        </t>
+    </t>
+</template>

+ 15 - 0
static/src/xml/widgets/top_sales_product.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<template xml:space="preserve">
+    <t t-name="TopSalesProductTmpl">
+        <t t-call="WidgetBaseTmpl">
+            <h2 class="widget-title">
+                <i class="fa fa-bar-chart"></i>
+                Top 10 productos más vendidos
+            </h2>
+            <div class="widget-content">
+                <canvas id="top-sales-product"></canvas>
+            </div>
+        </t>
+    </t>
+</template>

+ 29 - 0
templates.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+    <data>
+        <!-- Templates -->
+        <template id="eiru_dashboard_assets" inherit_id="web.assets_eiru">
+            <xpath expr="." position="inside">
+                <!-- Dashboard Style -->
+                <link rel="stylesheet" href="/eiru_dashboard/static/src/css/dashboard.css" />
+                <link rel="stylesheet" href="/eiru_dashboard/static/src/css/sale.css" />
+                <link rel="stylesheet" href="/eiru_dashboard/static/src/css/configuration.css" />
+
+                <!-- Dashboard Widget Base -->
+                <script type="text/javascript" src="/eiru_dashboard/static/src/js/widget_base.js" />
+
+                <!-- Dashboard Widgets -->
+                <script type="text/javascript" src="/eiru_dashboard/static/src/js/widgets/customer_counter.js" />
+                <script type="text/javascript" src="/eiru_dashboard/static/src/js/widgets/sales_in_the_week.js" />
+                <script type="text/javascript" src="/eiru_dashboard/static/src/js/widgets/top_sales_product.js" />
+                <script type="text/javascript" src="/eiru_dashboard/static/src/js/widgets/sales_in_warehouse_by_brand.js" />
+
+                <!-- Dashboard Main  -->
+                <script type="text/javascript" src="/eiru_dashboard/static/src/js/dashboard.js" />
+                <script type="text/javascript" src="/eiru_dashboard/static/src/js/sale.js" />
+                <script type="text/javascript" src="/eiru_dashboard/static/src/js/configuration.js" />
+                <script type="text/javascript" src="/eiru_dashboard/static/src/js/main.js" />
+            </xpath>
+        </template>
+    </data>
+</openerp>

+ 42 - 0
views/actions.xml

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+	<data>
+        <record id="eiru_dashboard_action" model="ir.actions.client">
+            <field name="name">Eiru Dashboard</field>
+            <field name="tag">eiru_dashboard.action_dashboard</field>
+        </record>
+
+        <record id="eiru_dashboard_sale_action" model="ir.actions.client">
+            <field name="name">Ventas y Presupuestos</field>
+            <field name="tag">eiru_dashboard.action_dashboard_sale</field>
+        </record>
+
+        <record id="eiru_dashboard_report_action" model="ir.actions.client">
+            <field name="name">Eiru Dashboard Reports</field>
+            <field name="tag">eiru_dashboard.action_dashboard_sale</field>
+        </record>
+
+        <record id="eiru_dashboard_customers_action" model="ir.actions.act_window">
+            <field name="name">Mis Clientes</field>
+            <field name="res_model">res.partner</field>
+            <field name="view_type">form</field>
+            <field name="view_mode">tree,form</field>
+            <field name="target">current</field>
+            <field name="domain">[("customer", "=", True)]</field>
+        </record>
+
+        <record id="eiru_dashboard_products_action" model="ir.actions.act_window">
+            <field name="name">Mis Productos</field>
+            <field name="res_model">product.template</field>
+            <field name="view_type">form</field>
+            <field name="view_mode">tree,form</field>
+            <field name="target">current</field>
+            <field name="domain">[("sale_ok", "=", True), ("active", "=", True)]</field>
+        </record>
+
+        <record id="action_dashboard_configuration" model="ir.actions.client">
+            <field name="name">Eiru Dashboard Configuration</field>
+            <field name="tag">eiru_dashboard.action_dashboard_configuration</field>
+        </record>
+    </data>
+</openerp>

+ 22 - 0
views/customer.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+	<data>
+		<!-- Tree -->
+        <record model="ir.ui.view" id="eiru_dashboard_customers_tree_view">
+            <field name="name">eiru.dashboard.res.partner.tree</field>
+            <field name="model">res.partner</field>
+            <field name="arch" type="xml">
+                <tree string="Clientes">
+					<field name="display_name"/>
+					<field name="function" invisible="1"/>
+					<field name="phone"/>
+					<field name="email"/>
+					<field name="user_id" invisible="1"/>
+					<field name="is_company" invisible="1"/>
+					<field name="country_id" invisible="1"/>
+					<field name="parent_id" invisible="1"/>
+                </tree>
+            </field>
+        </record>
+    </data>
+</openerp>

+ 17 - 0
views/menus.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+    <data>
+        <menuitem id="eiru_dashboard_menu" name="Inicio" sequence="0"/>
+        <menuitem id="eiru_dashboard_main" name="Principal" parent="eiru_dashboard_menu" />
+
+        <menuitem id="eiru_dashboard_dashboard" name="Mi tablero" parent="eiru_dashboard_main" action="eiru_dashboard_action" />
+        <menuitem id="eiru_dashboard_sale" name="Ventas y Presupuestos" parent="eiru_dashboard_main" action="eiru_dashboard_sale_action" />
+        <menuitem id="eiru_dashboard_reports" name="Reportes" parent="eiru_dashboard_main" action="eiru_dashboard_report_action" />
+
+        <menuitem id="eiru_dashboard_others" name="Otros" parent="eiru_dashboard_menu" />
+        <menuitem id="eiru_dashboard_customers" name="Mis Clientes" parent="eiru_dashboard_others" action="eiru_dashboard_customers_action" />
+        <menuitem id="eiru_dashboard_products" name="Mis Productos" parent="eiru_dashboard_others" action="eiru_dashboard_products_action" />
+
+        <menuitem id="menu_dashbord_configuration" name="Tablero" parent="base.menu_config" action="action_dashboard_configuration" sequence="100" />
+    </data>
+</openerp>

+ 20 - 0
views/products.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+	<data>
+        <record id="eiru_dashboard_products_tree_view" model="ir.ui.view">
+            <field name="name">eiru.dashboard.product.product</field>
+            <field name="model">product.product</field>
+            <field name="arch" type="xml">
+                <tree string="Productos">
+                    <field name="name"/>
+                    <field name="ean13"/>
+                    <field name="list_price"/>
+				  	<field name="categ_id"/>
+				  	<field name="type"/>
+				  	<field name="state"/>
+				  	<field name="uom_id" invisible="1"/>
+                </tree>
+            </field>
+        </record>
+    </data>
+</openerp>