فهرست منبع

mejorado el los métodos de manejo de datos y terminado la funcionalidad de modificación de attributos en la plantilla de productos

robert2206 8 سال پیش
والد
کامیت
d8966bd3a2

+ 6 - 5
package.json

@@ -23,20 +23,21 @@
     "@angular/platform-browser-dynamic": "2.1.1",
     "@angular/platform-server": "2.1.1",
     "@ionic/storage": "1.1.6",
+    "async": "^2.1.2",
+    "chart.js": "^2.3.0",
     "ionic-angular": "2.0.0-rc.3",
     "ionic-native": "2.2.3",
     "ionicons": "3.0.0",
-    "rxjs": "5.0.0-beta.12",
-    "zone.js": "0.6.26",
-    "async": "^2.1.2",
-    "chart.js": "^2.3.0",
     "pouchdb": "^6.0.7",
     "pouchdb-adapter-cordova-sqlite": "^2.0.0",
     "pouchdb-adapter-websql-core": "^6.0.7",
     "pouchdb-core": "^6.0.7",
+    "pouchdb-upsert": "^2.0.2",
     "relational-pouch": "^1.4.4",
     "rollup-plugin-node-builtins": "^2.0.0",
-    "rollup-plugin-node-globals": "^1.0.9"
+    "rollup-plugin-node-globals": "^1.0.9",
+    "rxjs": "5.0.0-beta.12",
+    "zone.js": "0.6.26"
   },
   "devDependencies": {
     "@ionic/app-scripts": "0.0.45",

BIN
src/assets/images/product.png


BIN
src/assets/images/product1.png


+ 12 - 1
src/defaults/default-listable.ts

@@ -66,7 +66,11 @@ export abstract class DefaultListable<T> implements IListable<T> {
      *
      */
     add(T: any): void {
-        this._elements.push(T);
+        this.elements.push(T);
+
+        if (this.elements.length < this._visibleRange[1]) {
+            this._visibleElements.push(T);
+        }    
     }
 
     /**
@@ -99,6 +103,13 @@ export abstract class DefaultListable<T> implements IListable<T> {
         return this._elements;
     }
 
+    /**
+     *
+     */
+    trackByElements(index: number, element: any) {
+        return element.id;
+    }
+
     /**
      *
      */

+ 37 - 21
src/models/product.ts

@@ -1,25 +1,41 @@
-import '../decorators/document-type';
-
-@type('product_template')
 export class Product {
 
-    company_id: number = 0;
-    default_code: string = null;
-    description: string = null;
-    ean13: string = null;
-    image_medium: string = null;
-    image_small: string = null;
-    name: string = null;
-    list_price: number = 1;
-    purchase_ok: boolean =  true;
-    qty_available: number = 0;
-    rental: boolean = false;
-    sale_ok: boolean = true;
-    standard_price: number = 0;
-    type: number = 0;
-    website_published: false = false;
-    remote_id: number = 0;
-    doc_state: string = "created";
+    public default_code: string;
+    public description: string;
+    public ean13: string;
+    public image_medium: string;
+    public image_small: string;
+    public name: string;
+    public list_price: number;
+    public purchase_ok: boolean;
+    public qty_available: number;
+    public rental: boolean;
+    public sale_ok: boolean;
+    public standard_price: number;
+    public type: number;
+    public website_published: false;
+    public remote_id: number;
+    public doc_state: string;
+    public company_id: number;
+    public attribute_line_ids: Array<any>;
 
-    constructor() {}
+    constructor() {
+        this.default_code = null;
+        this.description = null;
+        this.ean13 = null;
+        this.image_medium = null;
+        this.image_small = null;
+        this.name = null;
+        this.list_price = 1;
+        this.purchase_ok = false;
+        this.qty_available = 0;
+        this.rental = false;
+        this.standard_price = 1;
+        this.type = 0;
+        this.website_published = false;
+        this.remote_id = 0;
+        this.doc_state = "created";
+        this.company_id = 0;
+        this.attribute_line_ids = [];
+    }
 }

+ 2 - 2
src/pages/product-details/product-details.html

@@ -97,11 +97,11 @@
                 </ion-item>
             </ion-card>
 
-            <ion-fab right bottom>
+            <!--<ion-fab right bottom>
                 <button ion-fab primary (click)="addAttribute()">
                     <ion-icon name="add"></ion-icon>
                 </button>
-            </ion-fab>
+            </ion-fab>-->
         </div>
     </div>
 </ion-content>

+ 30 - 51
src/pages/product-details/product-details.ts

@@ -1,41 +1,19 @@
 import { Component } from '@angular/core';
 import { NavController, NavParams, ActionSheetController, ToastController, LoadingController } from 'ionic-angular';
 import { Shake, BarcodeScanner } from 'ionic-native';
-// import { Product } from '../../models/product'
+import { Product } from '../../models/product';
+import { ProductListPage } from '../product-list/product-list';
 import { DataProvider } from '../../providers/data-provider'
 import { CameraProvider } from '../../providers/camera-provider';
 import { PreferencesProvider } from '../../providers/preferences-provider';
 
 @Component({
     selector: 'page-product-details',
-    providers: [CameraProvider],
+    providers: [Product, CameraProvider],
     templateUrl: 'product-details.html'
 })
 export class ProductDetailsPage {
 
-    product = {
-        company_id: 0,
-        default_code: null,
-        description: null,
-        ean13: null,
-        image_medium: null,
-        image_small: null,
-        name: null,
-        list_price: 1,
-        purchase_ok: true,
-        qty_available: 0,
-        rental: false,
-        sale_ok: true,
-        standard_price: 0,
-        type: "product",
-        website_published: false,
-        remote_id: 0,
-        doc_state: "created",
-        attribute_line_ids: [],
-        write_date: null,
-        rev: null
-    }
-
     attribute_lines: Array<any> = [];
     attribute_values: Array<any> = [];
     attributes: Array<any> = [];
@@ -43,6 +21,7 @@ export class ProductDetailsPage {
     watcher: any;
 
     constructor(
+        public product: Product,
         public navCtrl: NavController,
         public params: NavParams,
         public data: DataProvider,
@@ -52,11 +31,9 @@ export class ProductDetailsPage {
         public cameraProvider: CameraProvider,
         public preferencesPreferences: PreferencesProvider
     ) { 
-        if (!(this.params.data instanceof Array)) {
+        if (!(this.params.data instanceof ProductListPage)) {
             this.product = this.params.data;
             this.product.doc_state = "updated";
-
-            delete this.product.rev;
         }
     }
 
@@ -64,8 +41,6 @@ export class ProductDetailsPage {
      *
      */
     ionViewDidLoad() {
-        this.initialize();
-
         this.watcher = Shake.startWatch(40).subscribe(() => { 
             BarcodeScanner.scan().then(bar => { 
                 this.product.ean13 = bar.cancelled ? null : bar.text;
@@ -87,13 +62,6 @@ export class ProductDetailsPage {
         }
     }
 
-    /**
-     *
-     */
-    private initialize() {
-        
-    }
-
     /**
      *
      */
@@ -155,14 +123,14 @@ export class ProductDetailsPage {
         });
         loader.present();
 
-        this.data.getAll('product_attribute_line').then(product_attribute_lines => {
+        this.data.getAll(DataProvider.DOCS.PRODUCT_ATTRIBUTE_LINE).then(product_attribute_lines => {
             this.attribute_lines = product_attribute_lines;
 
-            return this.data.getAll('product_attribute');
+            return this.data.getAll(DataProvider.DOCS.PRODUCT_ATTRIBUTE);
         }).then(product_attributes => {
             this.attributes = product_attributes;
 
-            return this.data.getAll('product_attribute_value');
+            return this.data.getAll(DataProvider.DOCS.PRODUCT_ATTRIBUTE_VALUE);
         }).then(product_attribute_values => {
             this.attribute_values = product_attribute_values;
 
@@ -195,15 +163,23 @@ export class ProductDetailsPage {
         })[0];
 
         attribute_line.value_ids = attribute_values;
+        
 
-        this.data.save('product_attribute_line', attribute_line).then(pal => { 
-            console.log(pal);
+        // this.data.get(DataProvider.DOCS.PRODUCT_ATTRIBUTE_LINE, attribute_line.id).then(instance => { 
+        //     console.log(instance);
             
-        }, e => { 
-            console.log(e);
+        // }).catch(e => { 
+        //     console.log(e);
             
+        // });
+        this.data.save(DataProvider.DOCS.PRODUCT_ATTRIBUTE_LINE, attribute_line).then(pal => { 
+            console.log(pal);           
+        }, e => { 
+            this.toastCtrl.create({
+                message: 'No se han podido guardar los cambios',
+                duration: 3000
+            }).present();
         });
-        
     }
 
     /**
@@ -214,17 +190,20 @@ export class ProductDetailsPage {
             return;
         }
 
-        console.log(this.product);
-        
-
-        this.data.save('product', this.product).then(result => {
-            if (this.params.data instanceof Array) {
-                this.params.data.push(result.products[0]);
+        this.data.save(DataProvider.DOCS.PRODUCT_TEMPLATE, this.product).then(product => {
+            if (this.params.data instanceof ProductListPage) {
+                this.params.data.add(product);
             }
             
             this.navCtrl.pop(this);
         }).catch(e => {
             console.log(e);
+            
+            this.toastCtrl.create({
+                message: 'No se han podido guardar los cambios',
+                duration: 3000
+            }).present();
+
         });
   
     }

+ 1 - 1
src/pages/product-list/product-list.html

@@ -27,7 +27,7 @@
 
 <ion-content>
 
-    <ion-card *ngFor="let p of visibleElements">
+    <ion-card *ngFor="let p of visibleElements; trackBy:trackByElements">
         <ion-item>
             <ion-thumbnail item-left>
                 <img src="./assets/images/product.png" *ngIf="!p.image_medium"/>

+ 2 - 4
src/pages/product-list/product-list.ts

@@ -24,7 +24,6 @@ export class ProductListPage extends DefaultListable<Product> implements INaviga
         public popoverCtrl: PopoverController
     ){
         super(loadingCtrl);
-        
     }
     
     ionViewDidLoad() {
@@ -40,7 +39,7 @@ export class ProductListPage extends DefaultListable<Product> implements INaviga
         });
 
         loader.present();
-        this.dataProvider.getAll("product_template").then(templates => {
+        this.dataProvider.getAll(DataProvider.DOCS.PRODUCT_TEMPLATE).then(templates => {
             this.elements = templates.filter(item => {
                 return item.doc_state !== "deleted"; 
             });
@@ -53,7 +52,7 @@ export class ProductListPage extends DefaultListable<Product> implements INaviga
      * Goto page
      */
     goToPage(page: any) {
-        this.navCtrl.push(ProductDetailsPage, this.elements);
+        this.navCtrl.push(ProductDetailsPage, this);
     }
 
     /**
@@ -93,7 +92,6 @@ export class ProductListPage extends DefaultListable<Product> implements INaviga
     openItem(item: any) {
         this.navCtrl.push(ProductDetailsPage, item, data => {
             console.log(data);
-            
         });
     }    
 

+ 56 - 23
src/providers/data-provider.ts

@@ -1,16 +1,24 @@
 import { Injectable } from '@angular/core';
 import { Platform } from 'ionic-angular';
 import PouchDB from 'pouchdb';
-import * as Relational from 'relational-pouch';
-import * as Sqlite from 'pouchdb-adapter-cordova-sqlite';
+import * as PouchRelational from 'relational-pouch';
+import * as PouchUpsert from 'pouchdb-upsert';
+import * as PouchSqlite from 'pouchdb-adapter-cordova-sqlite';
 import each from 'async/each';
 
-PouchDB.plugin(Relational).plugin(Sqlite);
+PouchDB.plugin(PouchRelational).plugin(PouchUpsert).plugin(PouchSqlite);
 
 @Injectable()
 export class DataProvider {
 
-    data: any;
+    public static readonly DOCS = {
+        PRODUCT_TEMPLATE: 'product.template',
+        PRODUCT_ATTRIBUTE: 'product.attribute',
+        PRODUCT_ATTRIBUTE_LINE: 'product.attribute.line',
+        PRODUCT_ATTRIBUTE_VALUE: 'product.attribute.value'
+    };
+
+    db: any;
     schema: Array<any> = [
         {
             singular: 'partner',
@@ -29,8 +37,8 @@ export class DataProvider {
             plural: 'companies'
         },
         {
-            singular: 'product_template',
-            plural: 'product_templates'
+            singular: 'product.template',
+            plural: 'product.templates'
         },
         {
             singular: 'warehouse',
@@ -45,16 +53,16 @@ export class DataProvider {
             plural: 'leads'
         },
         {
-            singular: 'product_attribute',
-            plural: 'product_attributes'
+            singular: 'product.attribute',
+            plural: 'product.attributes'
         },
         {
-            singular: 'product_attribute_line',
-            plural: 'product_attribute_lines'
+            singular: 'product.attribute.line',
+            plural: 'product.attribute.lines'
         },
         {
-            singular: 'product_attribute_value',
-            plural: 'product_attribute_values'
+            singular: 'product.attribute.value',
+            plural: 'product.attribute.values'
         },
         {
             singular: 'product',
@@ -72,12 +80,12 @@ export class DataProvider {
      *
      */
     private initialize(): void {
-        this.data = new PouchDB('odoo', {
+        this.db = new PouchDB('odoo', {
             auto_compaction: true,
             adapter: this.platform.is('core') ? 'idb' : 'websql'
         });
         
-        this.data.setSchema(this.schema);
+        this.db.setSchema(this.schema);
     }
 
     /**
@@ -104,7 +112,7 @@ export class DataProvider {
             if (data instanceof Array) {
 
                 each(data, (i, c) => {
-                    this.data.rel.save(type, i).then(() => {
+                    this.save(type, i).then(() => {
                         c();
                     }).catch(e => {
                         c(e);
@@ -118,11 +126,18 @@ export class DataProvider {
                 });
 
             } else {
-                this.data.rel.save(type, data).then(doc => { 
+
+                this.db.rel.save(type, data).then(doc => { 
                     resolve(doc[this.getPlural(type)][0]);
                 }).catch(e => {
-                    reject(e);
-                });
+                    this.db.upsert(data.id, doc => {
+                        return doc;
+                    }).then(r => { 
+                        resolve(r);
+                    }).catch(e => {
+                        reject(e);
+                    });
+                });   
             }
         });
     }
@@ -133,7 +148,7 @@ export class DataProvider {
     delete(type: string, data: any): any {
         return new Promise((resolve, reject) => {
             this.platform.ready().then(r => {
-                resolve(data.remote_id ? this.save(type, data) : this.data.rel.del(type, data));
+                resolve(data.remote_id ? this.save(type, data) : this.db.rel.del(type, data));
             });    
         });
     }
@@ -145,7 +160,7 @@ export class DataProvider {
         return new Promise((resolve, reject) => { 
             this.getAll(type).then(data => {
                 each(data[type], (i, c) => { 
-                    this.data.rel.del(type, i).then(r => {
+                    this.db.rel.del(type, i).then(r => {
                         c();
                     }).catch(e => {
                         c(e);
@@ -168,7 +183,20 @@ export class DataProvider {
      */
     getAll(type: string): Promise<any> {
         return new Promise((resolve, reject) => {
-            this.data.rel.find(type).then(result => {
+            this.db.rel.find(type).then(result => {
+                resolve(result[this.getPlural(type)]);
+            }).catch(e => {
+                reject(e);
+            });
+        });
+    }
+
+    /**
+     *
+     */
+    get(type: string, id?: string) {
+        return new Promise((resolve, reject) => { 
+            this.db.rel.find(type, id).then(result => {
                 resolve(result[this.getPlural(type)]);
             }).catch(e => {
                 reject(e);
@@ -181,7 +209,12 @@ export class DataProvider {
      */
     dropDatabase(): any {
         return new Promise((resolve, reject) => {
-            resolve(this.data.destroy());
+            this.db.destroy().then(r => {
+                this.initialize();
+                resolve(r);
+            }).catch(e => {
+                reject(e);
+            });
         });
     }
 
@@ -189,6 +222,6 @@ export class DataProvider {
      *
      */
     parseDocID(id: string): any {
-        return this.data.rel.parseDocID(id);
+        return this.db.rel.parseDocID(id);
     }
 }

+ 2 - 2
src/providers/sync/product-attribute-line-sync-provider.ts

@@ -34,10 +34,10 @@ export class ProductAttributeLineSyncProvider {
      */
     private storeLines(lines: Array<any>): Promise<any> {
         return new Promise((reject, resolve) => {
-            this.dataProvider.deleteAll('product_attribute_line').then(() => {
+            this.dataProvider.deleteAll(DataProvider.DOCS.PRODUCT_ATTRIBUTE_LINE).then(() => {
                 return;
             }).then(() => {
-                return this.dataProvider.save('product_attribute_line', lines.map(item => {
+                return this.dataProvider.save(DataProvider.DOCS.PRODUCT_ATTRIBUTE_LINE, lines.map(item => {
                     item.remote_id = item.id;
                     item.doc_state = "sync";
                     delete item.id;

+ 2 - 2
src/providers/sync/product-attribute-sync-provider.ts

@@ -34,10 +34,10 @@ export class ProductAttributeSyncProvider {
      */
     private storeAttributes(attrs: Array<any>): Promise<any> {
         return new Promise((reject, resolve) => {
-            this.dataProvider.deleteAll('product_attribute').then(() => {
+            this.dataProvider.deleteAll(DataProvider.DOCS.PRODUCT_ATTRIBUTE).then(() => {
                 return;
             }).then(() => {
-                return this.dataProvider.save('product_attribute', attrs.map(item => {
+                return this.dataProvider.save(DataProvider.DOCS.PRODUCT_ATTRIBUTE, attrs.map(item => {
                     item.remote_id = item.id;
                     item.doc_state = "sync";
                     delete item.id;

+ 2 - 2
src/providers/sync/product-attribute-value-sync-provider.ts

@@ -34,10 +34,10 @@ export class ProductAttributeValueSyncProvider {
      */
     private storeValues(values: Array<any>): Promise<any> {
         return new Promise((reject, resolve) => {
-            this.dataProvider.deleteAll('product_attribute_value').then(() => {
+            this.dataProvider.deleteAll(DataProvider.DOCS.PRODUCT_ATTRIBUTE_VALUE).then(() => {
                 return;
             }).then(() => {
-                return this.dataProvider.save('product_attribute_value', values.map(item => {
+                return this.dataProvider.save(DataProvider.DOCS.PRODUCT_ATTRIBUTE_VALUE, values.map(item => {
                     item.remote_id = item.id;
                     item.doc_state = "sync";
                     delete item.id;

+ 5 - 5
src/providers/sync/product-template-sync-provider.ts

@@ -48,7 +48,7 @@ export class ProductTemplateSyncProvider {
      */
     private getCreatedProducts(): Promise<any> {
         return new Promise((resolve, reject) => {
-            this.dataProvider.getAll("product_template").then(templates => {
+            this.dataProvider.getAll(DataProvider.DOCS.PRODUCT_TEMPLATE).then(templates => {
                 resolve(templates.filter(item => {
                     return item.doc_state === "created" || (item.doc_state === "updated" && !item.remote_id);
                 }));
@@ -63,7 +63,7 @@ export class ProductTemplateSyncProvider {
      */
     private getUpdatedProducts(): Promise<any> {
         return new Promise((resolve, reject) => {
-            this.dataProvider.getAll("product_template").then(templates => {
+            this.dataProvider.getAll(DataProvider.DOCS.PRODUCT_TEMPLATE).then(templates => {
                 let products = templates.filter(item => {
                     return item.doc_state === "updated" && item.remote_id;
                 });
@@ -83,7 +83,7 @@ export class ProductTemplateSyncProvider {
      */
     private getDeletedProducts(): Promise<any> {
         return new Promise((resolve, reject) => { 
-            this.dataProvider.getAll("product_template").then(templates => {
+            this.dataProvider.getAll(DataProvider.DOCS.PRODUCT_TEMPLATE).then(templates => {
                 let products = templates.filter(item => { 
                     return item.doc_state === "deleted";
                 });
@@ -103,13 +103,13 @@ export class ProductTemplateSyncProvider {
      */
     private storeProducts(products: Array<any>): Promise<any> {
         return new Promise((resolve, reject) => {
-            this.dataProvider.deleteAll("product_template").then(() => {
+            this.dataProvider.deleteAll(DataProvider.DOCS.PRODUCT_TEMPLATE).then(() => {
                 return;
             }).then(() => {
                 console.log(products);
                 
                 
-                return this.dataProvider.save("product_template", products.map(item => {
+                return this.dataProvider.save(DataProvider.DOCS.PRODUCT_TEMPLATE, products.map(item => {
                     item.remote_id = item.id;
                     item.doc_state = "sync";
                     delete item.id;