@krizim wrote:
Hi Dear,
I have trouble saving multiple items when I use the check out the system will remove all multiple items and print only one,
when I select multiple items the system will remove all, I found one item for each product.
I need to fix this problem.
import { SharedModule } from ‘…/…/app/shared.module’;
import { NgModule } from ‘@angular/core’;
import { IonicPageModule } from ‘ionic-angular’;
import { CheckoutPage } from ‘./checkout’;@NgModule({
declarations: [
CheckoutPage
],
imports: [
IonicPageModule.forChild(CheckoutPage),
SharedModule
],
})
export class CheckoutPageModule {}
checkout.ts
import { Component } from ‘@angular/core’;
import { StatusBar } from ‘@ionic-native/status-bar’;
import { IonicPage, App, Platform, AlertController, NavController, Events, ModalController, NavParams } from ‘ionic-angular’;
import { AddressProvider, SettingsProvider, ToastProvider, UserProvider, LoadingProvider, CartProvider, WooCommerceProvider, OrderProvider } from ‘…/…/providers/providers’;
import { TranslateService } from ‘@ngx-translate/core’;@IonicPage()
@Component({
selector: ‘page-checkout’,
templateUrl: ‘checkout.html’,
})export class CheckoutPage {
checkout: string = “shipping”;
cart: any;
settings: any;
billing: any;
shipping: any;
zones: any;
shipping_lines: any[] = [];
shipping_method: any = [];
payments: any[] = [];
coupons: any[] = [];
tax: any;
order: any = {};
total: number = 0;
allowFreeShipping: boolean = false;stripe: any = {
no: ‘’,
month: ‘’,
year: ‘’
};razor: any = {};
coupon: any = {};
months: any = [‘January’, ‘February’, ‘March’, ‘April’, ‘May’, ‘June’, ‘July’, ‘August’, ‘September’, ‘October’, ‘November’, ‘December’];
years: any = [];img: any = {
stripe: [
‘assets/img/logo/visa.svg’,
‘assets/img/logo/mastercard.svg’,
‘assets/img/logo/amex.svg’,
‘assets/img/logo/diners.svg’,
‘assets/img/logo/discover.svg’,
‘assets/img/logo/jcb.svg’
],
paypal: [
‘assets/img/logo/visa.svg’,
‘assets/img/logo/mastercard.svg’,
‘assets/img/logo/amex.svg’,
‘assets/img/logo/discover.svg’
],
razorpay: [
‘assets/img/logo/logo-razor.png’
]
};constructor(private setting: SettingsProvider, private app: App, private statusBar: StatusBar, private alert: AlertController, private platform: Platform, private nav: NavController, private translate: TranslateService, private toast: ToastProvider, private user: UserProvider, private loader: LoadingProvider, private woo: WooCommerceProvider, private _cart: CartProvider, private events: Events, private _order: OrderProvider, private address: AddressProvider, public navParams: NavParams, public modal: ModalController) {
this.woo.loadPayments().then( x=> {
this.payments = x;
});this.woo.loadCoupons().then( x=> { this.coupons = x; }, err => { console.log(err); }) this.cart = this._cart; if(this.setting.all.zones.length <= 0){ this.loader.present(); this.woo.loadZones(); this.setting.load().then(x=>{ this.zones = x.zones; this.loader.dismiss(); }) }else this.zones = this.setting.all.zones; this.woo.getTaxes().then( x=> { this.tax = x; console.log(x); }) this.listenOrder();
}
ionViewDidEnter(){
if (this.platform.is(‘cordova’))
this.statusBar.styleDefault();
this.setOrder();
}setOrder(){
if(this.address.getPrimary){ this.billing = this.address.getPrimary; this.shipping = this.address.getPrimary; } if(this._order.billing) this.billing = this._order.billing; if(this._order.shipping) this.shipping = this._order.shipping; let tmp = (this.settings.value == 'shipping') ? this.shipping : this.billing; if(this.shipping){ let id = this.woo.getSingleZone(this.setting.all.zones, this.shipping); if(id){ this.loader.present(); this.woo.getShippingZoneMethod(id).then( x=> { this.shipping_method = x; this.loader.dismiss(); let tmp; for(let i in x){ if(x[i].enabled && x[i].method_id == 'free_shipping'){ tmp = x[i].settings; break; } } if(tmp){ switch(tmp.requires.value){ case 'min_amount': // minimun order amount if(tmp.min_amount.value && this.cart.total > parseInt(tmp.min_amount.value)) this.allowFreeShipping = true; break; case 'coupon': // coupon if(this.coupon.description) // coupon valid this.allowFreeShipping = true; break; case 'either': // minimun order amount or coupon if(tmp.min_amount.value && this.cart.total > parseInt(tmp.min_amount.value) || this.coupon.description) this.allowFreeShipping = true; break; case 'both': // minimun order amount and coupon if(tmp.min_amount.value && this.cart.total > parseInt(tmp.min_amount.value) && this.coupon.description) this.allowFreeShipping = true; break; default: this.allowFreeShipping = true; } } }, e=> { console.log(e); }); }else{ this.shipping_method = []; this.translate.get(['NO_SHIPPING']).subscribe( x=> { this.toast.showWithClose(x.NO_SHIPPING); }); } }else{ this.translate.get(['SELECT_SHIPPING']).subscribe( x=> { this.toast.showWithClose(x.SELECT_SHIPPING); }); }
}
viewCart(){
this.modal.create(‘MiniCartPage’, {isCheckout: true}, { cssClass: ‘inset-modal’ }).present();
}setShipping(param){
this.shipping_lines = [];
let e = JSON.parse(param);
this.shipping_lines.push({
method_id: e.method_id,
method_title: e.title,
total: (e.settings.cost ? e.settings.cost.value : 0)
});this.updateTotal(); this.total = this.cart.total + parseInt(this.shipping_lines[0].total);
}
setPayment(param){
this.years = [];
let e = JSON.parse(param);
this.order.payment_method = e.id;
this.order.payment_method_title = e.method_title;
this.order.payment_method_description = e.description;
if(e.id != ‘cod’) this.order.set_paid = true;
for(let i in this.payments)
this.payments[i].open = false;for(let i in this.payments){ if(this.payments[i].id == e.id){ this.payments[i].open = true || !this.payments[i].open; break; } } if(e.id == 'stripe'){ if(e.settings.testmode.value == 'yes'){ this.stripe.publishable_key = e.settings.test_publishable_key.value; this.stripe.secret_key = e.settings.test_secret_key.value; }else{ this.stripe.publishable_key = e.settings.publishable_key.value; this.stripe.secret_key = e.settings.secret_key.value; } for(let i=0; i<10; i++) this.years.push(new Date().getFullYear() + i); } if(e.id == 'razorpay'){ if(e.settings.key_id.value) this.razor.key = e.settings.key_id.value; if(e.settings.key_secret.value) this.razor.key = e.settings.key_secret.value; }
}
listenOrder(){
this.events.subscribe(‘order:go’, (res) => {
this.setOrder();
});
}selectAddress(action){
let params = {
action: action
}
this.modal.create(‘SavedAddressPage’, {params: params}).present();
}addAddress(action){
let params = {
action: action
}
this.modal.create(‘AddAddressPage’, {params: params}).present();
}next(){
this.checkout = ‘payment’;
}isCouponValid(x){
console.log(this.coupon.input.toLowerCase());
console.log(x.toLowerCase());
return this.coupon.input.toLowerCase() == x.toLowerCase() ? true : false;
}isCouponExpired(x){
return new Date().getTime() > new Date(x).getTime() ? true : false;
}isMinimumValid(x){
return this.cart.total < x ? true : false;
}isMaximumValid(x){
return this.cart.total > x ? true : false;
}submitCoupon(){
this.allowFreeShipping = false;
this.order.coupon_lines = [];
this.coupon.err = ‘’;
this.coupon.description = ‘’;if(this.coupons){ let errors = [ 'Coupon is invalid', 'Coupon is expired', 'Subtotal must be > ', 'Subtotal must be < ', 'Coupon usage is limited' ] let valid = false; let x: any; for(let i in this.coupons){ x = this.coupons[i]; if(this.isCouponValid(x.code)){ valid = true; if(x.free_shipping) this.allowFreeShipping = true; break; } } if(valid){ if(x.date_expires && this.isCouponExpired(x.date_expires)) this.coupon.err = errors[1]; else if(x.minimum_amount > 0 && this.isMinimumValid(x.minimum_amount)) this.coupon.err = errors[2] + x.minimum_amount; else if(x.maximum_amount > 0 && this.isMaximumValid(x.maximum_amount)) this.coupon.err = errors[3] + x.maximum_amount; else if(x.usage_limit && x.usage_count >= x.usage_limit) this.coupon.err = errors[4]; else{ this.coupon.description = x.description || 'Congrat, your coupon is valid'; this.order.coupon_lines.push({ code: x.code, discount: this.getTotalDiscount(x) }); } }else this.coupon.err = errors[0]; this.updateTotal(); } if(this.coupon.err){ this.translate.get(['OK', 'COUPON_CODE', 'COUPON_INVALID']).subscribe( x=> { this.alert.create({ title: x.COUPON_CODE, message: this.coupon.err, buttons: [{ text: x.OK }] }).present(); }); }
}
getTotalDiscount(x:any){
let total = 0;
if(x.discount_type == ‘percent’)
total = x.amount * this.cart.total / 100;
else if(x.discount_type == ‘fixed_cart’)
total = x.amount;
else
total = x.amount * this.cart.totalQtyDetail;return total;
}
updateTotal(){
let shipping = this.shipping_lines[0] ? parseInt(this.shipping_lines[0].total) : 0;
let discount = this.coupon.description ? parseInt(this.order.coupon_lines[0].discount) : 0;
this.total = this.cart.total + shipping - discount;
}confirm(){
this.loader.present();
this.order.billing = this.billing;
this.order.shipping = this.shipping;
this.order.line_items = this.cart.lineItems;
this.order.currency = this.setting.all.settings.currency;if(this.coupon.description){ // update line item total if coupon valid let tmp: any; tmp = this.order.coupon_lines[0].discount / this.cart.totalQtyDetail; for(let i in this.order.line_items) this.order.line_items[i].total = this.order.line_items[i].subtotal - (tmp.toFixed(2) * this.order.line_items[i].quantity); } this.order.shipping_lines = this.shipping_lines; if(this.user.all) this.order.customer_id = this.user.id; console.log(this.order); this.loader.dismiss(); this.goTo('ThanksPage', this.order); // CHECKOUT WITH PAYPAL if(this.order.payment_method == 'paypal'){ if (!this.platform.is('cordova')) this.shouldDeviceOnly(); else{ this.order.total = this.total; this._order.checkoutPaypal(this.order).then((res)=>{ if(res){ this.createOrder(this.order); }else{ this.loader.dismiss(); this.toast.show(res); } }, err=>{ this.loader.dismiss(); this.toast.show(err); }); } // CHECKOUT WITH STRIPE }else if(this.order.payment_method == 'stripe'){ if (!this.platform.is('cordova')) this.shouldDeviceOnly(); else{ this.order.total = this.total; this._order.getStripeToken(this.stripe).then((token)=>{ if(token.id){ token.secret_key = this.stripe.secret_key; this._order.checkoutStripe(this.order, token) .subscribe( (res) => { this.createOrder(this.order); }, err => { this.loader.dismiss(); this.toast.showWithClose(err.json().error.message); }); }else{ this.loader.dismiss(); this.toast.showWithClose(token); } }, err => { this.loader.dismiss(); this.toast.showWithClose(err); }) } // CHECKOUT WITH RAZOR PAY }else if(this.order.payment_method == 'razorpay'){ if (!this.platform.is('cordova')) this.shouldDeviceOnly(); else{ this.order.total = this.total; this._order.checkoutRazorpay(this.order, this.razor) .then( (res) => { console.log(res); this.createOrder(this.order); }, err => { this.loader.dismiss(); this.toast.showWithClose(err.description); }); } // CHECKOUT WITH OTHERs }else if(this.order.payment_method == 'bacs' || this.order.payment_method == 'cod' || this.order.payment_method == 'cheque'){ this.createOrder(this.order); // NOT AVAILABLE }else{ this.loader.dismiss(); this.translate.get(['OK', 'NOT_AVAILABLE', 'PAYMENT_NOT_AVAILABLE']).subscribe( x=> { this.alert.create({ title: x.NOT_AVAILABLE, message: x.PAYMENT_NOT_AVAILABLE, buttons: [{ text: x.OK }] }).present(); this.loader.dismiss(); return false; }); }
}
shouldDeviceOnly(){
this.translate.get([‘OK’, ‘ONLY_DEVICE’, ‘ONLY_DEVICE_DESC’]).subscribe( x=> {
this.alert.create({
title: x.ONLY_DEVICE,
message: x.ONLY_DEVICE_DESC,
buttons: [{
text: x.OK
}]
}).present();
this.loader.dismiss();
return false;
});
}createOrder(order: any){
this.woo.createOrder(order).then( x=>{
if(x){
this._order.reset().then(() => {});
this.cart.reset().then(() => {});
this.goTo(‘ThanksPage’, x);
}else{
this.toast.showWithClose(‘CORS issues, please use https.’);
}
this.loader.dismiss();
}, err=> {
this.loader.dismiss();
this.toast.show(err);
})
}goTo(page, params){
this.app.getRootNav().setRoot(page, {params: params});
}}
checkout.html
{{ 'SHIPPING' | translate}} {{ 'PAYMENT' | translate}}{{ 'BILLING_ADDRESS' | translate}}
{{ 'BILLING_DESC' | translate}}{{billing.first_name}} • {{billing.phone}}
{{billing.address_1}}
{{billing.city}}, {{billing.state}}, {{billing.postcode}}
{{billing.country}}
{{ 'ADD' | translate}} {{ 'NEW_ADDRESS' | translate}} {{ 'SELECT' | translate}} {{ 'OTHER_ADDRESS' | translate}}<ion-list margin-top padding-top> <div padding-horizontal> <h3>{{ 'SHIPPING_ADDRESS' | translate}}</h3> <ion-note padding-bottom>{{ 'SHIPPING_DESC' | translate}}</ion-note> </div> <ion-item no-lines *ngIf="shipping"> <p>{{shipping.first_name}} • {{shipping.phone}}</p> <p>{{shipping.address_1}}</p> <p>{{shipping.city}}, {{shipping.state}}, {{shipping.postcode}}</p> <p>{{shipping.country}}</p> </ion-item> <div padding-horizontal> <button ion-button outline block icon-start *ngIf="!shipping" tappable (click)="addAddress(4)"> {{ 'ADD' | translate}} {{ 'NEW_ADDRESS' | translate}} </button> <button ion-button outline block icon-start *ngIf="shipping" tappable (click)="selectAddress(4)"> {{ 'SELECT' | translate}} {{ 'OTHER_ADDRESS' | translate}} </button> </div> </ion-list> <ion-list no-margin margin-top> <div padding-horizontal> <h3>{{ 'REVIEW_PURCHASE' | translate}}</h3> <ion-note>{{ 'REVIEW_DESC' | translate}}</ion-note> </div> </ion-list> <ion-list no-margin margin-top *ngIf="cart.all.length > 0"> <ion-item *ngFor="let x of cart.all"> <ion-thumbnail item-start> <div class="img" [ngStyle]="{'background-image': 'url(' + x.images[0].src +')'}"></div> </ion-thumbnail> <h3 [innerHTML]="x.name"></h3> <p> <span class="disc" *ngIf="x.on_sale">{{x.regular_price | money}} •</span> <span class="price">{{x.price | money}}</span> <ng-container *ngIf="x.attributes.length > 0"><span *ngFor="let y of x.attributes">• <i>{{y.option || y.options[0]}}</i> </span></ng-container> <span>• {{x.quantity}}x</span> </p> </ion-item> </ion-list> <ion-list margin-bottom padding-top *ngIf="coupons.length > 0"> <div padding-horizontal> <h3>{{ 'COUPON_CODE' | translate}}</h3> </div> </ion-list> <ion-list margin-bottom *ngIf="coupons.length > 0"> <ion-grid class="coupon" no-padding> <ion-row align-items-center padding-horizontal> <ion-col> <ion-item no-padding no-padding> <ion-input placeholder="{{ 'INPUT_CODE' | translate}}" [(ngModel)]="coupon.input" type="text"></ion-input> </ion-item> </ion-col> <ion-col col-4> <button ion-button small tappable color="secondary" (click)="submitCoupon()" block type="button" [disabled]="!coupon.input">{{ 'SUBMIT' | translate}}</button> </ion-col> </ion-row> <ion-row class="coupon-result" align-items-center margin padding *ngIf="coupon.description"> <ion-col>{{coupon.description}}</ion-col> </ion-row> </ion-grid> </ion-list> <ion-list no-margin margin-top padding-top> <div padding-horizontal> <h3>{{ 'NOTE_SELLER' | translate}}</h3> </div> </ion-list> <div padding> <ion-textarea placeholder="{{ 'NOTE_SELLER_DESC' | translate}}" [(ngModel)]="order.customer_note"></ion-textarea> </div> <ion-list no-margin margin-top padding-top> <div padding-horizontal> <h3>{{ 'SHIPPING_METHOD' | translate}}</h3> <ion-note>{{ 'SHIPPING_METHOD_DESC' | translate}}</ion-note> </div> </ion-list> <ion-list radio-group no-margin margin-vertical (ionChange)="setShipping($event)"> <ng-container *ngFor="let x of shipping_method"> <ion-item mode="ios" *ngIf="(x.enabled && x.method_id != 'free_shipping') || (x.enabled && x.method_id == 'free_shipping' && allowFreeShipping)"> <ion-label>{{x.title}} <span *ngIf="x.settings.cost">({{x.settings.cost ? (x.settings.cost.value | money) : ''}})</span></ion-label> <ion-radio mode="ios" [value]="x | json"></ion-radio> </ion-item> </ng-container> </ion-list> <div padding> <button ion-button block icon-start tappable (click)="next()" [disabled]="shipping_lines.length == 0"> {{ 'NEXT' | translate}} </button> </div> </div> <div *ngSwitchCase="'payment'"> <ion-list margin-bottom> <div padding-horizontal> <h3>{{ 'PAYMENT_METHOD' | translate}}</h3> <ion-note>{{ 'PAYMENT_METHOD_DESC' | translate}}</ion-note> </div> </ion-list> <ion-list radio-group no-margin margin-top margin-bottom (ionChange)="setPayment($event)"> <ng-container *ngFor="let x of payments; let i = index"> <ion-item mode="ios" *ngIf="(x.enabled && x.id != 'razorpay') || (x.enabled && x.id == 'razorpay' && setting.all.settings.currency == 'INR')" [ngClass]="{'section-active': x.open, 'section': !x.open}"> <ion-label> {{x.method_title ? x.method_title : x.title}} <img *ngFor="let x of img[x.id]" [src]="x" /> </ion-label> <ion-radio mode="ios" [value]="x | json"></ion-radio> </ion-item> <ion-list class="accord" no-lines padding no-margin *ngIf="x.open && x.description" [ngClass]="{'section-active': x.open, 'section': !x.open}"> <ion-item [innerHTML]="x.description" no-padding></ion-item> <ion-grid class="stripe-form" *ngIf="x.id == 'stripe'"> <ion-row> <ion-col> <ion-item no-padding> <ion-label floating>Card No</ion-label> <ion-input [(ngModel)]="stripe.no" [class.invalid]="!stripe.no" type="number" min="16" inputmode="numeric" pattern="[0-9]*"></ion-input> </ion-item> </ion-col> </ion-row> <ion-row> <ion-col> <ion-item no-padding> <ion-label floating>Month</ion-label> <ion-select [(ngModel)]="stripe.month" [class.invalid]="!stripe.month"> <ion-option *ngFor="let x of months; let i = index" [value]="i+1">{{x}}</ion-option> </ion-select> </ion-item> </ion-col> <ion-col> <ion-item no-padding> <ion-label floating>Year</ion-label> <ion-select [(ngModel)]="stripe.year" [class.invalid]="!stripe.year"> <ion-option *ngFor="let x of years; let i = index" [value]="x">{{x}}</ion-option> </ion-select> </ion-item> </ion-col> <ion-col> <ion-item no-padding> <ion-label floating>CVC</ion-label> <ion-input [(ngModel)]="stripe.cvc" type="password" min="3" [class.invalid]="!stripe.cvc" min="3" inputmode="numeric" pattern="[0-9]*"></ion-input> </ion-item> </ion-col> </ion-row> </ion-grid> </ion-list> </ng-container> </ion-list> <ion-list margin-bottom padding-top> <div padding-horizontal> <h3>Total</h3> </div> </ion-list> <ion-list no-margin margin-top class="total"> <ion-item> {{ 'SUBTOTAL' | translate}} ({{cart.totalQtyDetail}} items) <span item-end>{{cart.total | money}}</span> </ion-item> <ion-item *ngIf="coupon.description"> Coupon: {{order.coupon_lines[0].code}} <span item-end>{{(order.coupon_lines[0].discount * -1) | money}}</span> </ion-item> <ion-item *ngIf="shipping_lines[0]"> {{ 'SHIPPING' | translate}} ({{shipping_lines[0].method_title}}) <span item-end>{{shipping_lines[0].total | money}}</span> </ion-item> <ion-item> Total <span item-end>{{total | money}}</span> </ion-item> </ion-list> <div padding> <button ion-button block icon-start tappable (click)="confirm()" [disabled]="!order.payment_method || ((order.payment_method == 'stripe') && (!stripe.no || !stripe.month || !stripe.year || !stripe.cvc))"> {{ 'BUY_NOW' | translate}} {{total | money}} </button> </div> </div>
Posts: 1
Participants: 1