admin

Connecting to Secure Database...
Food Orders
0
Cloth Orders
0
Paid YT Deals
0
Comm. YT Deals
0
Insta Deals
0
FB Deals
0
Pend. Items
0
Food Drivers
0
Cloth Drivers
0

Live Food Orders

Loading...

Live Cloth Orders

Loading...

Active Delivery Partners

🍔 Food Drivers

Loading...

👕 Cloth Drivers

Loading...

Paid YT Channels

Loading...

Comm. YT Channels (Owner Access)

Channel NameSubsAction
Loading...

Instagram Deals

UsernameFollowersAction
Loading...

Facebook Deals

Page NameFollowersAction
Loading...

Pending Items

Loading...

Tailors / Laundry

Loading...

Food Restaurants

Loading...

Uploading Page

🎥 Content Portal

Secure Video & Thumbnail Submission

Translate this page:
Upload Your Work Safely

PT Seva Creators, apni Video aur Thumbnail safe tarike se submit karne ke liye niche diye gaye niyam padhein aur upload button par click karein.

GOLDEN RULES (ज़रूरी नियम)

  • Video (.mp4) aur Thumbnail (.jpg/.png) ka naam ekdum SAME hona chahiye.
    Catering_Video.mp4
    Catering_Video.jpg
  • Admin ne jo 'Topic Name' diya hai, exact wahi naam copy-paste karein. Koi extra space ya spelling mistake na karein.
Click Here to Upload
Secured via Google Forms
© 2026 PT SEVA. All rights reserved.

Admin Dashboard html code

Connecting to Secure Database...
Food
Orders
0
Cloth
Orders
0
Pending
Channels
0
Owner
Access
0
Pending
Items
0
Food
Drivers
0
Cloth
Drivers
0

Live Food Orders

Order IDAmountStatus
Loading...

Live Cloth Orders

Order IDAmountStatus
Loading...

Active Delivery Partners

🍔 Food Drivers

Loading...

👕 Cloth Drivers

Loading...

Pending Channels

ChannelPriceUTR IDAction
Loading...

Ch. Listing - After Owner Access

Channel NameSubsAction
Loading...

Pending Items

ItemPriceUTR IDAction
Loading...

Tailors / Laundry

Vendor NameBal.Status
Loading...

Food Restaurants

Shop NameToggle
Loading...

Admin Dashboard GAS script Code

// 📊 CHARO SHEETS KI ID const foodSheetId = '1NjqHSgvmcD6Oo7Xd6VUcIRLG-5P57x6WQkoTCveUeqg'; const listSheetId = '1e9Wxh3cps3Bgw-9zCzZ7uA88gcLRK5YYlNs7t1-NoYg'; const clothSheetId = '1LvFnqRaWJPp-FoxSR0iomBjXoP-mDbawnBHj26zx23M'; const ownerAccessSheetId = '15KTshizI8H48SbXJfwu7LPQUAo-qkxMYQ4JTcXn2AVw'; // 🚀 NAYI SERVICE (4th Sheet) // ========================================== // 📥 1. DATA FETCHING (GET) - WITH EXACT ROW NUMBERS // ========================================== function doGet(e) { try { const foodSs = SpreadsheetApp.openById(foodSheetId); const listSs = SpreadsheetApp.openById(listSheetId); const clothSs = SpreadsheetApp.openById(clothSheetId); const ownerSs = SpreadsheetApp.openById(ownerAccessSheetId); // Nayi sheet open ki // 🚀 O(1) ROW NUMBER ENGINE const getSafeDataWithRow = (ss, name) => { const sheet = ss.getSheetByName(name); if (!sheet) return []; const data = sheet.getDataRange().getValues(); const result = []; for(let i=1; i r[0] && String(r[11]).toLowerCase() !== 'delivered' && String(r[11]).toLowerCase() !== 'cancelled' && String(r[11]).toLowerCase() !== 'refunded') .map(r => [r[1], r[6], r[11], r[r.length-1]]); const dData = getSafeDataWithRow(foodSs, "DeliveryPartners"); const drivers = dData.filter(r => r[0]).map(r => [r[1], r[2], r[10], r[12], r[r.length-1]]); const rData = getSafeDataWithRow(foodSs, "Restaurants"); const restaurants = rData.filter(r => r[0]).map(r => [r[3], r[10], r[r.length-1]]); // --- 📺 PRE-LISTING & ITEMS DATA (WITH UTR) --- const dealData = getSafeDataWithRow(listSs, "PTSDeals"); const deals = dealData.filter(r => r[0] && String(r[13]).toLowerCase() === 'pending') .map(r => [r[2], r[8], r[12], r[13], r[r.length-1]]); // r[12] is Col M (UTR) const iData = getSafeDataWithRow(listSs, "PTSitems"); const items = iData.filter(r => r[0] && String(r[11]).toLowerCase() === 'pending') .map(r => [r[2], r[3], r[10], r[11], r[r.length-1]]); // r[10] is Col K (UTR) // --- 👕 CLOTH DATA --- const coData = getSafeDataWithRow(clothSs, "Orders_Master"); const clothOrders = coData.filter(r => r[0] && String(r[14]).toLowerCase() !== 'delivered' && String(r[14]).toLowerCase() !== 'cancelled') .map(r => [r[1], r[8], r[14], r[r.length-1]]); const cdData = getSafeDataWithRow(clothSs, "DeliveryPartners"); const clothDrivers = cdData.filter(r => r[0]).map(r => [r[1], r[2], r[11], r[8], r[r.length-1]]); const cvData = getSafeDataWithRow(clothSs, "Vendor_Master"); const clothVendors = cvData.filter(r => r[0]).map(r => [r[2], r[8], r[7], r[r.length-1]]); // --- 🤝 4. CHANNEL LISTING - AFTER OWNER ACCESS (NEW SERVICE) --- const ownerData = getSafeDataWithRow(ownerSs, "New Channels"); // Columns: r[0]=Timestamp, r[3]=Status (Col D), r[5]=Name (Col F), r[6]=Subs (Col G) const ownerAccessDeals = ownerData.filter(r => r[0] && String(r[3]).toLowerCase() === 'pending') .map(r => [r[5], r[6], r[3], r[r.length-1]]); // Return mapped data safely return ContentService.createTextOutput(JSON.stringify({ success: true, type: 'READ', orders, drivers, restaurants, deals, items, clothOrders, clothDrivers, clothVendors, ownerAccessDeals // NAYA DATA ADD KIYA })).setMimeType(ContentService.MimeType.JSON); } catch(err) { return ContentService.createTextOutput(JSON.stringify({success: false, error: err.toString()})).setMimeType(ContentService.MimeType.JSON); } } // ========================================== // 📤 2. DIRECT ROW UPDATING (POST) // ========================================== function doPost(e) { try { if (!e || !e.postData || !e.postData.contents) { return ContentService.createTextOutput(JSON.stringify({success: false, error: "Empty Payload"})).setMimeType(ContentService.MimeType.JSON); } const data = JSON.parse(e.postData.contents); const action = data.action; const rowNum = Number(data.id); const newValue = data.newValue; const channelId = data.extraData; // 🚀 HTML se aayi hui Channel ID (Agar ho toh) if(!rowNum || rowNum < 2) { return ContentService.createTextOutput(JSON.stringify({success: false, error: "Invalid Row Number"})).setMimeType(ContentService.MimeType.JSON); } const foodSs = SpreadsheetApp.openById(foodSheetId); const listSs = SpreadsheetApp.openById(listSheetId); const clothSs = SpreadsheetApp.openById(clothSheetId); const ownerSs = SpreadsheetApp.openById(ownerAccessSheetId); // Nayi sheet open ki let sheet, colNum; // Routing Logic to map actions to target sheet & column if (action === 'update_order') { sheet = foodSs.getSheetByName("Orders"); colNum = 12; } else if (action === 'update_driver') { sheet = foodSs.getSheetByName("DeliveryPartners"); colNum = 13; } else if (action === 'update_restaurant') { sheet = foodSs.getSheetByName("Restaurants"); colNum = 11; } else if (action === 'update_deal') { sheet = listSs.getSheetByName("PTSDeals"); colNum = 14; } else if (action === 'update_item') { sheet = listSs.getSheetByName("PTSitems"); colNum = 12; } else if (action === 'update_cloth_order') { sheet = clothSs.getSheetByName("Orders_Master"); colNum = 15; } else if (action === 'update_cloth_driver') { sheet = clothSs.getSheetByName("DeliveryPartners"); colNum = 9; } else if (action === 'update_cloth_vendor') { sheet = clothSs.getSheetByName("Vendor_Master"); colNum = 8; } // 🚀 ACTION FOR: "After Owner Access" Deals (Status is in Column D -> 4) else if (action === 'update_owner_access') { sheet = ownerSs.getSheetByName("Channel_Deals_Database"); colNum = 4; } else { return ContentService.createTextOutput(JSON.stringify({success: false, error: "Unknown Action"})).setMimeType(ContentService.MimeType.JSON); } if(sheet) { // Step 1: Normal Status Update karein sheet.getRange(rowNum, colNum).setValue(newValue); // 🚀 Step 2: Agar Owner Access approve hua hai aur Channel ID aayi hai, toh Col E me likhein if (action === 'update_owner_access' && newValue === 'APPROVED' && channelId) { sheet.getRange(rowNum, 5).setValue(channelId); // Column E = 5 } SpreadsheetApp.flush(); return ContentService.createTextOutput(JSON.stringify({success: true, type: 'WRITE', log: `Row ${rowNum} updated!`})).setMimeType(ContentService.MimeType.JSON); } else { return ContentService.createTextOutput(JSON.stringify({success: false, error: "Sheet tab not found"})).setMimeType(ContentService.MimeType.JSON); } } catch (err) { return ContentService.createTextOutput(JSON.stringify({success: false, error: err.toString()})).setMimeType(ContentService.MimeType.JSON); } }

PDF Selling System - error solved note

🚀 Google के फ्री टूल्स से बनाया 100% Automated PDF Selling System: मेरा A to Z सफर और चुनौतियाँ

जब hamne अपने Math और English के 'PT Seva Notes' (स्कूल और कम्पटीशन एग्जाम्स के लिए) ऑनलाइन बेचने का प्लान बनाया, तो एक बात साफ थी: hame किसी भी महंगी वेबसाइट, सॉफ्टवेयर या मंथली सब्सक्रिप्शन (जैसे Shopify) पर पैसे बर्बाद नहीं करने थे।

हमारा विज़न था कि पूरा सिस्टम Google के फ्री टूल्स (Blogger, Google Forms, Sheets, Drive) और Google Apps Script (GAS) की कोडिंग पर चले।

शुरुआत में यह बहुत आसान लगा, लेकिन जब ham इसे असल में बनाने उतरे, तो कई ऐसी तकनीकी चुनौतियाँ आईं जिन्होंने पसीने छुड़ा दिए। इस ब्लॉग में मैं शुरू से अंत तक का पूरा सफर शेयर कर रहा हूँ कि hamari क्या परेशानियाँ थीं और hamne उन्हें कैसे हैक (Solve) किया।

🎯 हमारा मास्टर प्लान क्या था?

  1. छात्र Blogger पर आएगा और ₹49 (स्कूल नोट्स) या ₹99 (शॉर्ट ट्रिक्स) का पेमेंट करेगा।

  2. वह वेबसाइट के फॉर्म में अपना UTR नंबर और ईमेल डालेगा।

  3. डेटा Google Sheet में आएगा।

  4. ham UTR चेक करके सिर्फ एक 'Approve' बॉक्स (Checkbox) पर टिक (✅) करेंगे।

  5. जादू (Automation): सिस्टम खुद Google Drive से उस PDF का एक्सेस छात्र की ईमेल पर भेजेगा, उसे एक कन्फर्मेशन ईमेल जाएगा, और शीट में 'Sent ✅' लिख जाएगा।

सब कुछ बढ़िया लग रहा था, लेकिन फिर शुरू हुआ असली खेल...

🚨 चुनौती 1: सिंपल Trigger काम नहीं कर रहा था

सबसे पहले hamne एक onEdit कोड लिखा जो चेकबॉक्स पर टिक करते ही ईमेल भेज दे। लेकिन टिक करने पर कुछ नहीं हुआ!

  • कारण: Google की सिक्योरिटी के हिसाब से, नॉर्मल (सिंपल) onEdit फंक्शन को किसी के अकाउंट से ईमेल भेजने (MailApp) की परमिशन नहीं होती।

  • सॉल्यूशन: hamne फंक्शन का नाम बदला और उसे Apps Script के Installable Triggers (घड़ी वाले आइकॉन) में जाकर मैन्युअली On edit पर सेट किया और अपने अकाउंट से एक बार 'Allow' किया। इसके बाद ईमेल धड़ाधड़ जाने लगे!

🚨 चुनौती 2: 1 साल और 3 साल का 'सब्सक्रिप्शन मॉडल'

ham नोट्स का लाइफटाइम एक्सेस नहीं देना चाहते थे। 9वीं-12वीं के लिए 1 साल और कम्पटीशन (Vyapam/SSC) के लिए 3 साल की वैलिडिटी चाहिए थी। लेकिन 'Anyone with the link' वाले सिस्टम में एक्सपायरी डेट नहीं लग सकती।

  • सॉल्यूशन: hamne कोड को अपग्रेड किया। अब कोड लिंक देने के बजाय, छात्र की Email ID को सीधे hamari Drive फाइल में 'Viewer' के तौर पर ऐड करता है। साथ ही, hamne एक "Auto-Cleaner" (Time-driven trigger) कोड बनाया जो रोज़ रात 12 बजे चलता है और जिन छात्रों का टाइम पूरा हो गया है, उनका एक्सेस चुपचाप हटा देता है।

🚨 चुनौती 3 (सबसे बड़ा सिरदर्द): Blogger से PDF Upload करने पर Permission Error

hamari सबसे बड़ी ख्वाहिश थी कि नया कोर्स या PDF जोड़ने के लिए बार-बार कोड न खोलना पड़े। hamne Blogger पर एक Private Admin Dashboard बनाया, ताकि वहाँ से PDF अपलोड करें और वह सीधे Google Drive में सेव होकर Sheet में लिंक दे दे।

लेकिन जैसे ही अपलोड पर क्लिक किया, एक खूंखार लाल एरर आया: Exception: You do not have permission to call DriveApp.createFile.

  • The Ultimate Solution (ब्रह्मास्त्र): इस ज़िद्दी सिक्योरिटी को तोड़ने के लिए hame सिस्टम की जड़ों में जाना पड़ा। hamne Apps Script की सेटिंग्स में जाकर छुपी हुई appsscript.json (Manifest file) को अनहाइड (Unhide) किया। उसमें oauthScopes का कोड डालकर Google को लिखित में कमांड दी कि hame Drive, Sheets और Email का फुल एक्सेस चाहिए। फिर एक डमी फंक्शन रन करके परमिशन 'Allow' की और काम हो गया!

🚨 चुनौती 4: "Invisible Spaces" का जाल (Syntax Error)

परमिशन फिक्स करने के बाद जब hamne नया कोड पेस्ट करके डिप्लॉय करना चाहा, तो एक अजीब सा Syntax error: Missing ; आने लगा, जबकि कोड 100% सही था।

  • कारण: चैट या नोटपैड से कोड कॉपी करते समय कुछ "अदृश्य खाली जगह" (Invisible formatting) आ गई थी।

  • सॉल्यूशन: hamne 'Clean Paste' का तरीका अपनाया। कोड को सीधे Paste करने के बजाय Ctrl + Shift + V दबाकर पेस्ट किया। इससे सारा कचरा हट गया!

🚨 चुनौती 5: शीट में डेटा गायब होने का रहस्य (The Ghost Row Trap)

जब सिस्टम लाइव हुआ और hamne टेस्ट ऑर्डर डाला, तो वह शीट में ऊपर दिखा ही नहीं!

  • कारण: hamne होशियारी दिखाते हुए पहले ही शीट में 1000 लाइन तक 'Approve' वाले खाली चेकबॉक्स लगा दिए थे। Google Script का नियम है कि वह डेटा सबसे आखिरी "भरी हुई" लाइन के नीचे डालता है। तो नया ऑर्डर सीधे 1001 नंबर की लाइन में जा रहा था!

  • सॉल्यूशन: hamne शीट से सारे एडवांस चेकबॉक्स डिलीट कर दिए। फिर कोड में एक जादुई लाइन (insertCheckboxes()) डाल दी, जिससे जब भी कोई नया ऑर्डर आता है, सिस्टम खुद सिर्फ उसी लाइन में एक नया चेकबॉक्स बना देता है।

🚨 चुनौती 6: Submit बटन पर इमोजी का अजीब कोड (✅)

Blogger के HTML एडिटर ने hamari एक और परीक्षा ली। जब ham 'Submit' बटन पर ✅ (इमोजी) लगाते, तो सेव करते ही वह अजीब से HTML कोड (&#9989;) में बदल जाता।

  • सॉल्यूशन: hamne JavaScript में .innerText को हटाकर .innerHTML किया और इमोजी की जगह FontAwesome के पक्के आइकॉन (<i class="fas fa-check-circle"></i>) का इस्तेमाल किया।

🚨 चुनौती 7: बैकएंड को बिना छुए UTR के साथ Price ट्रैक करना (The Smart Hack)

hame एक फीचर और चाहिए था: शीट में UTR नंबर के साथ यह भी दिखे कि बच्चे ने कितने पैसे दिए हैं (ताकि बैंक से मैच करने में आसानी हो)। लेकिन अगर ham शीट में नया कॉलम बनाते, तो हमारा पुराना कोड क्रैश हो सकता था।

  • सॉल्यूशन: hamne बैकएंड को बिल्कुल नहीं छेड़ा! इसके बजाय hamne लैंडिंग पेज के HTML में ही एक 'Smart Hack' लगा दिया। जब बच्चा 'Submit' दबाता है, तो कोड चुपके से UTR और Price को जोड़कर एक बना देता है (जैसे: 123456789012 (₹ 49)) और फिर उसे शीट में भेजता है।

🚨 चुनौती 8: Admin Panel में कैटेगरी की स्पेलिंग मिस्टेक (Smart Datalist)

प्राइवेट एडमिन पैनल से PDF अपलोड करते समय बार-बार कैटेगरी (जैसे 10th, 12th) हाथ से टाइप करनी पड़ रही थी, जिससे फिल्टर बिगड़ने का डर था।

  • सॉल्यूशन: hamne एडमिन पैनल में "Smart Datalist" का फीचर डाला। अब जैसे ही ham एडमिन पेज खोलते हैं, यह पीछे से Google Sheet को पढ़कर सारी पुरानी कैटेगरीज़ को ड्रॉपडाउन में ले आता है। ham लिस्ट से सेलेक्ट भी कर सकते हैं और कोई नई कैटेगरी हो तो टाइप भी कर सकते हैं!

🏆 आख़िर में क्या हुआ? (The Result)

आज हमारा 'PT Seva Notes' का पूरा बैकएंड 100% ऑटोमैटिक है।

  • एक प्राइवेट एडमिन डैशबोर्ड है जहाँ से ham प्राइस, वीडियो और PDF डालते हैं।

  • एक मास्टर Google Sheet है जो खुद-ब-खुद फॉर्म के डेटा और पेमेंट्स को सँभालती है।

  • और एक Apps Script है जो दिन-रात हमारे लिए डिलीवरी बॉय का काम कर रही है।

सीख (Learning): कोडिंग और ऑटोमेशन में एरर आना कोई बुरी बात नहीं है। हर एरर आपको यह सिखाता है कि सिस्टम अंदर से कैसे काम करता है। बस हार नहीं माननी है!