瀏覽代碼

leads sync module added and preferences page started

robert2206 8 年之前
父節點
當前提交
7aa6d184c4

+ 32 - 6
www/css/app.css

@@ -12,12 +12,11 @@
 }
 
 .logo {
-    width: 250px;
-    display: block;
-    margin-left: auto;
-    margin-right: auto;
-    margin-top: 100px;
-    margin-bottom: 15px;
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    margin-top: -80px;
+    margin-left: -100px;
 }
 
 .logo-footer {
@@ -31,6 +30,33 @@
     text-align: center;
 }
 
+.empty-data {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    margin-top: -87px;
+    margin-left: -100px;
+}
+
 .bar-icon {
     font-size:22px !important;
 }
+
+.centered-spinner {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    margin-top: -16px;
+    margin-left: -16px;
+}
+
+.spinner svg {
+  width: 32px;
+  height: 32px;
+  stroke: #387ef5;
+  fill: #387ef5;
+}
+
+.scroll {
+    height:100%;
+}

+ 1 - 0
www/index.html

@@ -30,6 +30,7 @@
     <script src="js/controllers/customer.controller.js"></script>
     <script src="js/controllers/lead.controller.js"></script>
     <script src="js/controllers/configuration.controller.js"></script>
+    <script src="js/controllers/preferences.controller.js"></script>
 
     <!-- Factories -->
     <script src="js/factories/utils.factory.js"></script>

+ 10 - 0
www/js/app.js

@@ -121,6 +121,16 @@ angular.module('odoo',['ionic', 'ngCordova', 'xml-rpc', 'jett.ionic.filter.bar']
             }
         })
 
+        .state('app.preferences', {
+            url: 'app/preferences',
+            views: {
+                'content': {
+                    templateUrl: 'templates/preferences.html',
+                    controller: 'PreferencesController'
+                }
+            }
+        })
+
         .state('configuration', {
             url: '/configuration',
             templateUrl: 'templates/configuration.html',

+ 1 - 1
www/js/controllers/configuration.controller.js

@@ -9,7 +9,7 @@ angular.module('odoo')
     sqlFactory,
     userStorage
 ) {
-    $scope.config = { host: '192.168.2.103', port: 8069, database: 'odoo', username: 'admin', password: 'admin' }
+    $scope.config = { host: '192.168.2.102', port: 8069, database: 'odoo', username: 'admin', password: 'admin' }
 
     // Apply configuration for app
     $scope.configure = function () {

+ 11 - 6
www/js/controllers/customer.controller.js

@@ -2,17 +2,16 @@ angular.module('odoo')
 
 .controller('CustomersController', function (
     $scope,
-    $ionicLoading,
     $ionicModal,
     $ionicActionSheet,
     $ionicPopup,
     customers,
-    odoo,
     sqlFactory,
     customerStorage,
     camera,
     contact
 ) {
+    $scope.loading = false;
     $scope.customers = [];
     $scope.customer = {};
 
@@ -36,16 +35,19 @@ angular.module('odoo')
     });
 
     // Fill view list from data readed from local database
-    $scope.fill = function () {
-        $ionicLoading.show();
+    $scope.fill = function (refresh = false) {
+        $scope.loading = !refresh;
 
         customers.sync(function (customers) {
             console.log('Customers sync correctly and receive ' + customers.length + ' items');
 
             $scope.getCustomers(function () {
                 $scope.$broadcast('scroll.refreshComplete');
-                $ionicLoading.hide();
+                $scope.loading = false;
             }, function (getCustomersError) {
+                $scope.$broadcast('scroll.refreshComplete');
+                $scope.loading = false;
+
                 $ionicPopup.alert({ title: 'No se pudo obtener los clientes' });
             });
         }, function (syncCustomersError) {
@@ -53,8 +55,11 @@ angular.module('odoo')
 
             $scope.getCustomers(function () {
                 $scope.$broadcast('scroll.refreshComplete');
-                $ionicLoading.hide();
+                $scope.loading = false;
             }, function (getCustomersError) {
+                $scope.$broadcast('scroll.refreshComplete');
+                $scope.loading = false;
+
                 $ionicPopup.alert({ title: 'No se pudo obtener los clientes' });
             });
         });

+ 29 - 5
www/js/controllers/lead.controller.js

@@ -10,6 +10,7 @@ angular.module('odoo')
     leadsStorageFactory,
     sqlFactory
 ) {
+    $scope.loading = false;
     $scope.leads = [];
     $scope.lead = {};
     $scope.search = null;
@@ -33,11 +34,32 @@ angular.module('odoo')
         $scope.lead = {};
     });
 
-    $scope.fill = function () {
-        leadsRemoteFactory.sync(function () {
-            console.log('ok');
-        }, function (error) {
-            console.log('error');
+    $scope.fill = function (refresh = false) {
+        $scope.loading = !refresh;
+
+        leadsRemoteFactory.sync(function (leads) {
+            console.log('Leads sync correctly and receive ' + leads.length + ' items');
+
+            $scope.getLeads(function () {
+                $scope.$broadcast('scroll.refreshComplete');
+                $scope.loading = false;
+            }, function (getLeadsErr) {
+                $scope.$broadcast('scroll.refreshComplete');
+                $scope.loading = false;
+
+                $ionicPopup.alert({ title: 'No se pudo obtener las iniciativas' });
+            });
+        }, function (syncErr) {
+
+            $scope.getLeads(function () {
+                $scope.$broadcast('scroll.refreshComplete');
+                $scope.loading = false;
+            }, function (getLeadsErr) {
+                $scope.$broadcast('scroll.refreshComplete');
+                $scope.loading = false;
+                
+                $ionicPopup.alert({ title: 'No se pudo obtener las iniciativas' });
+            });
         });
     }
 
@@ -116,6 +138,8 @@ angular.module('odoo')
             $scope.lead = $scope.leads[index];
         }
 
+            console.log('Customer selected => ' + JSON.stringify($scope.lead));
+
         $ionicActionSheet.show({
             titleText: 'Acciones',
             buttons: [

+ 0 - 2
www/js/factories/sales/customer.sync.factory.js

@@ -51,7 +51,6 @@ angular.module('odoo')
                                                 odoo.write('res.partner', id, localData, userConfig, function (response) {
                                                     loop.next();
                                                 }, function (odooWriteError) {
-                                                    console.error(odooWriteError);
                                                     loop.next();
                                                 });
                                             } else {
@@ -75,7 +74,6 @@ angular.module('odoo')
                                             odoo.unlink('res.partner', id, userConfig, function (response) {
                                                 loop.next();
                                             }, function (odooUnlinkError) {
-                                                console.error(odooUnlinkError);
                                                 loop.next();
                                             });
 

+ 4 - 4
www/js/factories/sales/lead.storage.factory.js

@@ -4,12 +4,12 @@ angular.module('odoo')
 
     // Save lead data to local storage
     var save = function (lead, success, error) {
-        var values = [lead.remote_id ? lead.remote_id : 0, 1, lead.name ? lead.name : '', lead.description ? lead.description : '', lead.contact_name ? lead.contact_name : '', lead.phone ? lead.phone : '', lead.mobile ? lead.mobile : '', lead.fax ? lead.fax : '', lead.street ? lead.street : '', lead.street2 ? lead.street2 : '', lead.meeting_count ? lead.meeting_count : 0, lead.message_bounce ? lead.message_bounce : 0, lead.planned_cost ? lead.planned_cost : 0, lead.planned_revenue ? lead.planned_revenue : 0, lead.priority ? lead.priority : 0, lead.probability ? lead.probability : 0, lead.type ? lead.type : 'lead', lead.partner_id ? lead.partner_id : 0];
+        var values = [lead.remote_id ? lead.remote_id : 0, 1, lead.name ? lead.name : '', lead.description ? lead.description : '', lead.contact_name ? lead.contact_name : '', lead.phone ? lead.phone : '', lead.mobile ? lead.mobile : '', lead.fax ? lead.fax : '', lead.street ? lead.street : '', lead.street2 ? lead.street2 : '', lead.meeting_count ? lead.meeting_count : 0, lead.message_bounce ? lead.message_bounce : 0, lead.planned_cost ? lead.planned_cost : 0, lead.planned_revenue ? lead.planned_revenue : 0, lead.priority ? lead.priority : 2, lead.probability ? lead.probability : 0, lead.type ? lead.type : 'lead', lead.partner_id ? lead.partner_id : 0];
         var sql = null;
 
         if (lead.id) {
             values.push(lead.id);
-            
+
             sql = 'UPDATE lead SET remote_id = ?, modified = ?, modifiedDate = CURRENT_TIMESTAMP, name = ?, description = ?, contact_name = ?, phone = ?, mobile = ?, fax = ?, street = ?, street2 = ?, meeting_count = ?, message_bounce = ?, planned_cost = ?, planned_revenue = ?, priority = ?, probability = ?, type = ?, partner_id = ? WHERE id = ?';
         } else {
             sql = 'INSERT INTO lead(remote_id, modified, name, description, contact_name, phone, mobile, fax, street, street2, meeting_count, message_bounce, planned_cost, planned_revenue, priority, probability, type, partner_id) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
@@ -40,8 +40,8 @@ angular.module('odoo')
         });
     }
 
-    var removeAll = function () {
-        var sql = 'DELETE FROM lead'
+    var removeAll = function (success, error) {
+        var sql = 'DELETE FROM lead';
 
         db.executeSql(sql, [], function(result) {
             success(result.rowsAffected);

+ 142 - 18
www/js/factories/sales/lead.sync.factory.js

@@ -1,9 +1,11 @@
 angular.module('odoo')
 
-.factory('leadsRemoteFactory', function (config, odoo, sqlFactory, asyncLoop) {
+.factory('leadsRemoteFactory', function (config, odoo, sqlFactory, leadsStorageFactory, asyncLoop) {
+    var server = {};
+    var local = {};
 
     // Retrieve leads data from server
-    var retrieve = function (success, error) {
+    server.retrieve = function (success, error) {
         config(function (configuration) {
             odoo.read('crm.lead', [['active', '=', true]], configuration, function (leads) {
                 success(leads);
@@ -15,8 +17,21 @@ angular.module('odoo')
         });
     }
 
+    // Retrieve lead by id
+    server.retrieveById = function (id, success, error) {
+        config(function (configuration) {
+            odoo.read('crm.lead', [['id', '=', id]], configuration, function (response) {
+                success(response);
+            }, function (odooReadErr) {
+                error(odooReadErr)
+            });
+        }, function (configErr) {
+            error(configErr);
+        });
+    }
+
     // Update leads remote data
-    var update = function (id, data, success, error) {
+    server.update = function (id, data, success, error) {
         config(function (configuration) {
             odoo.write('crm.lead', id, data, configuration, function (response) {
                 success(response);
@@ -28,14 +43,22 @@ angular.module('odoo')
         });
     }
 
-    // Create leads on remote data
-    var send = function (data, success, error) {
-        config(function (configuration) {retrieve(function (leads) {
-            console.log(leads);
-            success();
-        }, function (retrieveError) {
-            error(retrieveError);
+    // Remove lead from server
+    server.remove = function (id, success, error) {
+        config(function (configuration) {
+            odoo.unlink('crm.lead', id, configuration, function (response) {
+                success(response);
+            }, function (odooUnlinkErr) {
+                error(odooUnlinkErr);
+            });
+        }, function (configErr) {
+            error(configErr);
         });
+    }
+
+    // Create leads on remote data
+    server.send = function (data, success, error) {
+        config(function (configuration) {
             odoo.create('crm.lead', data, configuration, function (response) {
                 success(response);
             }, function (odooCreateErr) {
@@ -47,7 +70,7 @@ angular.module('odoo')
     }
 
     // Select leads from local storage
-    var select = function (contraint, success, error) {
+    local.retrieve = function (contraint, success, error) {
         sqlFactory.selectByConstraint('lead', contraint, function (leads) {
             success(leads);
         }, function (err) {
@@ -57,7 +80,8 @@ angular.module('odoo')
 
     // Sync leads data between local and remote storage
     var sync = function (success, error) {
-        select('remote_id = 0', function (newLeads) {
+        local.retrieve('remote_id = 0', function (newLeads) {
+            console.log(newLeads);
             asyncLoop(newLeads.length, function (loop) {
                 var data = newLeads.item(loop.iteration());
 
@@ -66,16 +90,116 @@ angular.module('odoo')
                 delete data.remote_id;
                 delete data.modified;
                 delete data.modifiedDate;
+                delete data.priority;
 
-                send(data, function (response) {
+                server.send(data, function (response) {
                     console.log(response);
                     loop.next();
                 }, function (sendErr) {
                     loop.break();
                 });
-
+            // End loop
             }, function () {
-                success();
+                console.log('New data sended success');
+
+                local.retrieve('remote_id != 0 AND modified = 1', function (modifiedLeads) {
+                    asyncLoop(modifiedLeads.length, function (loop) {
+                        var localData = modifiedLeads.item(loop.iteration());
+
+                        server.retrieveById(localData.remote_id, function (leads) {
+                            if (leads.length == 1) {
+                                var remoteData = leads[0];
+
+                                var remoteModifiedDate = new Date(remoteData.__last_update);
+                                var localModifiedDate = new Date(localData.modifiedDate);
+
+
+                                if (localModifiedDate > remoteModifiedDate) {
+                                    var id = localData.remote_id;
+
+                                    // Avoid odoo server warning message
+                                    delete localData.id;
+                                    delete localData.remote_id;
+                                    delete localData.modified;
+                                    delete localData.modifiedDate;
+                                    delete localData.priority;
+
+                                    server.update(id, localData, function (response) {
+                                        loop.next();
+                                    }, function (updateErr) {
+                                        console.log(updateErr);
+                                        loop.next();
+                                    });
+                                } else {
+                                    loop.next();
+                                }
+                            } {
+                                loop.next();
+                            }
+                        }, function (retrieveByIdErr) {
+                            console.log(retrieveByIdErr);
+                            loop.next();
+                        });
+
+                    // End loop
+                    }, function () {
+                        console.log('Modified data sended success');
+
+                        local.retrieve('remote_id != 0 AND modified = 2', function (deletedLeads) {
+                            asyncLoop(deletedLeads.length, function (loop) {
+                                var id = deletedLeads.item(loop.iteration()).remote_id;
+
+                                server.remove(id, function (response) {
+                                    loop.next();
+                                }, function (removeErr) {
+                                    console.log(removeErr);
+                                    loop.next();
+                                });
+
+                            // End loop
+                            }, function () {
+
+                                console.log('Remote data deleted success');
+                                server.retrieve(function (updatedLeads) {
+                                    console.log(updatedLeads);
+
+                                    leadsStorageFactory.removeAll(function () {
+                                        console.log('Removed All');
+
+                                        asyncLoop(updatedLeads.length, function (loop) {
+                                            var data = updatedLeads[loop.iteration()];
+
+                                            // Set id for save on local database
+                                            data.remote_id = data.id;
+                                            delete data.id;
+
+                                            leadsStorageFactory.save(data, function (leadId) {
+                                                loop.next();
+                                            }, function (saveLeadErr) {
+                                                console.log(saveLeadErr);
+                                                loop.next();
+                                            });
+
+                                        // End loop
+                                        }, function () {
+
+                                            console.log('Remote data downloaded success');
+                                            success(updatedLeads);
+                                        });
+                                    }, function (removeLeadsErr) {
+                                        error(removeLeadsErr);
+                                    });
+                                }, function (retrieveErr) {
+                                    error(retrieveErr);
+                                });
+                            });
+                        }, function (selectErr) {
+                            error(selectErr);
+                        });
+                    });
+                }, function (selectErr) {
+                    error(selectErr);
+                });
             });
         }, function (selectErr) {
             error(selectErr);
@@ -83,9 +207,9 @@ angular.module('odoo')
     }
 
     return {
-        retrieve: retrieve,
-        update: update,
-        send: send,
+        retrieve: server.retrieve,
+        update: server.update,
+        send: server.send,
         sync: sync
     }
 });

+ 12 - 1
www/js/factories/user.storage.factory.js

@@ -18,7 +18,18 @@ angular.module('odoo')
         });
     };
 
+    var remove = function (success, error) {
+        var sql = 'DELETE FROM user';
+
+        db.executeSql(sql, [], function(result) {
+            success(result.rowsAffected);
+        }, function(err) {
+            error(err);
+        });
+    }
+
     return {
-        save: save
+        save: save,
+        remove: remove
     }
 });

文件差異過大導致無法顯示
+ 0 - 0
www/templates/main.html


+ 4 - 2
www/templates/menu.html

@@ -19,8 +19,10 @@
         </ion-header-bar>
         <ion-content>
             <ion-list>
-                <ion-item menu-close class="item-icon-left" ui-sref="app.sales"><i class="icon ion-pricetag" style="font-size:22px"></i> Ventas</ion-item>
-                <ion-item menu-close class="item-icon-left"><i class="icon ion-briefcase" style="font-size:22px"></i> Proyectos</ion-item>
+                <ion-item menu-close class="item-icon-left" ui-sref="app.main"><i class="icon ion-home positive" style="font-size:22px"></i> Inicio</ion-item>
+                <ion-item menu-close class="item-icon-left" ui-sref="app.sales"><i class="icon ion-pricetag positive" style="font-size:22px"></i> Ventas</ion-item>
+                <ion-item menu-close class="item-icon-left"><i class="icon ion-briefcase positive" style="font-size:22px"></i> Proyectos</ion-item>
+                <ion-item menu-close class="item-icon-left" ui-sref="app.preferences"><i class="icon ion-settings positive" style="font-size:22px"></i> Preferencias</ion-item>
             </ion-list>
         </ion-content>
     </ion-side-menu>

+ 27 - 18
www/templates/sales/customer.html

@@ -14,32 +14,41 @@
         </div>
         <form id="customer-form" ng-submit="save()">
             <div class="list">
-                <label class="item item-input">
-                    <input type="text" autofocus="autofocus" placeholder="Nombre" ng-model="customer.name">
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Nombre</span>
+                    <input type="text" autofocus="autofocus" ng-model="customer.name">
                 </label>
-                <label class="item item-input">
-                    <input type="text" placeholder="Ciudad" ng-model="customer.city">
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Ciudad</span>
+                    <input type="text" ng-model="customer.city">
                 </label>
-                <label class="item item-input">
-                    <input type="tel" placeholder="Celular" ng-model="customer.mobile">
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label item-stacked-label">Celular</span>
+                    <input type="tel" ng-model="customer.mobile">
                 </label>
-                <label class="item item-input">
-                    <input type="tel" placeholder="Teléfono" ng-model="customer.phone">
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Teléfono</span>
+                    <input type="tel" ng-model="customer.phone">
                 </label>
-                <label class="item item-input">
-                    <input type="tel" placeholder="Fax" ng-model="customer.fax">
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Fax</span>
+                    <input type="tel" ng-model="customer.fax">
                 </label>
-                <label class="item item-input">
-                    <input type="email" placeholder="Email" ng-model="customer.email">
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Email</span>
+                    <input type="email" ng-model="customer.email">
                 </label>
-                <label class="item item-input">
-                    <input type="text" placeholder="Dirección 1" ng-model="customer.street">
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Dirección</span>
+                    <input type="text" ng-model="customer.street">
                 </label>
-                <label class="item item-input">
-                    <input type="text" placeholder="Dirección 2" ng-model="customer.street2">
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Dirección</span>
+                    <input type="text" ng-model="customer.street2">
                 </label>
-                <label class="item item-input">
-                    <textarea placeholder="Nota" rows="8" cols="40" ng-model="customer.comment"></textarea>
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Nota</span>
+                    <textarea rows="8" cols="40" ng-model="customer.comment"></textarea>
                 </label>
             </div>
         </form>

文件差異過大導致無法顯示
+ 3 - 3
www/templates/sales/customers.html


+ 24 - 16
www/templates/sales/lead.html

@@ -8,29 +8,37 @@
     <ion-content>
         <form id="lead-form" ng-submit="save()">
             <div class="list">
-                <label class="item item-input">
-                    <input type="text" autofocus="autofocus" placeholder="Asunto" ng-model="lead.name">
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Asunto</span>
+                    <input type="text" autofocus="autofocus" ng-model="lead.name">
                 </label>
-                <label class="item item-input">
-                    <input type="text" placeholder="Contacto" ng-model="lead.contact_name">
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Contacto</span>
+                    <input type="text" ng-model="lead.contact_name">
                 </label>
-                <label class="item item-input">
-                    <input type="text" placeholder="Dirección" ng-model="lead.street">
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Dirección</span>
+                    <input type="text" ng-model="lead.street">
                 </label>
-                <label class="item item-input">
-                    <input type="text" placeholder="Dirección" ng-model="lead.street2">
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Dirección</span>
+                    <input type="text" ng-model="lead.street2">
                 </label>
-                <label class="item item-input">
-                    <input type="tel" placeholder="Teléfono" ng-model="lead.phone">
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Teléfono</span>
+                    <input type="tel" ng-model="lead.phone">
                 </label>
-                <label class="item item-input">
-                    <input type="tel" placeholder="Celular" ng-model="lead.mobile">
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Celular</span>
+                    <input type="tel" ng-model="lead.mobile">
                 </label>
-                <label class="item item-input">
-                    <input type="tel" placeholder="Fax" ng-model="lead.fax">
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Fax</span>
+                    <input type="tel" ng-model="lead.fax">
                 </label>
-                <label class="item item-input">
-                    <textarea placeholder="Nota" rows="8" cols="40" ng-model="lead.description"></textarea>
+                <label class="item item-input item-stacked-label">
+                    <span class="input-label">Nota</span>
+                    <textarea rows="8" cols="40" ng-model="lead.description"></textarea>
                 </label>
             </div>
         </form>

文件差異過大導致無法顯示
+ 6 - 0
www/templates/sales/leads.html


+ 3 - 3
www/templates/sales/sales.html

@@ -1,9 +1,9 @@
 <ion-view title="Ventas">
     <ion-content>
         <ion-list>
-            <ion-item class="item-icon-left" ui-sref="app.customers"><i class="ion-person-stalker" style="font-size:22px"></i> Clientes</ion-item>
-            <ion-item class="item-icon-left" ui-sref="app.leads"><i class="ion-happy" style="font-size:22px"></i> Iniciativas</ion-item>
-            <ion-item class="item-icon-left"><i class="ion-star" style="font-size:22px"></i> Oportunidades</ion-item>
+            <ion-item class="item-icon-left" ui-sref="app.customers"><i class="ion-person-stalker positive" style="font-size:22px"></i> Clientes</ion-item>
+            <ion-item class="item-icon-left" ui-sref="app.leads"><i class="ion-happy positive" style="font-size:22px"></i> Iniciativas</ion-item>
+            <ion-item class="item-icon-left" ui-sref="app.leads"><i class="ion-star positive" style="font-size:22px"></i> Oportunidades</ion-item>
         </ion-list>
     </ion-content>
 </ion-view>

部分文件因文件數量過多而無法顯示