diff --git a/.gitignore b/.gitignore index 24f54f6fa..b6b38a0f4 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ mysite.log venv .idea/* media/ +logs/*.log diff --git a/floodrelief/settings.py b/floodrelief/settings.py index 4bb1d6582..08a5045b7 100644 --- a/floodrelief/settings.py +++ b/floodrelief/settings.py @@ -180,6 +180,9 @@ def get_list(text): 'simple': { 'format': '%(levelname)s %(message)s' }, + 'command': { + 'format': '%(asctime)s %(message)s' + }, }, 'handlers': { 'file': { @@ -188,6 +191,12 @@ def get_list(text): 'filename': 'mysite.log', 'formatter': 'verbose' }, + 'send_volunteer_sms': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'filename': 'logs/send_volunteer_sms.log', + 'formatter': 'command' + }, }, 'loggers': { 'django': { @@ -199,6 +208,10 @@ def get_list(text): 'handlers': ['file'], 'level': 'DEBUG', }, + 'send_volunteer_sms': { + 'handlers': ['send_volunteer_sms'], + 'level': 'DEBUG', + }, } } diff --git a/logs/.addthisfolderingit b/logs/.addthisfolderingit new file mode 100644 index 000000000..e69de29bb diff --git a/mainapp/management/commands/sendvolunteersms.py b/mainapp/management/commands/sendvolunteersms.py new file mode 100644 index 000000000..4fc87c878 --- /dev/null +++ b/mainapp/management/commands/sendvolunteersms.py @@ -0,0 +1,107 @@ +import os + +from django.core.management.base import BaseCommand +from django.core.cache import cache +import requests +from threading import Thread +from datetime import datetime + +from django.conf import settings +import csv +from dateutil import parser +import time + +import logging +import calendar + + +logger = logging.getLogger('send_volunteer_sms') + + +# python manage.py sendvolunteersms +# python manage.py sendvolunteersms /tmp/volunteer.csv +# python manage.py sendvolunteersms --clearcache=1 +class Command(BaseCommand): + # SMS_API_URL = "http://api.esms.kerala.gov.in/fastclient/SMSclient.php" + SMS_API_URL = "http://127.0.0.1:8000/test_send_sms/" + API_USERNAME = os.environ.get("SMS_USER") + API_PASSWORD = os.environ.get("SMS_PASSWORD") + + DEFAULT_CSV = os.path.join(settings.BASE_DIR, + 'mainapp/management/commands/smsvolunteer.csv') + BATCH_MAX = 10 + + msg_url_template = "http://keralarescue.in/c/{sendID}/{timestamp}" + message_template = "Thank you for registering to volunteer. Please click here to confirm {url}" + success_check_cache_key = "SendingFailed_{phone}" + + def add_arguments(self, parser): + parser.add_argument('path', nargs='?', type=str) + parser.add_argument('--clearcache', nargs='?', type=bool) + + @property + def volunteers(self): + with open(self.path, "r") as volunteers: + for volunteer in csv.DictReader(volunteers): + yield volunteer + + @staticmethod + def clean_timestamp(timestamp): + # not clear about this logic just copied from -> sms.py + timestamp = parser.parse(timestamp) + timestamp = calendar.timegm(timestamp.utctimetuple()) + return str(timestamp)[-4:] + + def send_sms(self, payload): + res = requests.get(self.SMS_API_URL, params=payload) + if res.status_code in (200, 201): + cache.set(self.success_check_cache_key.format( + phone=payload["numbers"]), True) + else: + logger.info("failed {} {}".format()) + + def process_batch(self, batch): + tasks = [] + for payload in batch: + self.total_count += 1 + t = Thread(target=self.send_sms, + args=(payload,)) + tasks.append(t) + t.start() + + for task in tasks: + t.join() + + def handle(self, *args, **options): + if options["clearcache"]: + logger.info("clearing cache for sendvolunteersms.") + cache.delete_pattern(self.success_check_cache_key.format(phone="*")) + else: + t1 = time.time() + self.path = options["path"] if options["path"] else self.DEFAULT_CSV + batch = [] + batch_count = 0 + self.total_count = 0 + logger.info("STARTING sendvolunteersms.") + + for volunteer in self.volunteers: + msg_url = self.msg_url_template.format(sendID=volunteer["ID"], + timestamp="{:%Y-%m-%d %H:%M}".format(datetime.now())) + message = self.message_template.format(url=msg_url) + payload = {'username': self.API_USERNAME, + 'password': self.API_PASSWORD, + 'message': message, + 'numbers': volunteer["phone"]} + if not cache.get( + self.success_check_cache_key.format( + phone=payload["numbers"])): + batch.append(payload) + batch_count += 1 + if batch_count == self.BATCH_MAX: + self.process_batch(payload) + batch_count = 0 + batch = [] + if batch: + self.process_batch(batch) + logger.info("{} COMPLETED IN {} Seconds sendvolunteersms.".format(self.total_count, + time.time() - t1)) diff --git a/mainapp/management/commands/smsvolunteer.csv b/mainapp/management/commands/smsvolunteer.csv new file mode 100644 index 000000000..b2898b9db --- /dev/null +++ b/mainapp/management/commands/smsvolunteer.csv @@ -0,0 +1,170 @@ +ID,phone +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 +1,0123456789 +2,9876543210 +3,0612345678 diff --git a/mainapp/migrations/0092_auto_20180828_1428.py b/mainapp/migrations/0092_auto_20180828_1428.py new file mode 100644 index 000000000..000a6dfd5 --- /dev/null +++ b/mainapp/migrations/0092_auto_20180828_1428.py @@ -0,0 +1,28 @@ +# Generated by Django 2.1 on 2018-08-28 08:58 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mainapp', '0091_merge_20180825_1236'), + ] + + operations = [ + migrations.AddField( + model_name='volunteer', + name='date_time', + field=models.TextField(blank=True), + ), + migrations.AddField( + model_name='volunteer', + name='email', + field=models.EmailField(blank=True, max_length=250), + ), + migrations.AddField( + model_name='volunteer', + name='local_body', + field=models.TextField(default='', max_length=250), + ), + ] diff --git a/mainapp/migrations/0092_auto_20180828_1429.py b/mainapp/migrations/0092_auto_20180828_1429.py new file mode 100644 index 000000000..1b8d6d08b --- /dev/null +++ b/mainapp/migrations/0092_auto_20180828_1429.py @@ -0,0 +1,93 @@ +# Generated by Django 2.1 on 2018-08-28 08:59 +import os +from django.db import migrations, models, IntegrityError, transaction +import django.db.models.deletion +import csv +from mainapp.models import districts, LocalBody as ExLocalBody +from django.conf import settings + + +class Populate: + valid_local_body_types = tuple([ex[0] for ex in ExLocalBody.local_body_types][:2]) + CSV_PATH = os.path.join(settings.BASE_DIR, + 'mainapp/migrations/local_bodies.csv') + + def __call__(self, apps, schema_editor): + self.apps = apps + self.schema_editor = schema_editor + self.db_alias = self.schema_editor.connection.alias + self.populate_districts() + self.populate_local_bodies() + + def populate_districts(self): + District = self.apps.get_model("mainapp", "District") + disctrict_objects = [] + for district in districts: + name = district[1].split("-")[0].strip(" ") + disctrict_objects.append(District(code=district[0], + name=name, + described_name=district[1])) + + District.objects.using(self.db_alias).bulk_create(disctrict_objects) + + def get_body_type(self, name): + name = name.lower() + for valid_type in self.valid_local_body_types: + if valid_type in name: + return valid_type + return "panchayat" + + def local_bodies(self, district): + with open(self.CSV_PATH, "r") as file: + for local_body in csv.DictReader(file): + if local_body[district]: + yield {"name": local_body[district], + "type": self.get_body_type( + local_body[district])} + + def populate_local_bodies(self): + District = self.apps.get_model("mainapp", "District") + LocalBody = self.apps.get_model("mainapp", "LocalBody") + for district in District.objects.all(): + for local_body in self.local_bodies(district.name): + print(local_body) + try: + with transaction.atomic(): + LocalBody.objects.create(district=district, + body_type=local_body["type"], + name=local_body["name"]) + except IntegrityError: + print("duplicate found {}".format(local_body["name"])) + + +class Migration(migrations.Migration): + + dependencies = [ + ('mainapp', '0091_merge_20180825_1236'), + ] + + operations = [ + migrations.CreateModel( + name='District', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=150)), + ('described_name', models.CharField(max_length=255)), + ('code', models.CharField(max_length=3, unique=True)), + ], + ), + migrations.CreateModel( + name='LocalBody', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('body_type', models.CharField(choices=[('corporation', 'corporation'), ('municipality', 'municipality'), ('panchayat', 'panchayat')], max_length=20)), + ('name', models.CharField(max_length=200)), + ('district', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mainapp.District')), + ], + ), + migrations.AlterUniqueTogether( + name='localbody', + unique_together={('name', 'district')}, + ), + migrations.RunPython(Populate(), lambda apps, schema_editor: None) + ] diff --git a/mainapp/migrations/0093_merge_20180828_1750.py b/mainapp/migrations/0093_merge_20180828_1750.py new file mode 100644 index 000000000..3f4aff56e --- /dev/null +++ b/mainapp/migrations/0093_merge_20180828_1750.py @@ -0,0 +1,14 @@ +# Generated by Django 2.1 on 2018-08-28 12:20 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('mainapp', '0092_auto_20180828_1429'), + ('mainapp', '0092_auto_20180828_1407'), + ] + + operations = [ + ] diff --git a/mainapp/migrations/0094_merge_20180828_1926.py b/mainapp/migrations/0094_merge_20180828_1926.py new file mode 100644 index 000000000..535524014 --- /dev/null +++ b/mainapp/migrations/0094_merge_20180828_1926.py @@ -0,0 +1,14 @@ +# Generated by Django 2.1 on 2018-08-28 13:56 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('mainapp', '0093_merge_20180828_1750'), + ('mainapp', '0092_auto_20180828_1428'), + ] + + operations = [ + ] diff --git a/mainapp/migrations/local_bodies.csv b/mainapp/migrations/local_bodies.csv new file mode 100644 index 000000000..76e65685f --- /dev/null +++ b/mainapp/migrations/local_bodies.csv @@ -0,0 +1,107 @@ +Alappuzha,Ernakulam,Idukki,Kannur,Kasaragod,Kollam,Kottayam,Kozhikode,Malappuram,Palakkad,Pathanamthitta,Thiruvananthapuram,Thrissur,Wayanad +Mavelikara Municipality,Cochin Corporation,Thodupuzha Municipality,Kannur Corporation,Kanhangad Municipality,Kollam Corporation,Pala Municipality,Kozhikode Corporation,Perinthalmanna Municipality,Ottappalam Municipality,Adoor Municipality,Thiruvananthapuram Corporation,Kadappuram,Kalpetta Municipality +Cherthala Municipality,Kalamassery Municipality,Kattappana Municipality,Mattannur Municipality,Kasaragod Municipality,Karunagappally Municipality,Vaikom Municipality,Vadakara Municipality,Ponnani Municipality,Shornur Municipality,Thiruvalla Municipality,Chemmaruthy,Orumanayur,Mananthavady Municipality +Kayamkulam Municipality,Kothamangalam Municipality,Parathode,Thalipparamba Municipality,Nileshwaram Municipality,Paravoor Municipality,Changanassery Municipality,Koyilandy Municipality,Manjeri Municipality,"Chittur,Thathamangalam Municipality",Pathanamthitta Municipality,Edava,Punnayur,Sulthanbathery Municipality +Alappuzha Municipality,Angamaly Municipality,Koruthod,Koothuparamba Municipality,Mangalpady,Punalur Municipality,Kottayam Municipality,Feroke Municipality,Tirur Municipality,Palakkad Municipality,Pandalam Municipality,Elakamon,Punnayurkulam,Vellamunda +Haripad Municipality,Tripunithura Municipality,Adimaly,Payyannur Municipality,Vorkady,Kottarakkara Municipality,Ettumanur Municipality,Payyoli Municipality,Malappuram Municipality,Pattambi Municipality,Chengannur Municipality,Manamboor,Vadekkekad,Thirunelly +Arookutty,Muvattupuzha Municipality,Konnathady,Thalassery Municipality,Puthige,Oachira,Erattupetta Municipality,Ramanattukara Municipality,Nilambur Municipality,Cherplachery Municipality,Kaviyoor,Ottoor,Choondal,Thondernad +Chennampallippuram,N.Paravur Municipality,Bisonvally,Anthoor Municipality,Meenja,Kulasekharapuram,TV Puram,Koduvally Municipality,Kottakkal Municipality,Mannarkkad Municipality,Kottanadu,Cherunniyoor,Chowwannur,Edavaka +Panavally,Perumbavoor Municipality,Vellathooval,Irutti Municipality,Manjeswhar,Clappana,Vechoor,Mukkam Municipality,Kondotty Municipality,Ottappalam Municipality,Kottangal,Vettoor,Kadavallur,Thavinhal +Perumbalam,Aluva Municipality,Pallivasal,Panoor Municipality,Paivalike,Thazhava,Udayanapuram,Azhiyoor,Tanur Municipality,Shornur Municipality,Kallooppara,Kilimanoor,Kandanassery,Panamaram +Thaicattussery,Thrikkakkara Municipality,Marayoor,Sreekandapuram Municipality,Enmakaje,Alappad,Kaduthuruthy,Chorode,Parappanangadi Municipality,"Chittur,Thathamangalam Municipality",Kunnanthanam,Pazhayakunnummel,Kattakambal,Poothadi +Vayalar,Elloor Municipality,Munnar,Kunhimangalam,Belloor,Thodiyoor,Kallara,Eramala,Valancherry Municipality,Palakkad Municipality,Mallappally,Karavaram,Porkulam,Mullamkolly +Pattanakkad,Marad Municipality,Kanthalloor,Ramanthali,Kumbadaje,Sasthamcotta,Mulakulam,Onchiyam,Tirurangadi Municipality,Pattambi Municipality,Kadapra,Madavoor,Kadangode,Pulpalli +Thuravoor,Piravom Municipality,Vattavada,"Karivellur,Paralam",Muliyar,West,Njeezhoor,Chekkiad,Chaliyar,Cherplachery Municipality,Kuttoor,Pallickal,Velur,Kaniambetta +Kuthiathodu,Koothattukulam Municipality,Santhanpara,Kankole,Karadka,Sooranad,Thalayolaparambu,Edacheri,Chungathara,Mannarkkad Municipality,Niranam,Nagaroor,Desamangalam,Meenangadi +Kodamthuruthu,Chennamangalam,Chinnakanal,"Eramam,Kuttoor",Delampady,Poruvazhy,Velloor,Purameri,Moothedam,Chalisseri,Nedumpram,Navaikulam,Erumapetty,Nenmeni +Ezhupunna,Kottuvally,Mankulam,"Peringome,Vayakkara",Bedaduka,Kunnathur,Aimanam,Thuneri,Vazhikkadavu,Kappur,Peringara,Pulimath,Mullurkara,Ambalavayal +Aroor,Ezhikkara,Devikulam,Cherupuzha,Kuttikol,Sooranad,Athirampuzha,Valayam,Edakkara,Nagalassery,Ayiroor,Anjuthengu,Thekkumkara,Noolpuzha +"Mararikulam,North",Vadakkekara,Edamalakudy,Cheruthazham,Chengala,Mynagappally,Arpookara,Vanimel,Pothukal,Pattithara,Eraviperoor,Vakkom,Varavoor,Kottathara +Kanjikuzhi,Chittattukara,Pampadumpara,Ezhone,Chemnad,Ummannur,Neendoor,Nadapuram,Amarambalam,Thirumittacode,Koipuram,Chirayinkeezhu,Chelakkara,Vengappally +Thanneermukkam,Karumalloor,Senapathy,Madayi,Madhur,Vettikkavala,Kumarakom,Kunnummal,Karulai,Thrithala,Thottapuzhassery,Kizhuvilam,Vallathol,Vythiri +Cherthala,Varapuzha,Karunapuram,Mattool,Mogral,Melila,Thiruvarpu,Kayakkodi,Kalikavu,Koppam,Ezhumattoor,Mudakkal,Kondazhy,Mutil +Kadakkarappally,Alangad,Rajakkad,Cherukunnu,Badiyadka,Mylam,Kadaplamattom,Kavilumpara,Chokkadu,Kulukkallur,Puramattom,Kadakkavoor,Panjal,Pozhuthana +Aryad,Kadungallur,Nedumkandam,Kalliasseri,Kumbala,Kulakkada,Marangattupally,Kuttiadi,Karuvarakundu,Muthuthala,Omallur,Kallara,Pazhayannur,Thariyode +Mannanchery,Mookkannur,Udumbanchola,Kannapuram,Uduma,Pavithreswaram,Kanakkari,Maruthomkara,Thuvvur,Ongallur,Chenneerkara,Nellanad,Thiruvilwamala,Padinharethara +"Mararikulam,South",Thuravoor,Rajakumari,Narath,Ajanoor,Vilakudy,Veliyannoor,Velom,Edappatta,Parudur,Elanthoor,Pullampara,Madakkathara,Meppadi +Muhamma,Manjapra,Vannappuram,Pattuvam,Madikkai,Thalavoor,Kuravilangad,Narippetta,Mambad,Thiruvegapuram,Cherukole,Vamanapuram,Nadathara,Muppainadu +Purakkad,Karukutty,Udumbanoor,Chengalai,Pallikkara,Piravanthur,Uzhavoor,Ayancheri,Pandikkad,Vilayur,Kozhenchery,Pangode,Pananchery,Anicadu +"Ambalapuzha,South",Ayyampuzha,Kodikulam,Kurumathur,Pullurperiya,Pattazhi,Ramapuram,Villiappally,Porur,Ambalapara,Mallapuzhassery,Nanniyode,Puthur,Pallickal +"Ambalapuzha,North",Kanjoor,Alakkode,Pariyaram,Balal,Pattazhi,Manjoor,Maniyoor,Trikkalangode,Ananganadi,Naranganam,Peringammala,Adat, +"Punnapra,South",Kalady,Velliyamattom,Chapparapadavu,Kodom,Pathanapuram,Bharananganam,Thiruvallur,Thiruvali,Chalavara,"Ranni,Pazhavangadi-",Manickal,Avanur, +"Punnapra,North","Malayattoor,Neeleswaram",Karimannoor,Naduvil,Panathady,Kulathupuzha,Karoor,Thurayur,Vandoor,Lakkidiperur,Ranni,Aryanad,Kaiparambu, +Thalavadi,Asamannoor,Kudayathoor,Udayagiri,Kallar,Eroor,Kozhuvanal,Keezhariyoor,Chelambra,Vaniamkulam,Ranni Angadi,Poovachal,Mulamkunnathukavu, +Edathua,Mudakuzha,Idukki,Alakode,East Eleri,Alayamon,Kadanad,Thikkodi,Cherukavu,Thrikkadeeri,Ranni Perunadu,Vellanad,Tholur, +Thakazhi,Vengoor,Vattikudy,"Kadannapally,Panapuzha",West Eleri,Anchal,Meenachil,Meppayyur,Pallikkal,Vallapuzha,Vadasserikkara,Vithura,Kolazhy, +Nedumudi,Rayamangalam,Arakulam,Eruvessi,Kinanoor,Edamulakkal,Mutholy,Cheruvannur,Vazhayur,Nellaya,Chittar,Uzhamalackal,Elavally, +Champakulam,Koovappady,Kamakshy,Irikkur,Cheruvathur,Karavaloor,Melukavu,Nochad,Vazhakkad,Kadampazhipuram,Seethathodu,Kuttichal,Mullassery, +Kainakary,Okkal,Vazhathope,Malapattom,Kayyur,Thenmala,Moonilavu,Changaroth,Pulikkal,Karimpuzha,Naranamoozhy,Tholicode,Pavaratty, +Muttar,Vengola,Mariyapuram,Payyavoor,Pilicode,Aryankavu,Poonjar,Kayanna,Muthuvallur,Pookkottukavu,Vechuchira,Kattakada,Venkitangu, +Veliyanad,Vazhakkulam,Upputhara,Kuttiattor,Thrikkaripur,Veliyam,"Poonjar,Thekkekara",Kuthali,Urungattiri,Sreekrishnapuram,Konni,Anad,Engandiyur, +Neelamperoor,Kizhakkambalam,Vandenmed,Mayyil,Valiyaparamba,Pooyappally,Thalappalam,Perambra,Kavannur,Vellinezhi,Aruvapulam,Aruvikkara,Vadanappally, +Kavalam,Choornikkara,Kanchiyar,Padiyurkalliad,Padne,Kareepra,Teekoy,Chakkittapara,Kizhuparambu,Karakurissi,Pramadom,Panavoor,Thalikulam, +Pulinkunnu,Edathala,Erattayar,Ulickal,,Ezhukone,Thalanad,Balussery,Pulpatta,Alanallur,Mylapra,Karakulam,Nattika, +Ramankari,Keezhmad,Ayyappancoil,Chirakkal,,Neduvathur,Thidanad,Naduvannur,Chekkode,Karimba,Vallicode,Vembayam,Valappad, +Mulakuzha,Kadamakudy,Chakkupallam,Valapattanam,,Perinad,Akalakunnam,Ulliyeri,Kuzhimanna,Kottoppadam,Thannithode,Andoorkonam,Anthicad, +Venmony,Cheranallur,Muttom,Azhikode,,Kundara,Elikulam,Kottur,Areekode,Kumaramputhur,Malayalapuzha,Kadinamkulam,Thanniyam, +Cheriyanad,Mulavucaud,Kumaramangalam,Pappinisseri,,Kizhakkekallada,Kooroppada,Unnikulam,Edavanna,Kanjirappuzha,Pandalam,Mangalapuram,Chazhoor, +Ala,Elamkunnapuzha,Edavetty,Kadamboor,,Perayam,Pampady,Panangad,Anakkayam,Thachanattukara,Thumpamon,Pothencode,Manallur, +Puliyoor,Njarakkal,Karimkunnam,Chembilode,,Mundrothuruthu,Pallikkathode,Koorachundu,Morayur,Tachampara,Aranmula,Azhoor,Arimpoor, +Budhannoor,Nayarambalam,Manakkad,Munderi,,Panayam,Meenadom,Chemanchery,Ponmala,Thenkara,Mezhuveli,Balaramapuram,Avinissery, +Pandanad,Edavanakkad,Purapuzha,Peralasseri,,Thrikkaruva,Kidangoor,Arikkulam,Pookkottur,Agali,Kulanada,Pallichal,Cherpu, +Thiruvanvandur,Pallippuram,Peruvanthanam,Kolacherry,,Thekkumbhagam,Manarkkad,Moodadi,Kodoor,Pudur,Enadimangalam,Maranalloor,Paralam, +Karthigappally,Kuzhuppilly,Kumily,Dharmadom,,Chavara,Ayarkkunnam,Chengottukavu,Othukkungal,Sholayar,Erathu,Malayinkeezh,Vallachira, +Thrikkunnapuzha,Chellanam,Kokkayar,Eranjoli,,Thevalakkara,Puthuppally,Atholi,Aliparambu,Keralassery,Ezhamkulam,Vilappil,Alagappa, +Kumarapuram,Kumbalangy,Peerumedu,Pinarayi,,Panmana,Panachikkad,Kakkodi,Elamkulam,Kongad,Kadampanadu,Vilavoorkkal,Kodakara, +Karuvatta,Kumbalam,Elappara,New,,Neendakara,Vijayapuram,Chelannur,Melattur,Mankara,Kalanjoor,Kalliyoor,Mattathur, +Pallippad,Udayamperur,Vandiperiyar,Muzhappilangad,,Mayyanad,Kurichy,Kakkur,Keezhattur,Mannur,Kodumon,Perumkadavila,Nenmanikkara, +Cheruthana,Mulamthuruthy,,Ancharakandy,,Thrikkovilvattom,Madappally,Nanmanda,Thazhekode,Mundur,Anicadu,Kollayil,Pudukkad, +Veeyapuram,Chottanikkara,,Vengad,,Kottamkara,Paippad,Narikkuni,Vettathur,Parali,Pallickal,Ottasekharamangalam,Trikkur, +"Mavelikkara,Thekkekara",Edakkattuvayal,,Kadirur,,Elambalur,Thrikkodithanam,Thalakkulathur,Pulamanthole,Pirayiri,,Aryancode,Varandarappilly, +Chettikulangara,Amballur,,Chokli,,Nedumpana,Vakathanam,Thiruvambadi,Angadipuram,Kottai,,Kallikkadu,Karalam, +"Chennithala,Thripperumthura",Maneed,,Mokeri,,Poothakkulam,Vazhappally,Koodaranji,Kuruva,Kuthanoor,,Kunnathukal,Kattur, +Thazhakara,Puthrukka,,Panniyannur,,Kalluvathukkal,Chirakkadavu,Kizhakkoth,Mankada,Kuzhalmannam,,Vellarada,Muriyad, +Mannar,Thiruvaniyoor,,Trippangottur,,Chathannur,Kangazha,Madavoor,Makkaraparamba,Mathur,,Amboori,Parappukkara, +Nooranad,"Vadavucode,Puthen,Cruz",,Chittariparamba,,Adichanalloor,Nedumkunnam,Puduppady,Moorkkanad,Peringottukurissi,,Athiyannoor,Padiyur, +Vallikunnam,Mazhuvannoor,,Kunnathuparamba,,Chirakkara,Vellavoor,Thamarassery,Koottilangadi,Thenkurissy,,Kanjiramkulam,Poomangalam, +Bharanikavu,Aikaranad,,Mangattidom,,Chithara,Vazhoor,Omassery,Puzhakkattiri,Kannadi,,Karumkulam,Puthenchira, +"Mavelikkara,Thamarakulam",Kunnathunad,,Pattiom,,Kadakkal,Karukachal,Kattippara,Athavanad,Eruthempathy,,Kottukal,Vellangallur, +Chunakkara,Paingottur,,Kottayam,,Chadayamangalam,Erumeli,Kodenchery,Edayoor,Kozhinjampara,,Venganoor,Vellookkara, +Palamel,Nellikuzhi,,Aralam,,Ittiva,Kanjirappally,Kodiyathur,Irimbilayam,Nalleppilly,,Chenkal,Edathiruthy, +Pathiyoor,Pindimana,,Ayyamkunnu,,Velinallur,Kootickal,Kuruvattur,Marakkara,Perumatty,,Karode,Kaipamangalam, +Kandalloor,Kottappady,,Keezhalloor,,Elamadu,Manimala,Mavoor,Kuttippuram,Vadakarapathy,,Kulathoor,Mathilakam, +Cheppad,Kavalangad,,Thilankeri,,Nilamel,Mundakayam,Karassery,Kalpakancheri,Elappully,,Parassala,Perinjanam, +Muthukulam,Varappetty,,Koodali,,Kummil,,Kunnamangalam,Abdul Rahman Nagar,Polpully,,Thirupuram, Sree Narayanapuram, +Arattupuzha,Keerampara,,Payam,,,,Chathamangalam,Edarikode,Kollenkode,,Poovar,Edavilangu, +Krishnapuram,Pothanikkad,,Kanichar,,,,Peruvayal,Parappur,Koduvayur,,Varkala Municipality,Eriyad, +Devikulangara,Pallarimangalam,,Kelakom,,,,Perumanna,Thennala,Muthalamada,,Attingal Municipality,Alur, +Chingoli,Kuttampuzha,,Kottiyoor,,,,Kadalundi,Vengara,Puthunagaram,,Nedumangad Municipality,Annamanada, +Thalayazham,Elanji,,Muzhakkunnu,,,,Olavanna,Kannamangalam,Vadavannur,,Neyyattinkara Municipality,Kuzhur, +Chempu,Thirumarady,,Kolayad,,,,,Urakam,Pattenchery,,,Mala, +Maravanthuruthu,Palakuzha,,Malur,,,,,Thenhippalam,Peruvembu,,,Poyya, +,Pampakuda,,Peravoor,,,,,Vallikkunnu,Ayiloor,,,Kadukutty, +,Ramamangalam,,,,,,,Moonniyur,Nelliampathy,,,Kodassery, +,Puthenvelikara,,,,,,,Nannambra,Elavenchery,,,Koratty, +,Chengamanad,,,,,,,Peruvalloor,Pallassana,,,Melur, +,Nedumbassery,,,,,,,Cheriyamundam,Melarcode,,,Pariyaram, +,Parakkadavu,,,,,,,Ozhur,Nenmara,,,Athirappally, +,Kunnukara,,,,,,,Tanalur,Vandazhy,,,Anakkara, +,Sreemoolanagaram,,,,,,,Valavannur,Alathur,,,, +,Avoly,,,,,,,Ponmundam,Erimayur,,,, +,Arakuzha,,,,,,,Niramaruthur,Kavassery,,,, +,Valakom,,,,,,,Perumannaclari,Kizhakkenchery,,,, +,Paipra,,,,,,,Purathur,Puducode,,,, +,Kalloorkkad,,,,,,,Thalakkad,Tarur,,,, +,Ayavana,,,,,,,Triprangode,Vadakkanchery,,,, +,Manjalloor,,,,,,,Vettom,Kannambra,,,, +,Marady,,,,,,,Thirunavaya,Akathethara,,,, +,,,,,,,,Mangalam,Malampuzha,,,, +,,,,,,,,Tavanur,Marutharoad,,,, +,,,,,,,,Vattamkulam,Puduppariyaram,,,, +,,,,,,,,Edappal,Pudussery,,,, +,,,,,,,,Kalady,Kodumbu,,,, +,,,,,,,,Alamcode,,,,, +,,,,,,,,Marancheri,,,,, +,,,,,,,,Nannamukku,,,,, +,,,,,,,,Perumpadappa,,,,, +,,,,,,,,Veliyancode,,,,, diff --git a/mainapp/models.py b/mainapp/models.py index 0f15746d5..4f6da8e42 100644 --- a/mainapp/models.py +++ b/mainapp/models.py @@ -195,11 +195,11 @@ class Volunteer(models.Model): verbose_name="District - ജില്ല" ) name = models.CharField(max_length=100, verbose_name="Name - പേര്") - phone_number_regex = RegexValidator(regex='^((\+91|91|0)[\- ]{0,1})?[456789]\d{9}$', message='Please Enter 10 digit mobile number or landline as 0', code='invalid_mobile') phone = models.CharField(max_length=14, verbose_name="Phone - ഫോണ്‍ നമ്പര്‍", validators=[phone_number_regex]) - + email = models.EmailField(max_length=250, blank=True) organisation = models.CharField(max_length=250, verbose_name="Organization (സംഘടന) / Institution") + local_body = models.TextField(max_length=250, default= "") address = models.TextField(verbose_name="Address - വിലാസം") area = models.CharField( max_length = 15, @@ -208,6 +208,7 @@ class Volunteer(models.Model): ) is_spoc = models.BooleanField(default=False, verbose_name="Is point of contact") joined = models.DateTimeField(auto_now_add=True) + date_time = models.TextField(blank=True) is_active = models.BooleanField(default=True) has_consented = models.BooleanField(default=False, verbose_name="Available") @@ -218,6 +219,25 @@ class Meta: def __str__(self): return self.name + @property + def district_name(self): + return { + 'alp': 'Alappuzha - ആലപ്പുഴ', + 'ekm': 'Ernakulam - എറണാകുളം', + 'idk': 'Idukki - ഇടുക്കി', + 'knr': 'Kannur - കണ്ണൂർ', + 'ksr': 'Kasaragod - കാസർഗോഡ്', + 'kol': 'Kollam - കൊല്ലം', + 'ktm': 'Kottayam - കോട്ടയം', + 'koz': 'Kozhikode - കോഴിക്കോട്', + 'mpm': 'Malappuram - മലപ്പുറം', + 'pkd': 'Palakkad - പാലക്കാട്', + 'ptm': 'Pathanamthitta - പത്തനംതിട്ട', + 'tvm': 'Thiruvananthapuram - തിരുവനന്തപുരം', + 'tcr': 'Thrissur - തൃശ്ശൂർ', + 'wnd': 'Wayanad - വയനാട്', + }.get(self.district, 'Unknown') + class NGO(models.Model): district = models.CharField( @@ -672,3 +692,28 @@ def full_clean(self, *args, **kwargs): def __str__(self): return self.name + + +class District(models.Model): + name = models.CharField(max_length=150) + described_name = models.CharField(max_length=255) + code = models.CharField(max_length=3, unique=True) + + def __repr__(self): + return "{} - {}".format(self.id, self.name) + + +class LocalBody(models.Model): + local_body_types = ( + ("corporation", "corporation"), + ("municipality", "municipality"), + ("panchayat", "panchayat")) + body_type = models.CharField(max_length=20, choices=local_body_types) + district = models.ForeignKey(District, on_delete=models.CASCADE) + name = models.CharField(max_length=200) + + class Meta: + unique_together = ("name", "district") + + def __repr__(self): + return "{} - {}".format(self.id, self.name) diff --git a/mainapp/templates/mainapp/reg_fail.html b/mainapp/templates/mainapp/reg_fail.html new file mode 100644 index 000000000..b1a3a7be4 --- /dev/null +++ b/mainapp/templates/mainapp/reg_fail.html @@ -0,0 +1,9 @@ +{% extends 'base.html' %} +{% load bootstrap3 %} + +{% block content %} + +

Your request has been failed

+

താങ്കളുടെ അഭ്യർത്ഥന പരാജയപ്പെട്ടു

+ +{% endblock %} diff --git a/mainapp/templates/mainapp/renew_volunteer.html b/mainapp/templates/mainapp/renew_volunteer.html new file mode 100644 index 000000000..2f05e2b5b --- /dev/null +++ b/mainapp/templates/mainapp/renew_volunteer.html @@ -0,0 +1,267 @@ +{% extends 'base.html' %} {% load bootstrap3 %} {% block content %} + + +

Renew as Volunteer

+

വൊളന്‍റീയര്‍ പുതുക്കാൻ

+ + + + +{% endblock %} \ No newline at end of file diff --git a/mainapp/urls.py b/mainapp/urls.py index 42247f077..779332d5a 100644 --- a/mainapp/urls.py +++ b/mainapp/urls.py @@ -21,6 +21,7 @@ url(r'request_details/(?P\d+)/$', views.request_details, name='requestdetailsview'), path('contactus/', views.districtmanager_list, name='contactus'), path('reg_success/', views.RegSuccess.as_view(), name='reg_successview'), + path('reg_fail/', views.RegFail.as_view(), name='reg_fail'), path('req_sucess/', views.ReqSuccess.as_view(), name='req_sucessview'), path('district_needs/', views.DistNeeds.as_view(), name='distneedsview'), path('collection_center/', views.CollectionCenterView.as_view(), name='collection_centers_view'), @@ -62,4 +63,6 @@ path('consent_success/', views.ConsentSuccess.as_view(), name='consent_success'), url(r'c/(?P\d+)/(?P\d+)/$', views.VolunteerConsent.as_view(), name='volunteer_consent'), url('missing_and_finding_persons/', views.ReportFindPerson.as_view(), name='report_find_person'), + url(r'renewvolunteer/(?P\d+)/$', views.RenewVolunteerPage.as_view(), name='renewvolunteer'), + url('test_send_sms/', views.test_send_sms, name='test_send_sms'), ] diff --git a/mainapp/views.py b/mainapp/views.py index 0b76491b0..b2f506e29 100644 --- a/mainapp/views.py +++ b/mainapp/views.py @@ -86,6 +86,49 @@ class RegisterVolunteer(CreateView): fields = ['name', 'district', 'phone', 'organisation', 'area', 'address'] success_url = '/reg_success/' + +class RenewVolunteerForm(forms.ModelForm): + + + class Meta: + model = Volunteer + help_texts = { + 'local_body': 'Indicate the local body name', + 'date_time': 'Indicate the dates that you are available for volunteering', + } + fields = ['district', 'name', 'local_body', 'phone', 'email', 'date_time', 'has_consented'] + + read_only = ('phone',) + widgets = { + 'name': forms.Textarea(attrs={'rows':1}), + 'phone': forms.Textarea(attrs={'rows':3, 'readonly':True}), + } + +class RenewVolunteerPage(CreateView): + model = Volunteer + fields = ['district', 'organisation', 'is_active', 'name', 'local_body', 'phone', 'email', 'date_time', 'has_consented'] + template_name = "mainapp/renew_volunteer.html" + success_url = '/reg_success/' + volunteer_ph = "" + + def dispatch(self, request, *args, **kwargs): + self.volunteer_ph = kwargs['volunteer_ph'] + return super().dispatch(request, *args, **kwargs) + + def get(self, request, *args, **kwargs): + try: + current = self.model.objects.all().filter(phone=self.volunteer_ph)[0] + except: + return HttpResponseRedirect(reverse("reg_fail")) + return render(request, self.template_name, {"current": current}) + + def form_invalid(self, form): + return HttpResponse(form.errors) + + def form_valid(self, form): + self.object = form.save() + return HttpResponseRedirect(self.get_success_url()) + def volunteerdata(request): filter = VolunteerFilter( request.GET, queryset=Volunteer.objects.all() ) req_data = filter.qs.order_by('-id') @@ -217,6 +260,9 @@ class ReqSuccess(TemplateView): class RegSuccess(TemplateView): template_name = "mainapp/reg_success.html" +class RegFail(TemplateView): + template_name = "mainapp/reg_fail.html" + class SubmissionSuccess(TemplateView): template_name = "mainapp/submission_success.html" @@ -941,3 +987,12 @@ class CollectionCenterView(CreateView): model = CollectionCenter form_class = CollectionCenterForm success_url = '/collection_centers/' + + +def test_send_sms(request): + print(request.GET) + import time + time.sleep(2) + return JsonResponse({ + "success": True + }, safe=False) diff --git a/renew_volunteer_sms.py b/renew_volunteer_sms.py new file mode 100644 index 000000000..f2644d125 --- /dev/null +++ b/renew_volunteer_sms.py @@ -0,0 +1,68 @@ +# Dependencies - Requests, dateutil +# Python 2.7.15 + +# Expects a csv file's path containing volunteer details +# Fill in the credentials in line 55, and run the script + +# Example usage: +# python2 path/to/sms.py path/to/csvFile.csv + +import calendar +import csv +import datetime +import sys +import time + +import requests + +from dateutil import parser + +csvFile = sys.argv[1] #command line argument + +if __name__ == "__main__": + + # csv file path not provided + if len(sys.argv) < 1: + sys.exit() + + #stores failed sms + failed = open("Failed",'w') + fin = open(csvFile,'r') + + # to avoid multiple sms to same mobile number + mark = {} + + for fields in csv.reader(fin): + + sendID = fields[0] + timestamp = fields[8] + mobile = fields[3] + + if mobile in mark: + continue + mark[mobile]=1 + + if mobile.isdigit(): + try: + # Converting timestamp to epoch + timestamp = parser.parse(timestamp) + timestamp = calendar.timegm(timestamp.utctimetuple()) + + # Preparing unique URL + url = 'http://keralarescue.in/c/' + sendID + "/" + str(timestamp)[-4:] + message = "If you would like to volunteer to do the damage assessment, please click this link " + url + + payload = { 'username':'xxxxxxxx','password':'xxxxxxxx','message':message,'numbers':mobile} + response = requests.get('http://api.esms.kerala.gov.in/fastclient/SMSclient.php',params=payload) + + except KeyboardInterrupt: + + failed.write(mobile) + sys.exit() + + except: + + failed.write(mobile) + + fin.close() + failed.close() diff --git a/requirements.txt b/requirements.txt index a5843f030..1bc511bf7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -23,3 +23,5 @@ django-storages==1.6.6 python-dateutil beautifulsoup4==4.6.3 ddtrace==0.12.1 +pympler==0.5 +django_debug_toolbar==1.9.1