Converted to an SPA
This commit is contained in:
parent
eb4fa966b0
commit
2791054327
@ -1,38 +0,0 @@
|
||||
{% 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"
|
||||
onchange="ondatechange()"
|
||||
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 %}
|
@ -1,25 +0,0 @@
|
||||
|
||||
{% include 'erpnext/public/js/date_polyfill.js' %}
|
||||
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")
|
||||
}
|
||||
if(date === ""){
|
||||
frappe.throw("Please select a date")
|
||||
}
|
||||
let tz = document.getElementsByName('appointment-timezone')[0].value;
|
||||
window.location = `/book-appointment/2?date=${date}&tz=${tz}`;
|
||||
}
|
||||
|
||||
function ondatechange(){
|
||||
let date = document.getElementById('appointment-date')
|
||||
if(holidays.includes(date.value)){
|
||||
frappe.throw("That day is a holiday")
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
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
|
||||
|
@ -1,60 +0,0 @@
|
||||
{% 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">
|
||||
{% for timeslot in timeslots %}
|
||||
<div class="col-md time-slot {% if timeslot.unavailable %}unavailable{% endif %}" id="{{ timeslot.time.time() }}">{{ timeslot.time.time().strftime('%H : %M') }}</div>
|
||||
{% endfor %}
|
||||
</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 %}
|
@ -1,31 +0,0 @@
|
||||
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)
|
||||
try{
|
||||
selected_element = document.getElementsByClassName('selected')[0]
|
||||
}catch(e){
|
||||
this.classList.add('selected')
|
||||
}
|
||||
selected_element.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}`;
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
import frappe
|
||||
import datetime
|
||||
|
||||
|
||||
def get_context(context):
|
||||
# Get query parameters
|
||||
date = frappe.form_dict['date']
|
||||
tz = frappe.form_dict['tz']
|
||||
tz = int(tz)
|
||||
# Database queries
|
||||
settings = frappe.get_doc('Appointment Booking Settings')
|
||||
holiday_list = frappe.get_doc('Holiday List', settings.holiday_list)
|
||||
# Format datetimes
|
||||
format_string = '%Y-%m-%d %H:%M:%S'
|
||||
start_time = datetime.datetime.strptime(date+' 00:00:00', format_string)
|
||||
end_time = datetime.datetime.strptime(date+' 23:59:59', format_string)
|
||||
# Convert to ist
|
||||
start_time = _convert_to_ist(start_time, tz)
|
||||
end_time = _convert_to_ist(end_time, tz)
|
||||
timeslots = get_available_slots_between(start_time, end_time, settings)
|
||||
converted_timeslots = []
|
||||
print('Appointments')
|
||||
print(frappe.get_list('Appointment',fields=['from_time']))
|
||||
for timeslot in timeslots:
|
||||
if timeslot > end_time or timeslot < start_time:
|
||||
pass
|
||||
else:
|
||||
if frappe.db.count('Appointment',{'from_time':start_time.time()}) < settings.number_of_agents:
|
||||
converted_timeslots.append(dict(time=_convert_to_tz(timeslot, tz), unavailable=False))
|
||||
else:
|
||||
converted_timeslots.append(dict(time=_convert_to_tz(timeslot, tz),unavailable=True))
|
||||
|
||||
context.timeslots = converted_timeslots
|
||||
context.date = date
|
||||
return context
|
||||
|
||||
def _is_holiday(date, holiday_list):
|
||||
for holiday in holiday_list.holidays:
|
||||
if holiday.holiday_date.isoformat() == date:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _convert_to_ist(datetime_object, timezone):
|
||||
offset = datetime.timedelta(minutes=timezone)
|
||||
datetime_object = datetime_object + offset
|
||||
offset = datetime.timedelta(minutes=-330)
|
||||
datetime_object = datetime_object - offset
|
||||
return datetime_object
|
||||
|
||||
def _convert_to_tz(datetime_object, timezone):
|
||||
offset = datetime.timedelta(minutes=timezone)
|
||||
datetime_object = datetime_object - offset
|
||||
offset = datetime.timedelta(minutes=-330)
|
||||
datetime_object = datetime_object + offset
|
||||
return datetime_object
|
||||
|
||||
def get_available_slots_between(start_time_parameter, end_time_parameter, settings):
|
||||
records = get_records(start_time_parameter, end_time_parameter, settings)
|
||||
timeslots = []
|
||||
appointment_duration = datetime.timedelta(
|
||||
minutes=settings.appointment_duration)
|
||||
for record in records:
|
||||
if record.day_of_week == weekdays[start_time_parameter.weekday()]:
|
||||
current_time = _deltatime_to_datetime(
|
||||
start_time_parameter, record.from_time)
|
||||
end_time = _deltatime_to_datetime(
|
||||
start_time_parameter, record.to_time)
|
||||
elif record.day_of_week == weekdays[end_time_parameter.weekday()]:
|
||||
current_time = _deltatime_to_datetime(
|
||||
end_time_parameter, record.from_time)
|
||||
end_time = _deltatime_to_datetime(
|
||||
end_time_parameter, record.to_time)
|
||||
while current_time + appointment_duration <= end_time:
|
||||
timeslots.append(current_time)
|
||||
current_time += appointment_duration
|
||||
return timeslots
|
||||
|
||||
|
||||
def get_records(start_time, end_time, settings):
|
||||
records = []
|
||||
for record in settings.availability_of_slots:
|
||||
if record.day_of_week == weekdays[start_time.weekday()] or record.day_of_week == weekdays[end_time.weekday()]:
|
||||
records.append(record)
|
||||
return records
|
||||
|
||||
|
||||
def _deltatime_to_datetime(date, deltatime):
|
||||
time = (datetime.datetime.min + deltatime).time()
|
||||
return datetime.datetime.combine(date.date(), time)
|
||||
|
||||
|
||||
weekdays = ["Monday", "Tuesday", "Wednesday",
|
||||
"Thursday", "Friday", "Saturday", "Sunday"]
|
@ -1,22 +0,0 @@
|
||||
{% 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 %}
|
@ -1,11 +0,0 @@
|
||||
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});
|
||||
}
|
25
erpnext/www/book-appointment/index.css
Normal file
25
erpnext/www/book-appointment/index.css
Normal file
@ -0,0 +1,25 @@
|
||||
.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;
|
||||
}
|
70
erpnext/www/book-appointment/index.html
Normal file
70
erpnext/www/book-appointment/index.html
Normal file
@ -0,0 +1,70 @@
|
||||
{% extends "templates/web.html" %}
|
||||
|
||||
{% block title %}{{ _("Book Appointment") }}{% endblock %}
|
||||
|
||||
{% block page_content %}
|
||||
<div class="container">
|
||||
<!-- title: Book an appointment -->
|
||||
<div id="select-date">
|
||||
<div class="text-center mb-5">
|
||||
<h3>Book an appointment</h3>
|
||||
<p class="lead">Select the date and your timezone</p>
|
||||
</div>
|
||||
<div class="row justify-content-center mt-3">
|
||||
<div class="col-md-4 align-self-center ">
|
||||
<form name="myform">
|
||||
<input type="date" onchange="validate_date()" name="appointment-date" id="appointment-date"
|
||||
class="form-control mt-3">
|
||||
<select name="appointment-timezone" id="appointment-timezone" class="form-control mt-3">
|
||||
</select>
|
||||
</form>
|
||||
<button class="form-control mt-3 btn btn-dark" id="next-button" onclick="navigate_to_time_select()">
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Select Time Slot-->
|
||||
<div id="select-time">
|
||||
<div class="text-center mb-5">
|
||||
<h3>Pick A Time Slot</h3>
|
||||
<p class="lead">Selected date is <span class="date-span">Date Span</span></p>
|
||||
</div>
|
||||
<div class="mt-3 justify-content-center">
|
||||
<div class="row" id="timeslot-container">
|
||||
|
||||
</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="initialise_enter_details()">
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Enter Details-->
|
||||
<div id="enter-details">
|
||||
<div class="text-center mb-5">
|
||||
<h3>Add details</h3>
|
||||
<p class="lead">Selected date is <span class="date-span">Date Span</span> at <span class="time-span"> time </span></p>
|
||||
</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>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
146
erpnext/www/book-appointment/index.js
Normal file
146
erpnext/www/book-appointment/index.js
Normal file
@ -0,0 +1,146 @@
|
||||
|
||||
frappe.ready(() => {
|
||||
initialise_select_date()
|
||||
})
|
||||
var holiday_list = [];
|
||||
|
||||
function navigator(page_no) {
|
||||
let select_date_div = document.getElementById('select-date');
|
||||
select_date_div.style.display = 'none';
|
||||
let select_time_div = document.getElementById('select-time');
|
||||
select_time_div.style.display = 'none';
|
||||
let contact_details_div = document.getElementById('enter-details');
|
||||
contact_details_div.style.display = 'none';
|
||||
let page;
|
||||
switch (page_no) {
|
||||
case 1: page = select_date_div; break;
|
||||
case 2: page = select_time_div; break;
|
||||
case 3: page = contact_details_div; break;
|
||||
}
|
||||
page.style.display = 'block'
|
||||
}
|
||||
|
||||
// Page 1
|
||||
async function initialise_select_date() {
|
||||
navigator(1);
|
||||
let timezones, settings;
|
||||
settings = (await frappe.call({
|
||||
method: 'erpnext.www.book-appointment.index.get_appointment_settings'
|
||||
})).message
|
||||
timezones = (await frappe.call({
|
||||
method: 'erpnext.www.book-appointment.index.get_timezones'
|
||||
})).message;
|
||||
holiday_list = (await frappe.call({
|
||||
method: 'erpnext.www.book-appointment.index.get_holiday_list',
|
||||
args: {
|
||||
'holiday_list_name': settings.holiday_list
|
||||
}
|
||||
})).message;
|
||||
let date_picker = document.getElementById('appointment-date');
|
||||
date_picker.max = holiday_list.to_date;
|
||||
date_picker.min = holiday_list.from_date;
|
||||
date_picker.value = (new Date()).toISOString().substr(0, 10);
|
||||
let timezones_element = document.getElementById('appointment-timezone');
|
||||
var offset = new Date().getTimezoneOffset();
|
||||
timezones.forEach(timezone => {
|
||||
var opt = document.createElement('option');
|
||||
opt.value = timezone.offset;
|
||||
opt.innerHTML = timezone.timezone_name;
|
||||
opt.defaultSelected = (offset == timezone.offset)
|
||||
timezones_element.appendChild(opt)
|
||||
});
|
||||
}
|
||||
|
||||
function validate_date() {
|
||||
let date_picker = document.getElementById('appointment-date');
|
||||
if (date_picker.value === '') {
|
||||
frappe.throw('Please select a date')
|
||||
}
|
||||
}
|
||||
|
||||
// Page 2
|
||||
async function navigate_to_time_select() {
|
||||
navigator(2);
|
||||
timezone = document.getElementById('appointment-timezone').value
|
||||
date = document.getElementById('appointment-date').value;
|
||||
var date_spans = document.getElementsByClassName('date-span');
|
||||
for (var i = 0; i < date_spans.length; i++) date_spans[i].innerHTML = date;
|
||||
// date_span.addEventListener('click',initialise_select_date)
|
||||
// date_span.style.color = '#5e64ff';
|
||||
// date_span.style.textDecoration = 'underline';
|
||||
// date_span.style.cursor = 'pointer';
|
||||
var slots = (await frappe.call({
|
||||
method: 'erpnext.www.book-appointment.index.get_appointment_slots',
|
||||
args: {
|
||||
date: date,
|
||||
timezone: timezone
|
||||
}
|
||||
})).message;
|
||||
let timeslot_container = document.getElementById('timeslot-container');
|
||||
console.log(slots)
|
||||
if (slots.length <= 0) {
|
||||
let message_div = document.createElement('p');
|
||||
|
||||
message_div.innerHTML = "There are no slots available on this date";
|
||||
timeslot_container.appendChild(message_div);
|
||||
}
|
||||
for (let i = 0; i < slots.length; i++) {
|
||||
const slot = slots[i];
|
||||
var timeslot_div = document.createElement('div');
|
||||
timeslot_div.classList.add('time-slot');
|
||||
timeslot_div.classList.add('col-md');
|
||||
if (!slot.availability) {
|
||||
timeslot_div.classList.add('unavailable')
|
||||
}
|
||||
timeslot_div.innerHTML = slot.time.substr(11, 20);
|
||||
timeslot_div.id = slot.time.substr(11, 20);
|
||||
timeslot_container.appendChild(timeslot_div);
|
||||
}
|
||||
set_default_timeslot()
|
||||
let time_slot_divs = document.getElementsByClassName('time-slot');
|
||||
for (var i = 0; i < time_slot_divs.length; i++) {
|
||||
time_slot_divs[i].addEventListener('click', select_time);
|
||||
}
|
||||
}
|
||||
|
||||
function select_time() {
|
||||
if (this.classList.contains("unavailable")) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
selected_element = document.getElementsByClassName('selected')[0]
|
||||
} catch (e) {
|
||||
this.classList.add("selected")
|
||||
}
|
||||
selected_element.classList.remove("selected");
|
||||
this.classList.add("selected");
|
||||
}
|
||||
|
||||
function set_default_timeslot() {
|
||||
let timeslots = document.getElementsByClassName('time-slot')
|
||||
for (let i = 0; i < timeslots.length; i++) {
|
||||
const timeslot = timeslots[i];
|
||||
if (!timeslot.classList.contains('unavailable')) {
|
||||
timeslot.classList.add("selected");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function initialise_enter_details() {
|
||||
navigator(3);
|
||||
let time_div = document.getElementsByClassName('selected')[0];
|
||||
let time_span = document.getElementsByClassName('time-span')[0];
|
||||
time_span.innerHTML = time_div.id
|
||||
}
|
||||
|
||||
function submit() {
|
||||
var date = document.getElementById('appointment-date').value;
|
||||
var time = document.getElementsByClassName('selected')[0].id;
|
||||
contact = {};
|
||||
contact.name = document.getElementById('customer_name').value;
|
||||
contact.number = document.getElementById('customer_number').value;
|
||||
contact.skype = document.getElementById('customer_skype').value;
|
||||
contact.notes = document.getElementById('customer_notes').value;
|
||||
console.log({ date, time, contact });
|
||||
}
|
123
erpnext/www/book-appointment/index.py
Normal file
123
erpnext/www/book-appointment/index.py
Normal file
@ -0,0 +1,123 @@
|
||||
import frappe
|
||||
import datetime
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_appointment_settings():
|
||||
settings = frappe.get_doc('Appointment Booking Settings')
|
||||
return settings
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_holiday_list(holiday_list_name):
|
||||
holiday_list = frappe.get_doc('Holiday List',holiday_list_name)
|
||||
return holiday_list
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_timezones():
|
||||
timezones = frappe.get_list('Timezone',fields='*')
|
||||
return timezones
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def get_appointment_slots(date,timezone):
|
||||
timezone = int(timezone)
|
||||
format_string = '%Y-%m-%d %H:%M:%S'
|
||||
query_start_time = datetime.datetime.strptime(date + ' 00:00:00',format_string)
|
||||
query_end_time = datetime.datetime.strptime(date + ' 23:59:59',format_string)
|
||||
query_start_time = _convert_to_ist(query_start_time,timezone)
|
||||
query_end_time = _convert_to_ist(query_end_time,timezone)
|
||||
# Database queries
|
||||
settings = frappe.get_doc('Appointment Booking Settings')
|
||||
holiday_list = frappe.get_doc('Holiday List', settings.holiday_list)
|
||||
timeslots = get_available_slots_between(query_start_time, query_end_time, settings)
|
||||
|
||||
# Filter timeslots based on date
|
||||
converted_timeslots = []
|
||||
for timeslot in timeslots:
|
||||
# Check if holiday
|
||||
if _is_holiday(timeslot.date(),holiday_list):
|
||||
converted_timeslots.append(dict(time=_convert_to_tz(timeslot,timezone),availability=False))
|
||||
continue
|
||||
# Check availability
|
||||
if check_availabilty(timeslot,settings):
|
||||
converted_timeslots.append(dict(time=_convert_to_tz(timeslot,timezone),availability=True))
|
||||
else:
|
||||
converted_timeslots.append(dict(time=_convert_to_tz(timeslot,timezone),availability=False))
|
||||
date_required = datetime.datetime.strptime(date + ' 00:00:00',format_string).date()
|
||||
converted_timeslots = filter_timeslots(date_required,converted_timeslots)
|
||||
return converted_timeslots
|
||||
|
||||
def get_available_slots_between(query_start_time, query_end_time, settings):
|
||||
records = _get_records(query_start_time, query_end_time, settings)
|
||||
timeslots = []
|
||||
appointment_duration = datetime.timedelta(
|
||||
minutes=settings.appointment_duration)
|
||||
for record in records:
|
||||
if record.day_of_week == WEEKDAYS[query_start_time.weekday()]:
|
||||
current_time = _deltatime_to_datetime(
|
||||
query_start_time, record.from_time)
|
||||
end_time = _deltatime_to_datetime(
|
||||
query_start_time, record.to_time)
|
||||
else :
|
||||
current_time = _deltatime_to_datetime(
|
||||
query_end_time, record.from_time)
|
||||
end_time = _deltatime_to_datetime(
|
||||
query_end_time, record.to_time)
|
||||
while current_time + appointment_duration <= end_time:
|
||||
timeslots.append(current_time)
|
||||
current_time += appointment_duration
|
||||
return timeslots
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def create_appointment(date,time,contact):
|
||||
|
||||
appointment = frappe.frappe.get_doc('Appointment')
|
||||
appointment.scheduled_time = date
|
||||
|
||||
def filter_timeslots(date,timeslots):
|
||||
filtered_timeslots = []
|
||||
for timeslot in timeslots:
|
||||
if(timeslot['time'].date() == date):
|
||||
filtered_timeslots.append(timeslot)
|
||||
return filtered_timeslots
|
||||
|
||||
def check_availabilty(timeslot,settings):
|
||||
return frappe.db.count('Appointment',{'scheduled_time':timeslot})<settings.number_of_agents
|
||||
|
||||
|
||||
|
||||
def _is_holiday(date, holiday_list):
|
||||
for holiday in holiday_list.holidays:
|
||||
if holiday.holiday_date == date:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _get_records(start_time, end_time, settings):
|
||||
records = []
|
||||
for record in settings.availability_of_slots:
|
||||
if record.day_of_week == WEEKDAYS[start_time.weekday()] or record.day_of_week == WEEKDAYS[end_time.weekday()]:
|
||||
records.append(record)
|
||||
return records
|
||||
|
||||
def _deltatime_to_datetime(date, deltatime):
|
||||
time = (datetime.datetime.min + deltatime).time()
|
||||
return datetime.datetime.combine(date.date(), time)
|
||||
|
||||
def _datetime_to_deltatime(date_time):
|
||||
midnight = datetime.datetime.combine(date_time.date(),datetime.time.min)
|
||||
return (date_time-midnight)
|
||||
|
||||
def _convert_to_ist(datetime_object, timezone):
|
||||
offset = datetime.timedelta(minutes=timezone)
|
||||
datetime_object = datetime_object + offset
|
||||
offset = datetime.timedelta(minutes=-330)
|
||||
datetime_object = datetime_object - offset
|
||||
return datetime_object
|
||||
|
||||
def _convert_to_tz(datetime_object, timezone):
|
||||
offset = datetime.timedelta(minutes=timezone)
|
||||
datetime_object = datetime_object - offset
|
||||
offset = datetime.timedelta(minutes=-330)
|
||||
datetime_object = datetime_object + offset
|
||||
return datetime_object
|
||||
|
||||
WEEKDAYS = ["Monday", "Tuesday", "Wednesday",
|
||||
"Thursday", "Friday", "Saturday", "Sunday"]
|
Loading…
x
Reference in New Issue
Block a user