geer-builder 1.2.957 → 1.2.959

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/GCheckout.vue CHANGED
@@ -208,6 +208,23 @@
208
208
  <div v-if="!is_adspro" class="text-right">{{payment_method.payment_method_id =='gc_points' ? 'GC' : main_currency}} {{$_formatNumber(this.checkout_info.shipping_total, { decimal: 2})}}</div>
209
209
  <div v-if="(this.checkout_info.voucher_total*-1)>0">Voucher Discount: </div>
210
210
  <div v-if="(this.checkout_info.voucher_total*-1)>0" class="text-right">{{payment_method.payment_method_id =='gc_points' ? 'GC' : main_currency}} -{{$_formatNumber(this.checkout_info.voucher_total, { decimal: 2})}}</div>
211
+ <!-- Coupon Code Input -->
212
+ <div v-if="show_coupon_code" style="grid-column: 1 / -1;" class="q-mt-sm q-mb-sm">
213
+ <div style="display:flex; align-items:center;">
214
+ <q-input dense outlined v-model="coupon_code_input" label="Coupon Code"
215
+ @input="coupon_code_input = coupon_code_input.toUpperCase()"
216
+ style="flex:1;" class="q-mr-sm"></q-input>
217
+ <q-btn :loading="is_coupon_loading" dense color="primary" label="Apply"
218
+ @click="applyProductCoupon" no-caps></q-btn>
219
+ <q-btn v-if="applied_product_coupon" dense flat color="negative" icon="close"
220
+ @click="removeProductCoupon" class="q-ml-xs"></q-btn>
221
+ </div>
222
+ </div>
223
+ <!-- Coupon Discount line -->
224
+ <div v-if="show_coupon_code && coupon_discount_total > 0">Coupon Discount: </div>
225
+ <div v-if="show_coupon_code && coupon_discount_total > 0" class="text-right">
226
+ {{payment_method.payment_method_id =='gc_points' ? 'GC' : main_currency}} -{{$_formatNumber(coupon_discount_total, { decimal: 2})}}
227
+ </div>
211
228
  <div v-if="this.public_settings.hasOwnProperty('custom_ecommerce_fee') && payment_method.payment_method_id !='gc_points'">{{public_settings.custom_ecommerce_fee.label}}: </div>
212
229
  <div v-if="this.public_settings.hasOwnProperty('custom_ecommerce_fee') && payment_method.payment_method_id !='gc_points'" class="text-right">{{main_currency}} {{$_formatNumber(custom_fees, { decimal: 2})}}<template v-if="public_settings.hasOwnProperty('custom_ecommerce_fee') && public_settings.custom_ecommerce_fee.percentage">(<b>{{public_settings.custom_ecommerce_fee.value}}%</b>)</template></div>
213
230
  <div><b>Total Payment: </b></div>
@@ -366,6 +383,23 @@
366
383
  <div v-if="this.public_settings.hasOwnProperty('custom_ecommerce_fee') && payment_method.payment_method_id !='gc_points'" >{{main_currency}} {{$_formatNumber(custom_fees, { decimal: 2})}}<template v-if="public_settings.hasOwnProperty('custom_ecommerce_fee') && public_settings.custom_ecommerce_fee.percentage">(<b>{{public_settings.custom_ecommerce_fee.value}}%</b>)</template></div>
367
384
  <div>Shipping Total: </div>
368
385
  <div>{{payment_method.payment_method_id =='gc_points' ? 'GC' : main_currency}} {{$_formatNumber(this.checkout_info.shipping_total, { decimal: 2})}}</div>
386
+ <!-- Coupon Code Input (Mobile) -->
387
+ <div v-if="show_coupon_code" style="grid-column: 1 / -1;" class="q-mt-sm q-mb-sm">
388
+ <div style="display:flex; align-items:center;">
389
+ <q-input dense outlined v-model="coupon_code_input" label="Coupon Code"
390
+ @input="coupon_code_input = coupon_code_input.toUpperCase()"
391
+ style="flex:1;" class="q-mr-sm"></q-input>
392
+ <q-btn :loading="is_coupon_loading" dense color="primary" label="Apply"
393
+ @click="applyProductCoupon" no-caps></q-btn>
394
+ <q-btn v-if="applied_product_coupon" dense flat color="negative" icon="close"
395
+ @click="removeProductCoupon" class="q-ml-xs"></q-btn>
396
+ </div>
397
+ </div>
398
+ <!-- Coupon Discount line (Mobile) -->
399
+ <div v-if="show_coupon_code && coupon_discount_total > 0">Coupon Discount: </div>
400
+ <div v-if="show_coupon_code && coupon_discount_total > 0" class="text-right">
401
+ {{payment_method.payment_method_id =='gc_points' ? 'GC' : main_currency}} -{{$_formatNumber(coupon_discount_total, { decimal: 2})}}
402
+ </div>
369
403
  </div>
370
404
  </div>
371
405
 
@@ -440,7 +474,7 @@ import EcommerceMaintenance from './dialogs/EcommerceMaintenance';
440
474
  export default {
441
475
  components: { EcommerceMaintenance,SelectShippingOptions, AddNewAddressForm ,ProcessCheckoutConfirmDialog, GLoader, axios ,ChooseCourierDialog, SelectVoucherDialog},
442
476
  mixins: [GlobalMixins],
443
- props:{ checkout_list: Array, show_discount_badge: Boolean, is_heartzone: Boolean, is_adspro : Boolean },
477
+ props:{ checkout_list: Array, show_discount_badge: Boolean, is_heartzone: Boolean, is_adspro : Boolean, show_coupon_code: Boolean },
444
478
  data: () =>
445
479
  ({
446
480
  is_branch_pickup:false,
@@ -495,6 +529,10 @@ export default {
495
529
  courier_list_cod:[],
496
530
  pass_merchant_order: {},
497
531
  all_voucher_list:[],
532
+ applied_product_coupon: null,
533
+ coupon_code_input: '',
534
+ coupon_discount_total: 0,
535
+ is_coupon_loading: false,
498
536
  cod_payment_limit:999999,
499
537
  online_payment_limit:999999,
500
538
  hide_voucher:false,
@@ -985,6 +1023,95 @@ export default {
985
1023
  this.pass_merchant_order = Object.assign({},merch);
986
1024
  this.is_select_voucher_open = true;
987
1025
  },
1026
+ async applyProductCoupon()
1027
+ {
1028
+ if (!this.coupon_code_input || !this.coupon_code_input.trim())
1029
+ {
1030
+ this.$q.dialog({ html: true, title: 'Invalid Coupon', message: 'Please enter a coupon code.' });
1031
+ return;
1032
+ }
1033
+ this.is_coupon_loading = true;
1034
+ try
1035
+ {
1036
+ // Collect cart product IDs for backend validation
1037
+ let cart_product_ids = [];
1038
+ for (let m = 0; m < this.groupedProducts.length; m++)
1039
+ {
1040
+ for (let p = 0; p < this.groupedProducts[m].products.length; p++)
1041
+ {
1042
+ let pid = this.groupedProducts[m].products[p].product_id || '';
1043
+ if (pid && cart_product_ids.indexOf(pid) === -1)
1044
+ {
1045
+ cart_product_ids.push(pid);
1046
+ }
1047
+ }
1048
+ }
1049
+ let result = await this.$_fbCall('memberValidateProductCoupon', {
1050
+ coupon_code: this.coupon_code_input.trim().toUpperCase(),
1051
+ cart_product_ids: cart_product_ids
1052
+ });
1053
+ this.applied_product_coupon = result;
1054
+ this.coupon_discount_total = this.computeCouponDiscount();
1055
+ await this.getShippingFee();
1056
+ this.$q.dialog({ html: true, title: 'Coupon Applied', message: 'Coupon code <b>' + this.applied_product_coupon.coupon_code + '</b> applied successfully!' });
1057
+ }
1058
+ catch (error)
1059
+ {
1060
+ this.applied_product_coupon = null;
1061
+ this.coupon_discount_total = 0;
1062
+ this.$q.dialog({ html: true, title: 'Invalid Coupon', message: error.message || 'Invalid coupon code.' });
1063
+ }
1064
+ this.is_coupon_loading = false;
1065
+ },
1066
+ removeProductCoupon()
1067
+ {
1068
+ this.applied_product_coupon = null;
1069
+ this.coupon_code_input = '';
1070
+ this.coupon_discount_total = 0;
1071
+ this.getShippingFee();
1072
+ },
1073
+ computeCouponDiscount()
1074
+ {
1075
+ if (!this.applied_product_coupon) return 0;
1076
+
1077
+ var coupon = this.applied_product_coupon;
1078
+ var product_ids = coupon.product_ids || [];
1079
+ var total_coupon_discount = 0;
1080
+
1081
+ for (var m = 0; m < this.groupedProducts.length; m++)
1082
+ {
1083
+ var merch = this.groupedProducts[m];
1084
+ for (var p = 0; p < merch.products.length; p++)
1085
+ {
1086
+ var prod = merch.products[p];
1087
+ var pid = prod.product_id || (prod.id ? prod.id : '');
1088
+ if (product_ids.indexOf(pid) !== -1)
1089
+ {
1090
+ var unit_price = Number(prod.selling_price);
1091
+ var qty = Number(prod.quantity);
1092
+ var discount_amount = 0;
1093
+
1094
+ if (coupon.discount_type === 'fix_discount')
1095
+ {
1096
+ discount_amount = Number(coupon.discount) * qty;
1097
+ }
1098
+ else if (coupon.discount_type === 'percent')
1099
+ {
1100
+ discount_amount = (unit_price * (Number(coupon.discount) / 100)) * qty;
1101
+ }
1102
+
1103
+ // Cap: cannot make product price go below 0
1104
+ var max_discount = unit_price * qty;
1105
+ if (discount_amount > max_discount)
1106
+ {
1107
+ discount_amount = max_discount;
1108
+ }
1109
+ total_coupon_discount += discount_amount;
1110
+ }
1111
+ }
1112
+ }
1113
+ return Number(total_coupon_discount.toFixed(2));
1114
+ },
988
1115
  courierListChecker(order)
989
1116
  {
990
1117
  // this.courier_settings.courier_list.forEach(cour => {
@@ -2277,6 +2404,13 @@ export default {
2277
2404
  // });
2278
2405
 
2279
2406
  }
2407
+ // Apply product coupon discount (after vouchers, before custom fees)
2408
+ this.coupon_discount_total = 0;
2409
+ if (this.applied_product_coupon)
2410
+ {
2411
+ this.coupon_discount_total = this.computeCouponDiscount();
2412
+ this.checkout_info.grand_total -= this.coupon_discount_total;
2413
+ }
2280
2414
  if(this.public_settings.hasOwnProperty('custom_ecommerce_fee') && this.payment_method.payment_method_id != 'gc_points')
2281
2415
  {
2282
2416
  if(this.public_settings.custom_ecommerce_fee.percentage)
@@ -2380,6 +2514,16 @@ export default {
2380
2514
  },
2381
2515
  async proceedCheckout()
2382
2516
  {
2517
+ // Auto-apply coupon if user typed one but didn't click Apply
2518
+ if (this.show_coupon_code && this.coupon_code_input && this.coupon_code_input.trim() && !this.applied_product_coupon)
2519
+ {
2520
+ await this.applyProductCoupon();
2521
+ if (!this.applied_product_coupon)
2522
+ {
2523
+ return;
2524
+ }
2525
+ }
2526
+
2383
2527
  if(this.show_gcash_fee && this.gcash_fee > 0)
2384
2528
  {
2385
2529
  this.checkout_info.grand_total + this.gcash_fee;
@@ -2552,6 +2696,18 @@ export default {
2552
2696
  },
2553
2697
  async executeProceedCheckout()
2554
2698
  {
2699
+ // Attach product coupon data if applied
2700
+ if (this.applied_product_coupon)
2701
+ {
2702
+ this.checkout_info.applied_product_coupon = {
2703
+ coupon_code: this.applied_product_coupon.coupon_code,
2704
+ coupon_id: this.applied_product_coupon.id,
2705
+ discount_type: this.applied_product_coupon.discount_type,
2706
+ discount: this.applied_product_coupon.discount,
2707
+ product_ids: this.applied_product_coupon.product_ids
2708
+ };
2709
+ this.checkout_info.coupon_discount_total = this.coupon_discount_total;
2710
+ }
2555
2711
  if(this.checkout_info.payment_method.payment_method_id == "wallet")
2556
2712
  {
2557
2713
  this.sale_id = await this.$_fbCall('memberProceedCheckout', this.checkout_info)
@@ -122,11 +122,12 @@ export default
122
122
  {
123
123
  complan_plan.breakdown_complan.map((val) =>
124
124
  {
125
- let res = { icon: val.icon, active: val.active, label: val.label, complan: val.key, amount : 0, last_update: null, show:val.show };
125
+ let extra_keys = val.extra_keys && Array.isArray(val.extra_keys) ? val.extra_keys : [];
126
+ let res = { icon: val.icon, active: val.active, label: val.label, complan: val.key, amount : 0, last_update: null, show:val.show, extra_keys: extra_keys };
126
127
  this.earning_breakdown.forEach((breakdown) =>
127
128
  {
128
129
  let another_keyword = val.key+"_convert";
129
- if(breakdown.id == val.key || breakdown.id == another_keyword)
130
+ if(breakdown.id == val.key || breakdown.id == another_keyword || extra_keys.indexOf(breakdown.id) !== -1)
130
131
  {
131
132
  res.amount = res.amount+breakdown.amount;
132
133
  res.last_update = breakdown.last_update;
@@ -141,9 +142,9 @@ export default
141
142
  }
142
143
  });
143
144
 
144
- for (var key in this.earning_breakdown_slot.temporary_wallet)
145
+ for (var key in this.earning_breakdown_slot.temporary_wallet)
145
146
  {
146
- if(key == val.key)
147
+ if(key == val.key || extra_keys.indexOf(key) !== -1)
147
148
  {
148
149
  res.amount = res.amount +this.earning_breakdown_slot.temporary_wallet[key];
149
150
  }