Merge pull request #2 from avishkarabhishek786/master
merge basic ecommerce structure
This commit is contained in:
commit
f5afb13995
321
index.html
321
index.html
@ -803,7 +803,7 @@
|
|||||||
|
|
||||||
//for cloud apps
|
//for cloud apps
|
||||||
subAdmins: [],
|
subAdmins: [],
|
||||||
application: "eCommerce",
|
application: "eCommerce_test1",
|
||||||
vectorClock: {},
|
vectorClock: {},
|
||||||
appObjects: {},
|
appObjects: {},
|
||||||
generalData: {},
|
generalData: {},
|
||||||
@ -972,7 +972,8 @@
|
|||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="checkoutModalModalLabel">Bill Preview</h5>
|
<h5 class="modal-title" id="checkoutModalModalLabel">Bill Preview</h5>
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"
|
||||||
|
onclick="ecommerce.loggedInUser.user_info.reset_bucket_list()">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -10417,15 +10418,17 @@ Bitcoin.Util = {
|
|||||||
|
|
||||||
parse_flo_comments: async function() {
|
parse_flo_comments: async function() {
|
||||||
text = `masterFLOKey=FNU7DncTsfMc6BJsA1s8Ai23yDotFpagKf
|
text = `masterFLOKey=FNU7DncTsfMc6BJsA1s8Ai23yDotFpagKf
|
||||||
#!#SUBJECT=TEST_ECOMMERCE_8
|
|
||||||
#!#CURRENCY=INR
|
#!#CURRENCY=INR
|
||||||
#!#DATA_TYPE={
|
#!#DATA_TYPE={
|
||||||
"SELLING_PRODUCTS":"RANCHI_SELLING_PRODUCTS_8",
|
"SELLING_PRODUCTS":"ECOMM_SELLING_PRODUCTS",
|
||||||
"BUY_ORDERS":"RANCHI_BUY_ORDERS_8",
|
"BUY_ORDERS":"ECOMM_BUY_ORDERS",
|
||||||
"MESSAGES":"RANCHI_MESSAGES_8",
|
"MESSAGES":"ECOMM_MESSAGES",
|
||||||
"CASHIERS_DATA":"RANCHI_CASHIERS_DATA_8",
|
"CASHIERS_DATA":"ECOMM_CASHIERS_DATA",
|
||||||
"COURIER_DATA":"RANCHI_COURIER_DATA_8",
|
"COURIER_DATA":"ECOMM_COURIER_DATA",
|
||||||
"PURCHASED_ITEMS": "RANCHI_PURCHASED_ITEMS_8"}
|
"CASHIER_APPROVED_BUY_ORDER":"ECOMM_CASHIER_APPROVED_BUY_ORDER",
|
||||||
|
"PURCHASED_ITEMS": "ECOMM_PURCHASED_ITEMS",
|
||||||
|
"PROCESSED_PURCHASED_ITEMS":"ECOMM_PROCESSED_PURCHASED_ITEMS"
|
||||||
|
}
|
||||||
#!#CITY=Ranchi
|
#!#CITY=Ranchi
|
||||||
#!#product_categories=Electronics,Clothes & Accessories,Home Appliances, Food
|
#!#product_categories=Electronics,Clothes & Accessories,Home Appliances, Food
|
||||||
#!#cashiers=
|
#!#cashiers=
|
||||||
@ -10582,13 +10585,13 @@ Bitcoin.Util = {
|
|||||||
LIVE_USER.user_info.display_purchased_items();
|
LIVE_USER.user_info.display_purchased_items();
|
||||||
}
|
}
|
||||||
if(LIVE_USER.user_info.user_role==='CASHIER') {
|
if(LIVE_USER.user_info.user_role==='CASHIER') {
|
||||||
LIVE_USER.user_info.validate_buy_orders()
|
LIVE_USER.user_info.load_buy_orders()
|
||||||
}
|
}
|
||||||
if(LIVE_USER.user_info.user_role==='MANAGER') {
|
if(LIVE_USER.user_info.user_role==='MANAGER') {
|
||||||
LIVE_USER.user_info.get_general_data()
|
LIVE_USER.user_info.get_general_data()
|
||||||
}
|
}
|
||||||
if(LIVE_USER.user_info.user_role==='SELLER') {
|
if(LIVE_USER.user_info.user_role==='SELLER') {
|
||||||
LIVE_USER.user_info.list_products_to_sell();
|
//LIVE_USER.user_info.list_products_to_sell();
|
||||||
await floCloudAPI.requestGeneralData(ecommerce.master_configurations.DATA_TYPE.BUY_ORDERS, {receiverID:myFloID});
|
await floCloudAPI.requestGeneralData(ecommerce.master_configurations.DATA_TYPE.BUY_ORDERS, {receiverID:myFloID});
|
||||||
LIVE_USER.user_info.list_buy_orders();
|
LIVE_USER.user_info.list_buy_orders();
|
||||||
}
|
}
|
||||||
@ -10598,7 +10601,7 @@ Bitcoin.Util = {
|
|||||||
retrieveLatestContent: async function (receiverID = floGlobals.adminID, senderIDs = floGlobals.subAdmins) {
|
retrieveLatestContent: async function (receiverID = floGlobals.adminID, senderIDs = floGlobals.subAdmins) {
|
||||||
showMessage('Loading the latest content')
|
showMessage('Loading the latest content')
|
||||||
const promises = [];
|
const promises = [];
|
||||||
promises.push(floCloudAPI.requestObjectData(ecommerce.master_configurations.SUBJECT, { receiverID, senderIDs }));
|
promises.push(floCloudAPI.requestObjectData(floGlobals.application, { receiverID, senderIDs }));
|
||||||
if(floGlobals.subAdmins.includes(myFloID)) {
|
if(floGlobals.subAdmins.includes(myFloID)) {
|
||||||
promises.push(floCloudAPI.requestGeneralData(ecommerce.master_configurations.DATA_TYPE.SELLING_PRODUCTS,
|
promises.push(floCloudAPI.requestGeneralData(ecommerce.master_configurations.DATA_TYPE.SELLING_PRODUCTS,
|
||||||
{ senderIDs:Object.keys(ecommerce.master_configurations.sellers_list) }))
|
{ senderIDs:Object.keys(ecommerce.master_configurations.sellers_list) }))
|
||||||
@ -10768,7 +10771,7 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
this.product_info.product_static_information.product_flo_id = floCrypto.generateNewID().floID;
|
this.product_info.product_static_information.product_flo_id = floCrypto.generateNewID().floID;
|
||||||
this.product_info.product_static_information.seller_flo_id = ecommerce.loggedInUser.user_info.flo_id||myFloID;
|
this.product_info.product_static_information.seller_flo_id = ecommerce.loggedInUser.user_info.flo_id||myFloID;
|
||||||
this.product_info.product_dynamic_information.lastUpdated = + new Date();
|
this.product_info.product_dynamic_information.datetime = + new Date();
|
||||||
this.product_info.product_dynamic_information.onSale = true;
|
this.product_info.product_dynamic_information.onSale = true;
|
||||||
},
|
},
|
||||||
physical_products: function(product_details) {
|
physical_products: function(product_details) {
|
||||||
@ -10780,8 +10783,8 @@ Bitcoin.Util = {
|
|||||||
this.new_digital_product.product_info.product_static_information.product_type = "DIGITAL";
|
this.new_digital_product.product_info.product_static_information.product_type = "DIGITAL";
|
||||||
},
|
},
|
||||||
get_approved_products_id: function() {
|
get_approved_products_id: function() {
|
||||||
if(typeof floGlobals.appObjects[ecommerce.master_configurations.SUBJECT]=="undefined") return [];
|
if(typeof floGlobals.appObjects[floGlobals.application]=="undefined") return [];
|
||||||
return Object.values(floGlobals.appObjects[ecommerce.master_configurations.SUBJECT].Products)
|
return Object.values(floGlobals.appObjects[floGlobals.application].Products)
|
||||||
.reduce((t, c, i)=>[...Object.values(c)], [])
|
.reduce((t, c, i)=>[...Object.values(c)], [])
|
||||||
.filter(f=>f.product_approved===true)
|
.filter(f=>f.product_approved===true)
|
||||||
.map(m=>m.product_flo_id);
|
.map(m=>m.product_flo_id);
|
||||||
@ -10802,40 +10805,31 @@ Bitcoin.Util = {
|
|||||||
},
|
},
|
||||||
// Segregate admin approved products from general objects
|
// Segregate admin approved products from general objects
|
||||||
get_approved_products_list: async function() {
|
get_approved_products_list: async function() {
|
||||||
try {
|
try {
|
||||||
let generalData = floGlobals.generalData[JSON.stringify(
|
await floCloudAPI.requestGeneralData(ecommerce.master_configurations.DATA_TYPE.SELLING_PRODUCTS,
|
||||||
{ application: floGlobals.application,
|
{ senderIDs:Object.keys(ecommerce.master_configurations.sellers_list) });
|
||||||
type: ecommerce.master_configurations.DATA_TYPE.SELLING_PRODUCTS
|
|
||||||
})];
|
|
||||||
|
|
||||||
if(generalData.length<1) {
|
let generalData = floDapps.getNextGeneralData(
|
||||||
await floCloudAPI.requestGeneralData(ecommerce.master_configurations.DATA_TYPE.SELLING_PRODUCTS,
|
ecommerce.master_configurations.DATA_TYPE.SELLING_PRODUCTS, "0");
|
||||||
{ senderIDs:Object.keys(ecommerce.master_configurations.sellers_list) })
|
|
||||||
|
|
||||||
generalData = floGlobals.generalData[JSON.stringify(
|
|
||||||
{ application: floGlobals.application,
|
|
||||||
type: ecommerce.master_configurations.DATA_TYPE.SELLING_PRODUCTS
|
|
||||||
})];
|
|
||||||
}
|
|
||||||
|
|
||||||
const certified_products = generalData
|
|
||||||
.map(m=>m.message[Object.keys(m.message)[0]])
|
|
||||||
.filter(f=>ecommerce.approved_products_ids
|
|
||||||
.includes(f.product_info.product_static_information.product_flo_id));
|
|
||||||
|
|
||||||
Object.defineProperty(ecommerce, "approved_products_list",
|
const certified_products = generalData
|
||||||
{
|
.map(m=>m.message[Object.keys(m.message)[0]])
|
||||||
value: certified_products,
|
.filter(f=>ecommerce.approved_products_ids
|
||||||
writable: false,
|
.includes(f.product_info.product_static_information.product_flo_id));
|
||||||
configurable: false,
|
|
||||||
enumerable: true
|
|
||||||
});
|
|
||||||
|
|
||||||
return ecommerce.approved_products_list;
|
Object.defineProperty(ecommerce, "approved_products_list",
|
||||||
|
{
|
||||||
} catch (error) {
|
value: certified_products,
|
||||||
throw new Error(error);
|
writable: false,
|
||||||
}
|
configurable: false,
|
||||||
|
enumerable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
return ecommerce.approved_products_list;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(error);
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
get_product_details_by_floId: function(productFloId='') {
|
get_product_details_by_floId: function(productFloId='') {
|
||||||
@ -10855,10 +10849,9 @@ Bitcoin.Util = {
|
|||||||
},
|
},
|
||||||
get_product_details_by_txid: function(txid='') {
|
get_product_details_by_txid: function(txid='') {
|
||||||
try {
|
try {
|
||||||
const latest_buy_orders = floGlobals.generalData[JSON.stringify(
|
const latest_buy_orders = floDapps.getNextGeneralData(
|
||||||
{ application: floGlobals.application,
|
ecommerce.master_configurations.DATA_TYPE.BUY_ORDERS, "0");
|
||||||
type: ecommerce.master_configurations.DATA_TYPE.BUY_ORDERS
|
|
||||||
})];
|
|
||||||
return Object.values(latest_buy_orders)
|
return Object.values(latest_buy_orders)
|
||||||
.filter(f=>f.message.txid===txid)
|
.filter(f=>f.message.txid===txid)
|
||||||
.map(m=>m.message)
|
.map(m=>m.message)
|
||||||
@ -10934,7 +10927,6 @@ Bitcoin.Util = {
|
|||||||
t += `<p><strong>Product Image</strong>: <input type="text" id="${pid}_productimg" class="form-control" value="${p.image}"></p>`;
|
t += `<p><strong>Product Image</strong>: <input type="text" id="${pid}_productimg" class="form-control" value="${p.image}"></p>`;
|
||||||
t += `<p><strong>Product Selling Price</strong>: <input type="text" id="${pid}_productsp" class="form-control" value="${p.selling_price}"></p>`;
|
t += `<p><strong>Product Selling Price</strong>: <input type="text" id="${pid}_productsp" class="form-control" value="${p.selling_price}"></p>`;
|
||||||
t += `<p><strong>Product Location</strong>: <input type="text" id="${pid}_productlocation" class="form-control" value="${p.product_location}"></p>`;
|
t += `<p><strong>Product Location</strong>: <input type="text" id="${pid}_productlocation" class="form-control" value="${p.product_location}"></p>`;
|
||||||
t += `<p><strong>Items Available </strong>: <input type="text" id="${pid}_productitemavail" class="form-control" value="${p.items_available}"></p>`;
|
|
||||||
t += `<p><strong>On Sale</strong>: <input type="text" id="${pid}_productonsale" class="form-control" value="${p.onSale}"></p>`;
|
t += `<p><strong>On Sale</strong>: <input type="text" id="${pid}_productonsale" class="form-control" value="${p.onSale}"></p>`;
|
||||||
t += `<p><button class="btn btn-primary"
|
t += `<p><button class="btn btn-primary"
|
||||||
onclick="ecommerce.loggedInUser.user_info.update_product_status('${pid}')">
|
onclick="ecommerce.loggedInUser.user_info.update_product_status('${pid}')">
|
||||||
@ -10948,22 +10940,31 @@ Bitcoin.Util = {
|
|||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
list_buy_orders: function() {
|
list_buy_orders: async function() {
|
||||||
try {
|
try {
|
||||||
const latest_buy_orders = floGlobals.generalData[JSON.stringify(
|
await floCloudAPI.requestGeneralData(ecommerce.master_configurations.DATA_TYPE.BUY_ORDERS,
|
||||||
{ application: floGlobals.application,
|
{ receiverID: myFloID });
|
||||||
type: ecommerce.master_configurations.DATA_TYPE.BUY_ORDERS
|
|
||||||
})];
|
const latest_buy_orders = floDapps.getNextGeneralData(ecommerce.master_configurations.DATA_TYPE.BUY_ORDERS, "0");
|
||||||
|
|
||||||
|
await floCloudAPI.requestGeneralData(ecommerce.master_configurations.DATA_TYPE.PROCESSED_PURCHASED_ITEMS,
|
||||||
|
{ receiverID: myFloID });
|
||||||
|
|
||||||
|
let all_processed_purcheses = floDapps.getNextGeneralData(ecommerce.master_configurations.DATA_TYPE.PROCESSED_PURCHASED_ITEMS, "0");
|
||||||
|
all_processed_purcheses_hashes = all_processed_purcheses.map(m=>m.message[0].txid);
|
||||||
|
console.log(all_processed_purcheses);
|
||||||
|
|
||||||
const latestBuyOrdersList = document.getElementById('latestBuyOrdersList')
|
const latestBuyOrdersList = document.getElementById('latestBuyOrdersList')
|
||||||
|
|
||||||
let t = ``;
|
let t = ``;
|
||||||
|
|
||||||
for (const buy_order of latest_buy_orders) {
|
for (const buy_order of latest_buy_orders) {
|
||||||
|
if(all_processed_purcheses_hashes.includes(buy_order.message.txid)) continue;
|
||||||
let bo = buy_order.message;
|
let bo = buy_order.message;
|
||||||
let product_dynamic_info = bo.buy_order_data.shopping_list[0].product_info.product_dynamic_information;
|
let product_dynamic_info = bo.buy_order_data.shopping_list[0].product_info.product_dynamic_information;
|
||||||
|
let product_static_info = bo.buy_order_data.shopping_list[0].product_info.product_static_information;
|
||||||
t += `<p>UPI Txid: ${bo.payment_to_vendor_txid}</p>`;
|
t += `<p>UPI Txid: ${bo.payment_to_vendor_txid}</p>`;
|
||||||
t += `<p>Item: ${product_dynamic_info.product_name}: ${bo.buy_order_data.quantity[product_dynamic_info.product_name]}</p>`;
|
t += `<p>Item: ${product_dynamic_info.product_name}: ${bo.buy_order_data.quantity[product_static_info.product_flo_id]}</p>`;
|
||||||
t += `<p>Total Price: ${bo.buy_order_data.final_price}</p>`;
|
t += `<p>Total Price: ${bo.buy_order_data.final_price}</p>`;
|
||||||
t += `<p><button onclick="ecommerce.loggedInUser.user_info.dispatch_product('${bo.txid}')">Dispatch Item</button></p>`;
|
t += `<p><button onclick="ecommerce.loggedInUser.user_info.dispatch_product('${bo.txid}')">Dispatch Item</button></p>`;
|
||||||
t += `<hr>`;
|
t += `<hr>`;
|
||||||
@ -10982,30 +10983,27 @@ Bitcoin.Util = {
|
|||||||
const product_details = latest_buy_orders[0].buy_order_data.shopping_list[0].product_info;
|
const product_details = latest_buy_orders[0].buy_order_data.shopping_list[0].product_info;
|
||||||
const buyer = latest_buy_orders[0].buy_order_data.buyer_flo_id;
|
const buyer = latest_buy_orders[0].buy_order_data.buyer_flo_id;
|
||||||
let product = product_details.product_dynamic_information.product;
|
let product = product_details.product_dynamic_information.product;
|
||||||
|
let expected_delivery = + new Date() + 24*60*60*1000;
|
||||||
|
let vendor_txid = latest_buy_orders[0].payment_to_vendor_txid;
|
||||||
|
|
||||||
|
let commodity = ``;
|
||||||
|
let seller_sig = ``;
|
||||||
|
let signed_item = ``;
|
||||||
|
let item_sent = ``;
|
||||||
|
let item_info = ``;
|
||||||
|
|
||||||
if(product_details.product_static_information.product_type==="DIGITAL") {
|
if(product_details.product_static_information.product_type==="DIGITAL") {
|
||||||
|
|
||||||
switch (product) {
|
switch (product) {
|
||||||
case "MOVIE_TICKETS":
|
case "MOVIE_TICKETS":
|
||||||
|
|
||||||
let ticket = `
|
let item_info = `
|
||||||
Buy_Txid: ${buy_txid}
|
Buy_Txid: ${buy_txid}
|
||||||
Buyer Id: ${buyer}
|
Buyer Id: ${buyer}
|
||||||
Movie: ${product_details.product_dynamic_information.product_name}
|
Movie: ${product_details.product_dynamic_information.product_name}
|
||||||
Movie DateTime: ${product_details.product_dynamic_information.movie_datetime}
|
DateTime: ${product_details.product_dynamic_information.movie_datetime}
|
||||||
`;
|
Cashier_To_Seller_TXID: ${vendor_txid}
|
||||||
|
`;
|
||||||
let seller_sig = floCrypto.signData(ticket, myPrivKey)
|
|
||||||
|
|
||||||
let signed_ticket = ticket+' VendorSignature: '+seller_sig;
|
|
||||||
|
|
||||||
let ticket_sent = await floCloudAPI.sendGeneralData(signed_ticket, ecommerce.master_configurations.DATA_TYPE.PURCHASED_ITEMS,
|
|
||||||
{ receiverID: buyer })
|
|
||||||
|
|
||||||
console.log(ticket_sent);
|
|
||||||
if(typeof ticket_sent == "object") {
|
|
||||||
// add buy_txid to dispatched items table
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -11015,7 +11013,52 @@ Bitcoin.Util = {
|
|||||||
|
|
||||||
} else if(product_details.product_static_information.product_type==="PHYSICAL") {
|
} else if(product_details.product_static_information.product_type==="PHYSICAL") {
|
||||||
|
|
||||||
|
let delivery_datetime = prompt('Enter expected delivery time: ', expected_delivery);
|
||||||
|
|
||||||
|
switch (product) {
|
||||||
|
case "Milko":
|
||||||
|
item_info = `
|
||||||
|
Buy_Txid: ${buy_txid}
|
||||||
|
Buyer Id: ${buyer}
|
||||||
|
Product: ${product_details.product_dynamic_information.product_name}
|
||||||
|
DateTime: ${product_details.product_dynamic_information.datetime}
|
||||||
|
Expected Delivery: ${delivery_datetime}
|
||||||
|
Cashier_To_Seller_TXID: ${vendor_txid}
|
||||||
|
`;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Pencil":
|
||||||
|
item_info = `
|
||||||
|
Buy_Txid: ${buy_txid}
|
||||||
|
Buyer Id: ${buyer}
|
||||||
|
Product: ${product_details.product_dynamic_information.product_name}
|
||||||
|
DateTime: ${product_details.product_dynamic_information.datetime}
|
||||||
|
Expected Delivery: ${delivery_datetime}
|
||||||
|
Cashier_To_Seller_TXID: ${vendor_txid}
|
||||||
|
`;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
seller_sig = floCrypto.signData(item_info, myPrivKey)
|
||||||
|
signed_item = item_info+' VendorSignature: '+seller_sig;
|
||||||
|
|
||||||
|
// Inform buyer
|
||||||
|
floCloudAPI.sendGeneralData(signed_item, ecommerce.master_configurations.DATA_TYPE.PURCHASED_ITEMS,
|
||||||
|
{ receiverID: buyer });
|
||||||
|
|
||||||
|
// Keep a record
|
||||||
|
floCloudAPI.sendGeneralData(latest_buy_orders, ecommerce.master_configurations.DATA_TYPE.PROCESSED_PURCHASED_ITEMS,
|
||||||
|
{ receiverID: myFloID });
|
||||||
|
|
||||||
|
showMessage('Item successfully processed (by Seller).');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
@ -11057,6 +11100,11 @@ Bitcoin.Util = {
|
|||||||
_id);
|
_id);
|
||||||
|
|
||||||
this.preview_shopping_bill();
|
this.preview_shopping_bill();
|
||||||
|
|
||||||
|
|
||||||
|
// let pay_using_wallet = confirm('Do you want to pay using rupee token?');
|
||||||
|
// console.log(pay_using_wallet);
|
||||||
|
// this.checkout(pay_using_wallet);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
@ -11123,6 +11171,8 @@ Bitcoin.Util = {
|
|||||||
// Reset buy price
|
// Reset buy price
|
||||||
this.total_buying_price = 0;
|
this.total_buying_price = 0;
|
||||||
let bill_preview = [];
|
let bill_preview = [];
|
||||||
|
let billPreviewUI = ``;
|
||||||
|
console.log(this.buy_list);
|
||||||
for (const buying_product_info in this.buy_list) {
|
for (const buying_product_info in this.buy_list) {
|
||||||
if (this.buy_list.hasOwnProperty(buying_product_info)) {
|
if (this.buy_list.hasOwnProperty(buying_product_info)) {
|
||||||
const item = this.buy_list[buying_product_info];
|
const item = this.buy_list[buying_product_info];
|
||||||
@ -11138,15 +11188,17 @@ Bitcoin.Util = {
|
|||||||
)) {
|
)) {
|
||||||
|
|
||||||
let item_name = product_details.product_info.product_dynamic_information.product_name;
|
let item_name = product_details.product_info.product_dynamic_information.product_name;
|
||||||
|
let item_flo_id = product_details.product_info.product_static_information.product_flo_id;
|
||||||
|
|
||||||
// Prevent duplicate registration of products in shopping_list
|
// Prevent duplicate registration of products in shopping_list
|
||||||
if(!this.shopping_bill.shopping_list.some(s=>s.product_info.product_static_information.product_flo_id
|
if(!this.shopping_bill.shopping_list.some(s=>s.product_info.product_static_information.product_flo_id
|
||||||
===product_details.product_info.product_static_information.product_flo_id)) {
|
===product_details.product_info.product_static_information.product_flo_id)) {
|
||||||
this.shopping_bill.shopping_list.push(product_details);
|
this.shopping_bill.shopping_list.push(product_details);
|
||||||
|
this.shopping_bill.quantity[item_flo_id] = Number(item.buying_units);
|
||||||
|
} else {
|
||||||
|
this.shopping_bill.quantity[item_flo_id] = this.buy_list.filter(m=>m.product_flo_id===item_flo_id).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.shopping_bill.quantity[item_name] = Number(item.buying_units);
|
|
||||||
|
|
||||||
bill_preview.push({
|
bill_preview.push({
|
||||||
"product": item_name,
|
"product": item_name,
|
||||||
"price": product_details.product_info.product_dynamic_information.selling_price,
|
"price": product_details.product_info.product_dynamic_information.selling_price,
|
||||||
@ -11160,6 +11212,7 @@ Bitcoin.Util = {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.error(`Product with id ${item.product_flo_id} not found`);
|
console.error(`Product with id ${item.product_flo_id} not found`);
|
||||||
continue;
|
continue;
|
||||||
@ -11173,15 +11226,19 @@ Bitcoin.Util = {
|
|||||||
this.final_price = to_fiat_number(this.total_buying_price);
|
this.final_price = to_fiat_number(this.total_buying_price);
|
||||||
this.shopping_bill.final_price = this.final_price;
|
this.shopping_bill.final_price = this.final_price;
|
||||||
console.log(this.shopping_bill);
|
console.log(this.shopping_bill);
|
||||||
//return this.shopping_bill;
|
|
||||||
|
for (const _list of this.shopping_bill.shopping_list) {
|
||||||
|
let sp = _list.product_info.product_dynamic_information.selling_price;
|
||||||
|
let qty = this.shopping_bill.quantity[_list.product_info.product_static_information.product_flo_id];
|
||||||
|
billPreviewUI += `
|
||||||
|
<p>Product: ${_list.product_info.product_dynamic_information.product_name}</p>
|
||||||
|
<p>Price: ${sp}</p>
|
||||||
|
<p>Quantity: ${qty}</p>
|
||||||
|
<p>Total: ${Math.floor(sp*qty)}</p><hr>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
//billPreview
|
billPreviewUI += `<hr><h5>Total: ${this.shopping_bill.final_price}</h5>`;
|
||||||
let billPreviewUI = `
|
|
||||||
<p>Product: ${this.shopping_bill.shopping_list[0].product_info.product_dynamic_information.product_name}</p>
|
|
||||||
<p>Price: ${this.shopping_bill.shopping_list[0].product_info.product_dynamic_information.selling_price}</p>
|
|
||||||
<p>Quantity: ${this.shopping_bill.quantity[this.shopping_bill.shopping_list[0].product_info.product_dynamic_information.product_name]}</p>
|
|
||||||
<h5>Total: ${this.shopping_bill.final_price}</h5>
|
|
||||||
`;
|
|
||||||
|
|
||||||
document.getElementById('billPreview').innerHTML=billPreviewUI;
|
document.getElementById('billPreview').innerHTML=billPreviewUI;
|
||||||
document.getElementById('item_delivery_addr').innerHTML=localStorage.getItem("FloECommerceUserAddress");
|
document.getElementById('item_delivery_addr').innerHTML=localStorage.getItem("FloECommerceUserAddress");
|
||||||
@ -11189,6 +11246,7 @@ Bitcoin.Util = {
|
|||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showMessage('Failed to preview shopping list', 'ERROR');
|
showMessage('Failed to preview shopping list', 'ERROR');
|
||||||
|
this.reset_bucket_list();
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -11305,15 +11363,19 @@ Bitcoin.Util = {
|
|||||||
// Store info in local history
|
// Store info in local history
|
||||||
compactIDB.addData('my_orders_history', buy_order_object, buy_order_object.txid);
|
compactIDB.addData('my_orders_history', buy_order_object, buy_order_object.txid);
|
||||||
|
|
||||||
floCloudAPI.sendGeneralData(buy_order_object, ecommerce.master_configurations.DATA_TYPE.BUY_ORDERS,
|
let send_payment_info = await floCloudAPI.sendGeneralData(buy_order_object, ecommerce.master_configurations.DATA_TYPE.BUY_ORDERS,
|
||||||
{receiverID:cashier});
|
{receiverID:cashier});
|
||||||
|
|
||||||
|
console.log(send_payment_info);
|
||||||
|
|
||||||
|
showMessage('Payment request sent to cashier.')
|
||||||
|
|
||||||
// const payment_info_data = {
|
// const payment_info_data = {
|
||||||
// payment_amount: this.final_price,
|
// payment_amount: this.final_price,
|
||||||
// cashier: cashier,
|
// cashier: cashier,
|
||||||
// }
|
// }
|
||||||
|
|
||||||
//this.proceed_to_payment(payment_info_data);
|
// this.proceed_to_payment(payment_info_data);
|
||||||
this.reset_bucket_list();
|
this.reset_bucket_list();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11363,8 +11425,7 @@ Bitcoin.Util = {
|
|||||||
try {
|
try {
|
||||||
const myProducts = ecommerce.approved_products_list;
|
const myProducts = ecommerce.approved_products_list;
|
||||||
const mySellingProducts = myProducts.filter(f=>
|
const mySellingProducts = myProducts.filter(f=>
|
||||||
(f.product_info.product_dynamic_information.onSale===true
|
(f.product_info.product_dynamic_information.onSale===true));
|
||||||
&& f.product_info.product_dynamic_information.items_available>0));
|
|
||||||
console.table(mySellingProducts);
|
console.table(mySellingProducts);
|
||||||
let t = ``;
|
let t = ``;
|
||||||
for (const product of mySellingProducts) {
|
for (const product of mySellingProducts) {
|
||||||
@ -11406,10 +11467,9 @@ Bitcoin.Util = {
|
|||||||
},
|
},
|
||||||
display_purchased_items: function() {
|
display_purchased_items: function() {
|
||||||
try {
|
try {
|
||||||
const my_purchased_items = floGlobals.generalData[JSON.stringify(
|
const my_purchased_items = floDapps.getNextGeneralData(ecommerce.master_configurations.DATA_TYPE.PURCHASED_ITEMS, "0");
|
||||||
{ application: floGlobals.application,
|
|
||||||
type: ecommerce.master_configurations.DATA_TYPE.PURCHASED_ITEMS
|
my_purchased_items.reverse();
|
||||||
})];
|
|
||||||
|
|
||||||
const myPurchasedItemsList = document.getElementById('myPurchasedItemsList')
|
const myPurchasedItemsList = document.getElementById('myPurchasedItemsList')
|
||||||
|
|
||||||
@ -11438,24 +11498,23 @@ Bitcoin.Util = {
|
|||||||
// Start ecommerce in a new city
|
// Start ecommerce in a new city
|
||||||
create_new_city_ecommerce: function() {
|
create_new_city_ecommerce: function() {
|
||||||
|
|
||||||
if(typeof ecommerce.master_configurations.SUBJECT!=="string" || ecommerce.master_configurations.SUBJECT.length<2) {
|
if(typeof floGlobals.application!=="string" || floGlobals.application.length<2) {
|
||||||
showMessage('Error: Please provide a subject in master configuration.', 'error');
|
showMessage('Error: Please provide a subject in master configuration.', 'error');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const flo_ecommerce = {};
|
const flo_ecommerce = {};
|
||||||
flo_ecommerce[ecommerce.master_configurations.SUBJECT] = {};
|
|
||||||
|
|
||||||
// Master configurations should come from here
|
// Master configurations should come from here
|
||||||
flo_ecommerce[ecommerce.master_configurations.SUBJECT].master_configurations = '';
|
flo_ecommerce.master_configurations = '';
|
||||||
|
|
||||||
flo_ecommerce[ecommerce.master_configurations.SUBJECT].Orders = {};
|
flo_ecommerce.Orders = {};
|
||||||
flo_ecommerce[ecommerce.master_configurations.SUBJECT].Orders.buy_orders = {};
|
flo_ecommerce.Orders.buy_orders = {};
|
||||||
|
|
||||||
// Every approved product is for sale
|
// Every approved product is for sale
|
||||||
//flo_ecommerce[cityname].Orders.sell_orders = {};
|
//flo_ecommerce[cityname].Orders.sell_orders = {};
|
||||||
|
|
||||||
flo_ecommerce[ecommerce.master_configurations.SUBJECT].Products = {};
|
flo_ecommerce.Products = {};
|
||||||
|
|
||||||
// Messages should be in general object
|
// Messages should be in general object
|
||||||
// flo_ecommerce[cityname].Messages = {};
|
// flo_ecommerce[cityname].Messages = {};
|
||||||
@ -11464,17 +11523,17 @@ Bitcoin.Util = {
|
|||||||
// flo_ecommerce[cityname].Messages["cashier_messages"] = {}
|
// flo_ecommerce[cityname].Messages["cashier_messages"] = {}
|
||||||
// flo_ecommerce[cityname].Messages["delivery_messages"] = {}
|
// flo_ecommerce[cityname].Messages["delivery_messages"] = {}
|
||||||
// flo_ecommerce[cityname].Messages["manager_messages"] = {}
|
// flo_ecommerce[cityname].Messages["manager_messages"] = {}
|
||||||
floGlobals.appObjects[ecommerce.master_configurations.SUBJECT] = flo_ecommerce;
|
floGlobals.appObjects[floGlobals.application] = flo_ecommerce;
|
||||||
|
|
||||||
floCloudAPI.resetObjectData(ecommerce.master_configurations.SUBJECT);
|
floCloudAPI.resetObjectData(floGlobals.application);
|
||||||
},
|
},
|
||||||
// Load ecommerce data relevent to an admin
|
// Load ecommerce data relevent to an admin
|
||||||
get_general_data: async function() {
|
get_general_data: async function() {
|
||||||
await floCloudAPI.requestGeneralData(ecommerce.master_configurations.DATA_TYPE.SELLING_PRODUCTS,
|
await floCloudAPI.requestGeneralData(ecommerce.master_configurations.DATA_TYPE.SELLING_PRODUCTS,
|
||||||
{ senderIDs:Object.keys(ecommerce.master_configurations.sellers_list) })
|
{ senderIDs:Object.keys(ecommerce.master_configurations.sellers_list) })
|
||||||
|
|
||||||
const new_generalData = floGlobals.generalData[JSON.stringify({ application: floGlobals.application, type: ecommerce.master_configurations.DATA_TYPE.SELLING_PRODUCTS })];
|
const new_generalData = floDapps.getNextGeneralData(
|
||||||
|
ecommerce.master_configurations.DATA_TYPE.SELLING_PRODUCTS, "0");
|
||||||
for (const new_data of new_generalData) {
|
for (const new_data of new_generalData) {
|
||||||
if(!Object.keys(ecommerce.master_configurations.sellers_list).includes(new_data.sender)) continue;
|
if(!Object.keys(ecommerce.master_configurations.sellers_list).includes(new_data.sender)) continue;
|
||||||
|
|
||||||
@ -11516,7 +11575,6 @@ Bitcoin.Util = {
|
|||||||
for (const elem in ui_data) {
|
for (const elem in ui_data) {
|
||||||
if (ui_data.hasOwnProperty(elem)) {
|
if (ui_data.hasOwnProperty(elem)) {
|
||||||
if(0) t += ``;
|
if(0) t += ``;
|
||||||
|
|
||||||
t += `<li>${elem}:${ui_data[elem]}</li>`;
|
t += `<li>${elem}:${ui_data[elem]}</li>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -11528,8 +11586,9 @@ Bitcoin.Util = {
|
|||||||
// Approve only static values of a product
|
// Approve only static values of a product
|
||||||
approve_seller_item: function(productId) {
|
approve_seller_item: function(productId) {
|
||||||
try {
|
try {
|
||||||
const new_generalData = floGlobals.generalData[JSON.stringify({ application: floGlobals.application,
|
const new_generalData = floDapps.getNextGeneralData(
|
||||||
type: ecommerce.master_configurations.DATA_TYPE.SELLING_PRODUCTS })];
|
ecommerce.master_configurations.DATA_TYPE.SELLING_PRODUCTS, "0");
|
||||||
|
|
||||||
const mapped = new_generalData.map(m=>m.message);
|
const mapped = new_generalData.map(m=>m.message);
|
||||||
const filtered = Object.values(mapped)
|
const filtered = Object.values(mapped)
|
||||||
.filter(key => Object.keys(key)[0]===productId);
|
.filter(key => Object.keys(key)[0]===productId);
|
||||||
@ -11549,7 +11608,7 @@ Bitcoin.Util = {
|
|||||||
|
|
||||||
console.log(admin_approval_signature);
|
console.log(admin_approval_signature);
|
||||||
|
|
||||||
const ROOT_OBJECT = floGlobals.appObjects[ecommerce.master_configurations.SUBJECT];
|
const ROOT_OBJECT = floGlobals.appObjects[floGlobals.application];
|
||||||
|
|
||||||
if(typeof ROOT_OBJECT !== "object" || ROOT_OBJECT==null) {
|
if(typeof ROOT_OBJECT !== "object" || ROOT_OBJECT==null) {
|
||||||
showMessage("Undefined Object. Approval process failed.", "ERROR");
|
showMessage("Undefined Object. Approval process failed.", "ERROR");
|
||||||
@ -11566,7 +11625,8 @@ Bitcoin.Util = {
|
|||||||
ROOT_OBJECT.Products[product_static_info.seller_flo_id]
|
ROOT_OBJECT.Products[product_static_info.seller_flo_id]
|
||||||
[product_static_info.product_flo_id] = admin_approval_signature;
|
[product_static_info.product_flo_id] = admin_approval_signature;
|
||||||
|
|
||||||
floCloudAPI.updateObjectData(ecommerce.master_configurations.SUBJECT).then(result => {
|
floCloudAPI.updateObjectData(floGlobals.application).then(result => {
|
||||||
|
console.log(result);
|
||||||
ecommerce.actions.retrieveLatestContent();
|
ecommerce.actions.retrieveLatestContent();
|
||||||
showMessage(`Product ID ${product_static_info.product_flo_id} approved successfully.`);
|
showMessage(`Product ID ${product_static_info.product_flo_id} approved successfully.`);
|
||||||
return true;
|
return true;
|
||||||
@ -11587,10 +11647,8 @@ Bitcoin.Util = {
|
|||||||
ecommerce.master_configurations.DATA_TYPE.BUY_ORDERS,
|
ecommerce.master_configurations.DATA_TYPE.BUY_ORDERS,
|
||||||
{receiverID:myFloID});
|
{receiverID:myFloID});
|
||||||
|
|
||||||
const recent_buy_orders_req = floGlobals.generalData[JSON.stringify(
|
const recent_buy_orders_req = floDapps.getNextGeneralData(
|
||||||
{ application: floGlobals.application,
|
ecommerce.master_configurations.DATA_TYPE.BUY_ORDERS, "0");
|
||||||
type: ecommerce.master_configurations.DATA_TYPE.BUY_ORDERS
|
|
||||||
})];
|
|
||||||
|
|
||||||
ecommerce.recent_buy_orders = recent_buy_orders_req;
|
ecommerce.recent_buy_orders = recent_buy_orders_req;
|
||||||
return ecommerce.recent_buy_orders;
|
return ecommerce.recent_buy_orders;
|
||||||
@ -11598,7 +11656,7 @@ Bitcoin.Util = {
|
|||||||
throw new Error(error)
|
throw new Error(error)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
validate_buy_orders: async function() {
|
load_buy_orders: async function() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.retrieve_latest_buy_orders();
|
await this.retrieve_latest_buy_orders();
|
||||||
@ -11635,7 +11693,7 @@ Bitcoin.Util = {
|
|||||||
if(ecommerce.approved_products_ids
|
if(ecommerce.approved_products_ids
|
||||||
.includes(current_elem_info.product_static_information.product_flo_id)) {
|
.includes(current_elem_info.product_static_information.product_flo_id)) {
|
||||||
total += current_elem_info.product_dynamic_information.selling_price
|
total += current_elem_info.product_dynamic_information.selling_price
|
||||||
* buyOrderData.quantity[current_elem_info.product_dynamic_information.product_name];
|
* buyOrderData.quantity[current_elem_info.product_static_information.product_flo_id];
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
}, 0);
|
}, 0);
|
||||||
@ -11653,7 +11711,7 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.load_buy_orders(buyOrderUIObject);
|
this.load_buy_ordersUI(buyOrderUIObject);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showMessage(`Failed to load buy orders`, 'ERROR');
|
showMessage(`Failed to load buy orders`, 'ERROR');
|
||||||
@ -11661,7 +11719,7 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
load_buy_orders: async function(txid_array=[]) {
|
load_buy_ordersUI: async function(txid_array=[]) {
|
||||||
try {
|
try {
|
||||||
const approved_buys = await compactIDB.readAllData('approved_buy_orders')
|
const approved_buys = await compactIDB.readAllData('approved_buy_orders')
|
||||||
const approved_buys_txids = Object.values(approved_buys).map(m=>m.txid)
|
const approved_buys_txids = Object.values(approved_buys).map(m=>m.txid)
|
||||||
@ -11691,13 +11749,26 @@ Bitcoin.Util = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Sign and send to shopkeeper flo id
|
// Sign and send to shopkeeper flo id
|
||||||
approve_buy_orders: function(txid='') {
|
approve_buy_orders: async function(txid='') {
|
||||||
try {
|
try {
|
||||||
const payment_to_vendor_txid = prompt("Please enter the txid for payment to vendor: ", "");
|
|
||||||
if (typeof(payment_to_vendor_txid)!=="string" || payment_to_vendor_txid.length<1) return;
|
|
||||||
const validated_buy_order_array = ecommerce.products.get_product_details_by_txid(txid);
|
const validated_buy_order_array = ecommerce.products.get_product_details_by_txid(txid);
|
||||||
console.log(validated_buy_order_array);
|
console.log(validated_buy_order_array);
|
||||||
|
|
||||||
|
const vendor_pub_key = validated_buy_order_array[0].buy_order_data["shopping_list"][0]["seller_product_certificate"]["seller_public_key"];
|
||||||
|
const vendor_flo_id = bitjs.pubkey2address(vendor_pub_key);
|
||||||
|
if(typeof vendor_flo_id !== "string" || vendor_flo_id.length<1) throw new Error('Invalid Vendor Id.');
|
||||||
|
|
||||||
|
const final_price = Number(validated_buy_order_array[0].buy_order_data.final_price);
|
||||||
|
if(final_price<=0) throw new Error("Invalid final price");
|
||||||
|
const flo_comment = `transfer ${final_price} rupee#`;
|
||||||
|
const payment_to_vendor_txid = await floBlockchainAPI.sendTx(myFloID, vendor_flo_id, 0.0001, myPrivKey, flo_comment)
|
||||||
|
console.log(payment_to_vendor_txid);
|
||||||
|
if(typeof payment_to_vendor_txid !== "string") {
|
||||||
|
this.message = `Transaction unsuccessfull. You can try payment through UPI to continue.`;
|
||||||
|
alert(this.message);
|
||||||
|
throw new Error(this.message);
|
||||||
|
}
|
||||||
|
|
||||||
const validated_buy_order = validated_buy_order_array[0];
|
const validated_buy_order = validated_buy_order_array[0];
|
||||||
validated_buy_order.status = "PAYMENT_TRANSFERRED_FROM_CASHIER_TO_VENDOR";
|
validated_buy_order.status = "PAYMENT_TRANSFERRED_FROM_CASHIER_TO_VENDOR";
|
||||||
validated_buy_order.payment_to_vendor_txid = payment_to_vendor_txid;
|
validated_buy_order.payment_to_vendor_txid = payment_to_vendor_txid;
|
||||||
@ -11714,11 +11785,17 @@ Bitcoin.Util = {
|
|||||||
const vendor_addr = validated_buy_order.buy_order_data.shopping_list[0].product_info.product_static_information.seller_flo_id;
|
const vendor_addr = validated_buy_order.buy_order_data.shopping_list[0].product_info.product_static_information.seller_flo_id;
|
||||||
|
|
||||||
floCloudAPI.sendGeneralData(validated_buy_order, ecommerce.master_configurations.DATA_TYPE.BUY_ORDERS,
|
floCloudAPI.sendGeneralData(validated_buy_order, ecommerce.master_configurations.DATA_TYPE.BUY_ORDERS,
|
||||||
{receiverID:vendor_addr, senderIDs: [myFloID]});
|
{receiverID:vendor_addr});
|
||||||
|
|
||||||
compactIDB.addData("approved_buy_orders", validated_buy_order, txid);
|
compactIDB.addData("approved_buy_orders", validated_buy_order, txid);
|
||||||
|
|
||||||
// Can inform buyer
|
// Can inform buyer
|
||||||
|
floCloudAPI.sendGeneralData(validated_buy_order, ecommerce.master_configurations.DATA_TYPE.CASHIER_APPROVED_BUY_ORDER,
|
||||||
|
{receiverID:validated_buy_order_array[0].buy_order_data.buyer_flo_id});
|
||||||
|
|
||||||
|
showMessage('The order was successfuly approved');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showMessage('Errror');
|
showMessage('Errror');
|
||||||
@ -11727,6 +11804,12 @@ Bitcoin.Util = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<!-- Courier functions -->
|
||||||
|
<script>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
||||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user