Having trouble saving multiple items when I use the check out the system will remove all multiple items and print only one

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>&nbsp;</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>