trytonpsk-rental/booking.py

391 lines
13 KiB
Python

# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from __future__ import with_statement
from datetime import timedelta, datetime, time, date
from collections import OrderedDict
from trytond.model import Workflow, ModelView, ModelSQL, fields
from trytond.pyson import Eval, If, In, Get
from trytond.transaction import Transaction
from trytond.pool import Pool
STATES = {
'readonly': (Eval('state') != 'draft')
}
class Booking(Workflow, ModelSQL, ModelView):
'Rental Booking'
__name__ = 'rental.booking'
_rec_name = 'number'
number = fields.Char('Number', readonly=True)
equipment = fields.Many2One('maintenance.equipment', 'Equipment',
states=STATES)
type_document = fields.Selection([
('', ''),
('passport', 'Passport'),
('driver_license', 'Driver License'),
('medicare_card', 'Medicare Card'),
], 'Document Type', states=STATES)
doc_number = fields.Char('Doc. Number', required=True)
party = fields.Many2One('party.party', 'Customer',
states=STATES)
first_name = fields.Char('First Name', required=True)
last_name = fields.Char('Last Name', required=True)
mobile = fields.Char('Mobile', required=True)
email = fields.Char('Email', required=True)
signature = fields.Char('signature')
subdivision = fields.Many2One('country.subdivision', 'Subdivision')
address = fields.Char('Address', states=STATES)
city = fields.Char('City', states=STATES)
suburb = fields.Char('Suburb', states=STATES)
post_code = fields.Char('Post Code', states=STATES)
company = fields.Many2One('company.company', 'Company', required=True,
states=STATES, domain=[
('id', If(In('company', Eval('context', {})), '=', '!='),
Get(Eval('context', {}), 'company', 0))
])
product = fields.Many2One('product.product', 'Product', domain=[
('template.type', '=', 'assets')
], states=STATES)
brand = fields.Many2One('maintenance.equipment.brand', 'Brand')
lapse_time = fields.Integer('Lapse Time', states=STATES)
booking_date = fields.Date('Booking Date', states=STATES)
start_date = fields.DateTime('Start Date', states=STATES)
end_date = fields.DateTime('End Date', states=STATES)
comment = fields.Char('Comment', states=STATES)
signature = fields.Char('Signature', states=STATES)
notification_pickup = fields.Boolean('SMS Notification Pickup')
state = fields.Selection([
('draft', 'Draft'),
('booking', 'Booking'),
('processed', 'Processed'),
('cancelled', 'Cancelled'),
], 'State', readonly=True, required=True)
state_string = state.translated('state')
@classmethod
def __setup__(cls):
super(Booking, cls).__setup__()
cls._order = [
('booking_date', 'DESC'),
('number', 'DESC'),
]
cls._transitions |= set((
('draft', 'cancelled'),
('booking', 'cancelled'),
('cancelled', 'booking'),
('draft', 'booking'),
('booking', 'draft'),
('booking', 'processed')
))
cls._buttons.update({
'draft': {
'invisible': Eval('state').in_(['processed', 'draft']),
},
'cancel': {
'invisible': Eval('state').in_(['cancelled', 'processed']),
},
'booking': {
'invisible': Eval('state') != 'draft',
},
'process': {
'invisible': Eval('state') != 'booking',
},
'send_notification_pickup': {
'invisible': Eval('notification_pickup'),
}
})
@classmethod
def copy(cls, records, default=None):
if default is None:
default = {}
default = default.copy()
default['number'] = None
default['state'] = 'draft'
new_records = []
for record in records:
new_record, = super(Booking, cls).copy(
[record], default=default
)
new_records.append(new_record)
return new_records
@classmethod
def search_rec_name(cls, name, clause):
if clause[1].startswith('!') or clause[1].startswith('not '):
bool_op = 'AND'
else:
bool_op = 'OR'
return [bool_op, ('mobile',) + tuple(clause[1:])]
@staticmethod
def default_company():
return Transaction().context.get('company') or None
@staticmethod
def default_booking_date():
Date = Pool().get('ir.date')
return Date.today()
@staticmethod
def default_state():
return 'draft'
@classmethod
@ModelView.button
@Workflow.transition('draft')
def draft(cls, records):
print("¡Transición a estado 'draft' realizada con éxito!")
pass
@classmethod
@ModelView.button
@Workflow.transition('cancelled')
def cancel(cls, records):
pass
@classmethod
@ModelView.button
@Workflow.transition('booking')
def booking(cls, records):
cls.set_number(records)
# for rec in records:
# rec.send_emails()
# res = {
# 'status': 'success',
# 'msg': 'Booking succesful, please check your mail for more details!'
# }
# return res
# @classmethod
# def create(cls, vlist):
# bookings = super(Booking, cls).create(vlist)
# print('paso por aca')
# for boo in bookings:
# boo.send_email_confirmation()
# return bookings
def send_email_confirmation(self):
print(self, "self")
pool = Pool()
config = pool.get('rental.configuration')(1)
Template = pool.get('email.template')
return Template.send(config.email_booking_customer, self, self.email)
# return Template.send(config.email_booking_customer, self, self.email, attach=True)
@classmethod
@ModelView.button
def send_notification_pickup(cls, records):
for record in records:
record.send_sms_pickup()
cls.write([record], {'notification_pickup': True})
@classmethod
@ModelView.button
@Workflow.transition('processed')
def process(cls, records):
for record in records:
record.create_service()
record.send_emails()
@fields.depends('lapse_time', 'start_date', 'end_date')
def on_change_with_end_date(self, name=None):
config = Pool().get('rental.configuration')(1)
if self.start_date and self.lapse_time and config.rental_uom:
delta = timedelta(days=self.lapse_time)
if config.rental_uom.symbol == 'h':
delta = timedelta(hours=self.lapse_time)
end_date = self.start_date + delta
return end_date
@classmethod
def get_hours_available(cls, args):
pool = Pool()
config = pool.get('rental.configuration')(1)
User = pool.get('res.user')
Company = pool.get('company.company')
transaction = Transaction()
product_id = args.get('product')
start_date = args.get('start_date')
user_id = args.get('user')
if not all([product_id, start_date, user_id]):
return []
user = User(user_id)
if config.booking_start_time:
start_tm = config.booking_start_time
else:
start_tm = time(0, 0)
if config.booking_end_time:
end_tm = config.booking_end_time
else:
end_tm = time(23, 59)
res = OrderedDict()
for value in range(start_tm.hour, end_tm.hour):
fmt_value = time(value, 0)
fmt_value = fmt_value.strftime('%I:%M %p')
res[value] = {
'id': value,
'hour': fmt_value,
'status': 'available'
}
new_date = datetime.strptime(start_date, '%Y-%m-%d').date()
ctx = transaction.context.get('user')
start_date = datetime.combine(new_date, start_tm)
end_date = datetime.combine(new_date, end_tm)
with transaction.set_context(ctx):
start_date = Company.convert_timezone(start_date, True, user.company.id)
end_date = Company.convert_timezone(end_date, True, user.company.id)
bookings = cls.search([
('product', '=', product_id),
('start_date', '>=', start_date),
('start_date', '<=', end_date),
('state', 'in', ['draft', 'booking', 'processed']),
])
for bk in bookings:
with transaction.set_context(ctx):
start_date = Company.convert_timezone(bk.start_date, False, user.company.id)
hour = start_date.time().hour
res[hour]['status'] = 'not_available'
return res.values()
def send_sms_pickup(self):
pool = Pool()
config = pool.get('rental.configuration')(1)
template_sms = config.sms_customer_pickup
if not template_sms:
return
template_sms.server.send_message(self.mobile, template_sms.content)
def send_emails(self):
pool = Pool()
config = pool.get('rental.configuration')(1)
Template = pool.get('email.template')
print("template", config.email_rental_customer )
print("selft", self )
print("self.email", self.email )
try:
response = Template.send(config.email_rental_customer, self, self.email)
if response.status_code == 202:
print('correo enviado')
else:
response.json()
Template.send(config.email_rental_company, self, self.company.party.email)
except Exception as e:
print(e)
def send_emails_asignature(self):
pool = Pool()
config = pool.get('rental.configuration')(1)
Template = pool.get('email.template')
return Template.send(config.emaild_rental_customer, self, self.email)
def create_service(self):
print(self, "paso por aca para crear el servicio")
pool = Pool()
Party = pool.get('party.party')
Rental = pool.get('rental.service')
Config = pool.get('rental.configuration')
Equipment = pool.get('maintenance.equipment')
Item = pool.get('product.check_list_item')
ProductCheckList = pool.get('rental.service.product_check_list')
config = Config(1)
values = {
'name': self.first_name + ' ' + self.last_name,
'id_number': self.doc_number,
'addresses': [('create', [{
'street': self.address,
}])],
'contact_mechanisms': [
('create', [
{'type': 'email', 'value': self.email},
{'type': 'mobile', 'value': self.mobile},
])
]
}
if hasattr(Party, 'first_name') and hasattr(Party, 'last_name'):
values['first_name'] = self.first_name
values['last_name'] = self.last_name
party, = Party.create([values])
if not config.default_service:
return
values = {
'party': party.id,
'booking': self.id,
'service_product': config.default_service.id,
'photo_link_signature': self.signature,
'service_date': self.booking_date,
'start_date': date.today(),
'state': 'draft'
}
if self.product:
values['product'] = self.product.id
if self.equipment:
values['equipment'] = self.equipment.id
elif self.product:
equipments = Equipment.search([
('product', '=', self.product.id)
])
if equipments:
values['equipment'] = equipments[0].id
rental, = Rental.create([values])
def _get_item(item):
return {
'rental_service': rental.id,
'item': item.id,
'kind': item.kind,
}
items_to_create = []
for item in config.default_check_list:
items_to_create.append(_get_item(item))
childs = Item.search([
('parent', '=', item.id)
])
for child in childs:
items_to_create.append(_get_item(child))
ProductCheckList.create(items_to_create)
@classmethod
def set_number(cls, records):
'''
Fill the number field with the service sequence
'''
pool = Pool()
Config = pool.get('rental.configuration')
config = Config(1)
for record in records:
if record.number:
continue
if not config.rental_booking_sequence:
continue
number = config.rental_booking_sequence.get()
cls.write([record], {'number': number})