Added doctypes and portal pages

This commit is contained in:
pranav nachnekar 2019-08-28 16:57:37 +05:30
parent 48d9cfe304
commit 7b9e30914f
26 changed files with 600 additions and 0 deletions

View File

@ -0,0 +1,8 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Appointment', {
// refresh: function(frm) {
// }
});

View File

@ -0,0 +1,91 @@
{
"autoname": "format:APMT-{appointment_date}-{####}",
"creation": "2019-08-27 10:48:27.926283",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"from_time",
"to_time",
"appointment_date",
"customer_details_section",
"customer_name",
"customer_phone_number",
"customer_skype",
"customer_details"
],
"fields": [
{
"fieldname": "from_time",
"fieldtype": "Time",
"in_list_view": 1,
"label": "From Time",
"reqd": 1
},
{
"fieldname": "to_time",
"fieldtype": "Time",
"in_list_view": 1,
"label": "To Tme",
"reqd": 1
},
{
"fieldname": "appointment_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Date ",
"reqd": 1
},
{
"fieldname": "customer_details_section",
"fieldtype": "Section Break",
"label": "Customer Details"
},
{
"fieldname": "customer_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Name",
"reqd": 1
},
{
"fieldname": "customer_phone_number",
"fieldtype": "Data",
"label": "Phone Number"
},
{
"fieldname": "customer_skype",
"fieldtype": "Data",
"label": "Skype ID"
},
{
"fieldname": "customer_details",
"fieldtype": "Long Text",
"label": "Details"
}
],
"modified": "2019-08-27 12:43:30.143937",
"modified_by": "Administrator",
"module": "CRM",
"name": "Appointment",
"name_case": "UPPER CASE",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
class Appointment(Document):
pass

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
# import frappe
import unittest
class TestAppointment(unittest.TestCase):
pass

View File

@ -0,0 +1,18 @@
// frappe.ui.form.on('Availability Of Slots', 'from_time', check_time)
// frappe.ui.form.on('Availability Of Slots', 'to_time', check_time)
frappe.ui.form.on('Appointment Booking Settings', 'validate',check_times)
function check_times(frm) {
$.each(frm.doc.availability_of_slots || [], function (i, d) {
let from_time = Date.parse('01/01/2019 ' + d.from_time);
console.log(from_time);
let to_time = Date.parse('01/01/2019 ' + d.to_time);
if (from_time > to_time) {
frappe.throw(__(`In row ${i + 1} of Availability Of Slots : "To Time" must be later than "From Time"`))
}
})
}
// function check_times(frm, cdt, cdn) {
// let d = locals[cdt][cdn];
//
// }

View File

@ -0,0 +1,72 @@
{
"creation": "2019-08-27 10:56:48.309824",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"availability_of_slots",
"number_of_agents",
"holiday_list",
"email_reminders",
"appointment_duration"
],
"fields": [
{
"fieldname": "availability_of_slots",
"fieldtype": "Table",
"label": "Availability Of Slots",
"options": "Availability Of Slots",
"reqd": 1
},
{
"fieldname": "number_of_agents",
"fieldtype": "Int",
"in_list_view": 1,
"label": "No. Of Agents",
"reqd": 1
},
{
"fieldname": "holiday_list",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Holiday List",
"options": "Holiday List",
"reqd": 1
},
{
"default": "0",
"fieldname": "email_reminders",
"fieldtype": "Check",
"label": "Email Reminders"
},
{
"default": "60",
"fieldname": "appointment_duration",
"fieldtype": "Int",
"label": "Appointment Duration",
"reqd": 1
}
],
"issingle": 1,
"modified": "2019-08-27 17:32:46.208951",
"modified_by": "Administrator",
"module": "CRM",
"name": "Appointment Booking Settings",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
class AppointmentBookingSettings(Document):
pass

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
# import frappe
import unittest
class TestAppointmentBookingSettings(unittest.TestCase):
pass

View File

@ -0,0 +1,46 @@
{
"creation": "2019-08-27 10:52:54.204677",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"day_of_week",
"from_time",
"to_time"
],
"fields": [
{
"fieldname": "day_of_week",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Day Of Week",
"options": "Sunday\nMonday\nTuesday\nWednesday\nThursday\nFriday\nSaturday",
"reqd": 1
},
{
"fieldname": "from_time",
"fieldtype": "Time",
"in_list_view": 1,
"label": "From Time ",
"reqd": 1
},
{
"fieldname": "to_time",
"fieldtype": "Time",
"in_list_view": 1,
"label": "To Time",
"reqd": 1
}
],
"istable": 1,
"modified": "2019-08-27 10:52:54.204677",
"modified_by": "Administrator",
"module": "CRM",
"name": "Availabilty Of Slots",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
class AvailabilityOfSlots(Document):
pass

View File

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
# import frappe
import unittest
class TestTimezone(unittest.TestCase):
pass

View File

@ -0,0 +1,8 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Timezone', {
// refresh: function(frm) {
// }
});

View File

@ -0,0 +1,52 @@
{
"autoname": "field:timezone_name",
"creation": "2019-08-27 11:39:30.328670",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"offset",
"timezone_name"
],
"fields": [
{
"fieldname": "offset",
"fieldtype": "Int",
"in_list_view": 1,
"label": "Offset In Minutes",
"reqd": 1
},
{
"fieldname": "timezone_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Name",
"reqd": 1,
"unique": 1
}
],
"modified": "2019-08-27 11:39:30.328670",
"modified_by": "Administrator",
"module": "CRM",
"name": "Timezone",
"name_case": "Title Case",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
class Timezone(Document):
pass

View File

@ -0,0 +1,31 @@
{% extends "templates/web.html" %}
{% block title %}{{ _("Book Appointment") }}{% endblock %}
{% block page_content %}
<div class="container">
<!-- title: Book an appointment -->
<div class="text-center mb-5">
<h3>Book an appointment</h3>
<h4>Select the date and your timezone</h4>
</div>
<div class="row justify-content-center mt-3">
<div class="col-md-4 align-self-center ">
<form name="myform">
<input type="date" name="appointment-date" id="appointment-date" class="form-control mt-3" min="{{ from_date }}" max="{{ to_date }}">
<select name="appointment-timezone" id="appointment-timezone" class="form-control mt-3">
{% if timezones %}
{% for timezone in timezones%}
<option value="{{timezone.offset}}">{{timezone.timezone_name}}</option>
{% endfor %}
{% endif %}
</select>
</form>
<button class="form-control mt-3 btn btn-dark" id="next-button" onclick="next()">
Next
</button>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,14 @@
let holidays = [];
{% if holidays %}
holidays = {{holidays}}
{% endif %}
function next() {
let date = document.getElementsByName('appointment-date')[0].value;
if(holidays.includes(date)){
frappe.throw("That day is a holiday")
}
let tz = document.getElementsByName('appointment-timezone')[0].value;
window.location = `/book-appointment/2?date=${date}&tz=${tz}`;
}

View File

@ -0,0 +1,17 @@
import frappe
def get_context(context):
settings = frappe.get_doc('Appointment Booking Settings')
holiday_list = frappe.get_doc('Holiday List',settings.holiday_list)
holidays = []
for holiday in holiday_list.holidays:
print(str(holiday.holiday_date))
holidays.append(str(holiday.holiday_date))
context.holidays = holidays
context.from_date = holiday_list.from_date
context.to_date = holiday_list.to_date
timezones = frappe.get_all('Timezone',fields=["timezone_name","offset"])
context.timezones = timezones
return context

View File

@ -0,0 +1,85 @@
{% extends "templates/web.html" %}
{% block title %}{{ _("Book Appointment") }}{% endblock %}
{% block page_content %}
<style>
.time-slot {
margin: 0 0;
border: 0.5px solid #cccccc;
min-height: 100px;
}
.time-slot:hover {
background: #ddd;
}
.time-slot.unavailable {
background: #bbb;
color: #777777
}
input[type="radio"] {
visibility: hidden;
display: none;
}
.time-slot.selected {
color: white;
background: #5e64ff;
}
</style>
<div class="container">
<div class="text-center mb-5">
{% if is_holiday %}
<h3> This day is a holiday</h3>
{% else %}
<h3>Pick A Time Slot</h3>
<h4>Selected date is {{ date }}</h4>
</div>
<!-- Start of main content-->
<div class="mt-3 justify-content-center">
<div class="row">
<div class="col-md time-slot unavailable" id="12pm">12 pm to 1 am</div>
<div class="col-md time-slot selected" id="1am">1 am to 2 am</div>
<div class="col-md time-slot" id="2am">2 am to 3 am</div>
<div class="col-md time-slot" id="3am">3 am to 4 am</div>
<div class="col-md time-slot" id="4am">4 am to 5 am</div>
<div class="col-md time-slot" id="5am">5 am to 6 am</div>
<div class="col-md time-slot" id="6am">6 am to 7 am</div>
<div class="col-md time-slot" id="7am">7 am to 8 am</div>
</div>
<div class="row">
<div class=" col-md time-slot" id="8am">8 am to 9 am</div>
<div class=" col-md time-slot" id="9am">9 am to 10 am</div>
<div class=" col-md time-slot" id="10am">10 am to 11 am</div>
<div class=" col-md time-slot" id="11am">11 am to 12 am</div>
<div class=" col-md time-slot" id="12am">12 am to 1 pm</div>
<div class=" col-md time-slot" id="1pm">1 pm to 2 pm</div>
<div class=" col-md time-slot" id="2pm">2 pm to 3 pm</div>
<div class=" col-md time-slot" id="3pm">3 pm to 4pm</div>
</div>
<div class="row">
<div class=" col-md time-slot" id="4pm">4pm to 5pm</div>
<div class=" col-md time-slot" id="5pm">5 pm to 6 pm</div>
<div class=" col-md time-slot" id="6pm">6 pm to 7 pm</div>
<div class=" col-md time-slot" id="7pm">7 pm to 8 pm</div>
<div class=" col-md time-slot" id="8pm">8 pm to 9 pm</div>
<div class=" col-md time-slot" id="9pm">9 pm to 10 pm</div>
<div class=" col-md time-slot" id="10pm">10 pm to 11 pm</div>
<div class=" col-md time-slot" id="11pm">11 pm to 12 pm</div>
</div>
<div class="row justify-content-center">
<div class="col-md-4 align-self-center">
<button class="form-control mt-5 btn btn-dark" onclick="next()">
Next
</button>
</div>
</div>
{% endif %}
</div>
</div>
<!-- End of main content -->
{% endblock %}

View File

@ -0,0 +1,27 @@
let time_slot_divs = document.getElementsByClassName('time-slot');
function get_available_slots() {
frappe.db
}
function select_time() {
if (this.classList.contains("unavailable")) {
return
}
console.log(this.id)
var selected = document.getElementsByClassName('selected')[0];
selected.classList.remove('selected');
this.classList.add('selected');
}
for (var i = 0; i < time_slot_divs.length; i++) {
time_slot_divs[i].addEventListener('click', select_time);
}
function next() {
let urlParams = new URLSearchParams(window.location.search);
let date = urlParams.get("date");
let tz = urlParams.get("tz");
let time_slot = document.querySelector(".selected").id;
window.location.href = `/book-appointment/3?date=${date}&tz=${tz}&time=${time_slot}`;
}

View File

@ -0,0 +1,28 @@
import frappe
import datetime
def get_context(context):
context.date = frappe.form_dict['date']
settings = frappe.get_doc('Appointment Booking Settings')
holiday_list = frappe.get_doc('Holiday List', settings.holiday_list)
if(is_holiday(context.date,holiday_list)):
context.is_holiday = True
return context
get_time_slots(context.date,settings)
# time_slots = get_time_slots(date)
return context
def is_holiday(date,holiday_list):
for holiday in holiday_list.holidays:
if holiday.holiday_date.isoformat() == date:
print('matched')
return True
return False
def _deltatime_to_time(deltatime):
return (datetime.datetime.min + deltatime).time()
weekdays = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]

View File

@ -0,0 +1,22 @@
{% extends "templates/web.html" %}
{% block title %}{{ _("Book Appointment") }}{% endblock %}
{% block page_content %}
<div class="container">
<div class="text-center mb-5">
<h3>Add details</h3>
<h4>Selected date is {{ date }} at {{ time }}</h4>
</div>
<div class="row justify-content-center mt-3">
<div class="col-md-4 align-items-center">
<input class="form-control mt-3" type="text" name="customer_name" id="customer_name" placeholder="Your Name" required>
<input class="form-control mt-3" type="tel" name="customer_number" id="customer_number" placeholder="Contact Number" required>
<input class="form-control mt-3" type="text" name="customer_skype" id="customer_skype" placeholder="Skype" required>
<textarea class="form-control mt-3" name="customer_notes" id="customer_notes" cols="30" rows="10" placeholder="Notes"></textarea>
<button class="btn btn-primary form-control mt-3" onclick="submit()">Submit</button>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,11 @@
function submit(){
let params = new URLSearchParams(window.location.search);
const date = params.get('date');
const time = params.get('time');
const tz = params.get('tz');
const customer_name = document.getElementById('customer_name').value;
const customer_number = document.getElementById('customer_number').value;
const customer_skype = document.getElementById('customer_skype').value;
const customer_notes = document.getElementById('customer_notes').value;
console.log({date,time,tz,customer_name,customer_number,customer_skype,customer_notes});
}