How to calculate number of nights for hotel management module in Odoo 8 - odoo-8
I am working on hotel management module in odoo version 8.
I wish to calculate number of nights stayed between check-in date and check-out date. Can anyone help me with this?
I defined a class for reservations, with on change methods for check-in and check-out. I tried for a function calculating total_nights. Here is my code,
class hotel_reservation(osv.Model):
_name = "hotel.reservation"
_rec_name = "reservation_no"
_description = "Reservation"
_order = 'reservation_no desc'
_columns = {
'reservation_no': fields.char('Reservation No', size=64, required=True, readonly=True),
'date_order':fields.datetime('Date Ordered', required=True, readonly=True, states={'draft':[('readonly', False)]}),
'warehouse_id':fields.many2one('stock.warehouse', 'Hotel', readonly=True, required=True, states={'draft':[('readonly', False)]}),
'partner_id':fields.many2one('res.partner', 'Guest Name', readonly=True, required=True, states={'draft':[('readonly', False)]}),
'pricelist_id':fields.many2one('product.pricelist', 'Price List', required=True, readonly=True, states={'draft':[('readonly', False)]}, help="Pricelist for current reservation. "),
'partner_invoice_id':fields.many2one('res.partner', 'Invoice Address', readonly=True, states={'draft':[('readonly', False)]}, help="Invoice address for current reservation. "),
'partner_order_id':fields.many2one('res.partner', 'Ordering Contact', readonly=True, states={'draft':[('readonly', False)]}, help="The name and address of the contact that requested the order or quotation."),
'partner_shipping_id':fields.many2one('res.partner', 'Delivery Address', readonly=True, states={'draft':[('readonly', False)]}, help="Delivery address for current reservation. "),
'checkin': fields.datetime('Expected-Date-Arrival', required=True, readonly=True, states={'draft':[('readonly', False)]}),
'checkout': fields.datetime('Expected-Date-Departure', required=True, readonly=True, states={'draft':[('readonly', False)]}),
'adults':fields.integer('Adults', size=64, readonly=True, states={'draft':[('readonly', False)]}, help='List of adults there in guest list. '),
'children':fields.integer('Children', size=64, readonly=True, states={'draft':[('readonly', False)]}, help='Number of children there in guest list. '),
'reservation_line':fields.one2many('hotel_reservation.line', 'line_id', 'Reservation Line', help='Hotel room reservation details. '),
'state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirm'), ('cancel', 'Cancel'), ('done', 'Done')], 'State', readonly=True),
'folio_id': fields.many2many('hotel.folio', 'hotel_folio_reservation_rel', 'order_id', 'invoice_id', 'Folio'),
'dummy': fields.datetime('Dummy'),
#'No_of_nights': fields.integer('Number of Nights', size=64, readonly=True, states={'draft':[('readonly', False)]}, help='Number of Nights.'),
'no_of_nights':fields.function(_total_nights, string='Amount to be returned',
store={
'value': (lambda self, cr, uid, ids, c={}: ids, ['amount', 'roi'], 10),
},),
}
_defaults = {
'reservation_no': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'hotel.reservation'),
'state': lambda *a: 'draft',
'date_order': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
}
def on_change_checkin(self, cr, uid, ids, date_order, checkin_date=time.strftime('%Y-%m-%d %H:%M:%S'), context=None):
if date_order and checkin_date:
if checkin_date < date_order:
raise osv.except_osv(_('Warning'), _('Checkin date should be greater than the current date.'))
return {'value':{}}
def on_change_checkout(self, cr, uid, ids, checkin_date=time.strftime('%Y-%m-%d %H:%M:%S'), checkout_date=time.strftime('%Y-%m-%d %H:%M:%S'), context=None):
if not (checkout_date and checkin_date):
return {'value':{}}
if checkout_date < checkin_date:
raise osv.except_osv(_('Warning'), _('Checkout date should be greater than the Checkin date.'))
delta = datetime.timedelta(days=1)
addDays = datetime.datetime(*time.strptime(checkout_date, '%Y-%m-%d %H:%M:%S')[:5]) + delta
val = {'value':{'dummy':addDays.strftime('%Y-%m-%d %H:%M:%S')}}
return val
def onchange_partner_id(self, cr, uid, ids, partner_id):
if not partner_id:
return {'value':{'partner_invoice_id': False, 'partner_shipping_id':False, 'partner_order_id':False}}
partner_obj = self.pool.get('res.partner')
addr = partner_obj.address_get(cr, uid, [partner_id], ['delivery', 'invoice', 'contact'])
pricelist = partner_obj.browse(cr, uid, partner_id).property_product_pricelist.id
return {'value':{'partner_invoice_id': addr['invoice'], 'partner_order_id':addr['contact'], 'partner_shipping_id':addr['delivery'], 'pricelist_id': pricelist}}
def total_nights(self, cr, uid, ids, context=None):
print("Function for Calculating total Nights !")
context = context or {}
res = {}
''''''
for value in self.browse(cr, uid, ids, checkin_date=time.strftime('%Y-%m-%d %H:%M:%S'), checkout_date=time.strftime('%Y-%m-%d %H:%M:%S'), context=context):
check_in = datetime.strptime(check_in, "%Y-%m-%d")
check_out = datetime.strptime(check_out, "%Y-%m-%d")
delta = check_out - check_in
print delta.days
return res
class hotel_room_reservation_line(osv.Model):
_name = 'hotel.room.reservation.line'
_description = 'Hotel Room Reservation'
_rec_name = 'room_id'
_columns = {
'room_id': fields.many2one('hotel.room', 'Room id'),
'check_in':fields.datetime('Check In Date', required=True),
'check_out': fields.datetime('Check Out Date', required=True),
'state': fields.selection([('assigned', 'Assigned'), ('unassigned', 'Unassigned')], 'Room Status'),
'reservation_id': fields.many2one('hotel.reservation', 'Reservation'),
}
hotel_room_reservation_line()
This code may help you:
# Making difference in dates to get no. of days .....
#api.one
#api.onchange('check_in')
def onchange_date_time(self):
# print 'working till now ----------------------------'
if self.check_in:
check_in = datetime.datetime.strptime(self.check_in, "%Y-%m-%d").date()
if check_in<datetime.date.today():
#raise except_orm('Error','Please enter the correct date')
self.check_in = None
else:
pass
#api.one
#api.onchange('check_out')
def onchange_check_out(self):
if self.check_out:
check_out = datetime.datetime.strptime(self.check_out, "%Y-%m-%d").date()
check_in = datetime.datetime.strptime(self.check_in, "%Y-%m-%d").date()
if check_out<datetime.date.today():
self.check_out = False
# if not self.check_out:
# raise osv.except_orm('Error','Please enter the correct date')
else:
pass
#api.onchange('check_out')
def onchange_num_day(self):
if self.check_out and self.check_in:
check_in = datetime.datetime.strptime(self.check_in, "%Y-%m-%d").date()
check_out = datetime.datetime.strptime(self.check_out, "%Y-%m-%d").date()
self.days = (check_out-check_in).days+1
if self.days == 0:
self.days = 1
#Hence we will get No.of days .. Ends
fields: checked_in,checked_out,days
Thanks
Related
Unable to create profile from user Serializer (Django-resst-framework)
I have 2 models, Account model as shown class Account(AbstractBaseUser,PermissionsMixin): email = models.EmailField(max_length=100, unique = True) username = models.CharField(max_length = 30) is_admin = models.BooleanField(default = False) is_staff = models.BooleanField(default = False) is_active = models.BooleanField(default = False) date_joined = models.DateTimeField(auto_now_add = True) USERNAME_FIELD = 'email' REQUIRED_FIELDS = [ 'username' ] and the profile table as shown below class Profile(models.Model): user = models.OneToOneField(Account, on_delete = models.CASCADE) avatar = models.ImageField(default = "defaultpic.png", blank = True, null = True, upload_to="MEDIA_FILES" ) tel = PhoneField(blank=False, null = False) ProfileSerializer class ProfileSerializer(serializers.ModelSerializer): class Meta: model = Profile fields = [ 'avatar', 'tel', ] UserSerializer class AccountSerializer(serializers.ModelSerializer): profile = ProfileSerializer(read_only = True) class Meta: model = get_user_model() fields = [ 'email', 'username', 'password', 'profile' ] extra_kwargs = { 'password': {'write_only': True}, } def create(self, validated_data): user_password = validated_data.pop('password') user = get_user_model()( email = validated_data['email'], username = validated_data['username'] ) user.set_password(user_password) user.save() user.email_user("Hello world") return user Endpoint to register a new user #api_view(["POST"]) #permission_classes([AllowAny, ]) def register(request): profSerializer = ProfileSerializer( data = request.data ) serializer = AccountSerializer( data = request.data ) if serializer.is_valid(): serializer.save() serializer.send_mail("Hello") return JsonResponse( serializer.data ) else: print( serializer.errors ) return JsonResponse( { "_err": serializer.errors } ) My problem now comes in when I send a post request to the registering endpoint, the profile fields remain empty, the avatar field is assigned the default value of default.png. I need the endpoint to create both user account and profile entries whenever a user sign up The post request to the endpoint is the following JSON { email:"some email", username:"username", password:"password", tel:"tel number", avatar:"image" }
In your AccountSerializer you have set the profile field to read only: profile = ProfileSerializer(read_only=True) This means the field will be neglected and will not be shown in request.data. Then you need a little change in your create method, something like this: def create(self, validated_data): profile_data = validated_data['profile'] # user creation steps ... profile = Profile( user=user, **profile_data ) profile.save() return user rest_framework cannot create related objects by default, this is why you need to create an account instance first, and then create a Profile by yourself Then, you do not need to serialize request.data with ProfileSerializer in your view, remove the line and change the request body to: { email:"some email", username:"username", password:"password", profile: { tel:"tel number", avatar:"image" } } I suggest you learning about nested serializers and how they work
generate random username automatically in django rest
Is there any way to generate the username automatically. and I also need username while signing in so it must be unique- class User(AbstractUser): username = models.CharField(max_length=50, unique=True, null= False, blank=False) email = models.EmailField(unique=True, null=False, blank=False) USERNAME_FIELD = 'username' def __str__(self): return "{}".format(self.email) below is the code for user create serializer: class UserSerializer(serializers.HyperlinkedModelSerializer): profile = UserProfileSerializer(required=True) username = serializers.CharField(label="username field", required=True, allow_null=False, allow_blank=False) class Meta: model = User fields = ('id', 'username', 'email', 'first_name', 'last_name', 'password', 'profile') extra_kwargs = {'password': {'write_only': True}, 'first_name': {'required': True}, 'last_name': {'required': True}} def create(self, validated_data): profile_data = validated_data.pop('profile') password = validated_data.pop('password') try: if User.objects.filter(username__iexact=User(**validated_data).username).exists(): raise serializers.ValidationError("username already exists") except Exception as e: error = {'message': ",".join(e.args) if len(e.args) > 0 else 'Unknown Error'} raise serializers.ValidationError(error) user = User(**validated_data) print(user.username) user.set_password(password) user.save() UserProfile.objects.create(user=user, **profile_data) return user what changes should i make to generate username automatically?
You should raise ValidationError only from validate functions. Use managers to create objects. User model has built-in create_user method. To generate username you could use a library such as coolname. Create two serializers. One for creating user and another one for reading. If you want to allow users to specify their own username, add a validator on the field. Move profile creation to create_user method. from coolname import generate_slug class UserCreateSerializer(serializers.HyperlinkedModelSerializer): username = serializers.CharField( min_length=3, max_length=50, validators=[UniqueValidator(queryset=User.objects.all())], allow_null=True, default=None ) class Meta: model = User fields = ('username',) def validate_username(self, val): return val or generate_slug() def perform_create(self, validated_data): # use User manager ...
You can use this method: from allauth.utils import generate_unique_username Then you can generate unique usernames like this: # Create user object first_name = 'My firstname' last_name = 'My lastname' email = 'myemail#gmail.com' user = User() user.first_name = first_name user.last_name = last_name user.email = email user.username = generate_unique_username([f'{first_name} {last_name}', email, 'user']) user.save()
How to get the nested objects in DRF
I have two models Role and User. User model has a foreign-key field associated with model Role. Model Role class Role(models.Model): role_name = models.CharField(max_length=255, blank=False, unique=True) def __str__(self): return 'Role Object ({})'.format(self.id, self.role_name) Model User class User(AbstractBaseUser, PermissionsMixin): first_name = models.CharField(max_length=255, blank=False) last_name = models.CharField(max_length=255, blank=False) email = models.EmailField(max_length=255, blank=False, unique= True) phone_number = models.BigIntegerField(blank=False, unique= True) password = models.TextField(blank=False) company_name = models.CharField(max_length=255, null=True, unique=True) is_active = models.BooleanField(default= False) role = models.ForeignKey(Role, related_name='group_name', on_delete=models.CASCADE, blank=False) business = models.ForeignKey(Businesses, on_delete=models.CASCADE, null=True) objects = UserManager() USERNAME_FIELD = 'email' def __str__(self): return 'User Object ({})'.format(self.id) Using ModelSerializer and ListAPIView I want to get the list of all the users as shown below - { "first_name": "", "last_name":"", "email":"", "phone_number":, "is_active":"", "role":{ "id":1, "role_name": "Admin" } } Also, I have created serializers - class AdminSerializer(serializers.ModelSerializer): role = RoleSerializer(read_only=True) class Meta: model = User fields = ['id', 'first_name', 'last_name', 'email', 'phone_number', 'password', 'role', 'is_active' ] read_only_field = ['role_name'] extra_kwargs = { 'password':{ 'write_only':True }, 'is_active':{ 'required':False } } def create(self, validated_data): return User.objects.create_user(**validated_data) class RoleSerializer(serializers.ModelSerializer): class Meta: model = Role field = ['id', 'role_name'] What exactly should I do to my serializer to achieve desire output. What exactly should I write in my ListAPIView() what a ListAPIVIew returns. class UsersListAPIView(ListAPIView): queryset = User.objects.all() serializer_class = AdminSerializer def list(self, request): queryset = self.get_queryset().filter(role=request.query_params.get['id']).prefetch_related("group_name") serializer = AdminSerializer(queryset, many=True) return Response(serializer.data) This returns an error - TypeError: 'method' object is not subscriptable
Cannot Login using Custom User Model Django Rest Framework
I just create a Custom User Model with Django for Django Rest Framework, I create the generics.ListAPIView to get the list of User and Create New User Then I create the Login View with views.APIView with overridden post() with validation. But when I clicked the "POST", its return the "User already exists". Why the login method tried to create an account even when i use django-rest-auth? Thanks in advance here is the code models.py class AccountManager(BaseUserManager): def create_user(self, email, first_name=None, last_name=None, password=None, is_active=True, is_staff=False, is_admin=False, is_superuser=False): if not email: raise ValueError("User must have an email address") if not password: raise ValueError("User must have a password") if not first_name: raise ValueError("User must have a first name") user = self.model( email=self.normalize_email(email) ) user.set_password(password) user.first_name = first_name user.last_name = last_name user.staff = is_staff user.admin = is_admin user.active = is_active user.superuser = is_superuser user.save(using=self._db) return user def create_superuser(self, email, first_name=None, last_name=None, password=None): user = self.create_user( email=email, first_name = first_name, last_name = last_name, password=password, is_superuser=True, is_staff=True, is_admin=True, ) return user class Account(AbstractBaseUser): email =models.EmailField(max_length=255, unique=True) first_name = models.CharField(max_length=255,default='') last_name = models.CharField(max_length=255, default='') active = models.BooleanField(default=True) staff = models.BooleanField(default=False) admin = models.BooleanField(default=False) superuser = models.BooleanField(default=False) created_data = models.DateTimeField(auto_now_add=True) last_login = models.DateTimeField(auto_now=True) #USERNAME_FIELD and password are required by default USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['first_name', 'last_name'] objects = AccountManager() def __str__(self): return self.email def get_full_name(self): return (self.first_name + self.last_name) def get_short_name(self): return self.first_name def has_perm(self, perm, obj=None): return True def has_module_perms(self, app_label): return True #property def is_admin(self): return self.admin #property def is_staff(self): return self.staff #property def is_superuser(self): return self.superuser serializers.py class AccountRegistrationSerializer(serializers.ModelSerializer): # password = serializers.CharField(style={'input_type':'password'}, write_only=True) password2 = serializers.CharField(style={'input_type':'password'}, write_only=True) class Meta: model = Account extra_kwargs = { 'password': {'write_only': True} } fields = ['email', 'first_name', 'last_name','password', 'password2',] def create(self, validated_data): account = Account( email=self.validated_data['email'], first_name=self.validated_data['first_name'], last_name=self.validated_data['last_name'] ) password = self.validated_data['password'] password2 = self.validated_data['password2'] if password != password2: raise serializer.ValidationError({'password':'Passwords must match'}) account.set_password(password) account.save() return account class AccountLoginSerializer(serializers.ModelSerializer): class Meta: model = Account extra_kwargs = { 'password': { 'write_only': True }, 'first_name': { 'read_only': True }, 'last_name': { 'read_only': True }, } fields = ['email', 'first_name', 'last_name', 'password'] def validate(self, data): return data views.py class AccountLoginView(APIView): permission_classes = [AllowAny,] serializer_class = AccountLoginSerializer def post(self, request, *args, **kwargs): data = request.data serializer = AccountLoginSerializer(data=data) if serializer.is_valid(raise_exception=True): new_data = serializer.data return Response(new_data, status=HTTP_200_OK) return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)
it's been 5 days since I asked this question. I have solved this problem by override to_internal_value method and validate the serializers. serializer.py def to_internal_value(self, data): try: try: email = data["email"] user = Account.objects.filter(email=email) return data except KeyError: raise serializers.ValidationError({'email':'Please Input your Email'}) except ValueError: raise serializers.ValidationError({'email':'Email Not Valid'}) except Account.DoesNotExist: raise serializers.ValidationError({'error':'Database Error'}) def validate(self, data): user_obj=None email = data.get('email', None) password = data.get('password', None) if not email and not username: raise ValidationError({"error":"Need to be filled"}) user = Account.objects.filter( Q(email=email) ).distinct() user = user.exclude(email__isnull=True).exclude(email__iexact='') if user.exists() and user.count() == 1: user_obj = user.first() else: raise ValidationError({"email":"Not valid"}) if user_obj: if not user_obj.check_password(password): raise ValidationError({"password":"Incorrect credentials please try again"}) new_data = user_obj return new_data
Create model with foreign key and return serialized response
I'm trying to create a new note via a POST request that looks like this: {content: "hello world", user: 1} with a response that looks like this: { id: 1, content: "hello world", user: { id: 1, first_name: "Homer", last_name: "Simpson" }. After reading at the other foreign key questions I've been able to create the note and get back something like: { id: 1, content: "hello world", user: 1 } but I really need the additional user information. I attempted to modify the response using the to_representation like so: class NotePOSTSerializer(serializers.ModelSerializer): class Meta: model = Note fields = ('id', 'content', 'timestamp', 'user') def to_representation(self, instance): rep = super().to_representation(instance) """Convert `status` to human-readable.""" rep['user'] = UserSerializer(id=rep['user']) return rep but I got this error: TypeError: Object of type ModelState is not JSON serializable This is what I've got so far. Thanks in advance! models.py class Article(models.Model): id = models.PositiveSmallIntegerField('Article Id', null=True) title = models.CharField('Title', max_length=100) content = models.TextField('Description', blank=True, null=True) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) def __str__(self): return self.title class Note(models.Model): id = models.PositiveSmallIntegerField('Note Id', null=True) content = models.TextField('Content', blank=True) timestamp = models.DateTimeField('Timestamp', auto_now_add=True) user = models.ForeignKey(User, on_delete=models.CASCADE) views.py class ArticleListView(viewsets.ModelViewSet): serializer_class = ArticleSerializer queryset = Article.objects.all() class NoteListView(viewsets.ModelViewSet): serializer_class =NoteSerializer queryset = Note.objects.all() def get_serializer_class(self): assert self.serializer_class is not None, ( "'%s' should either include a `serializer_class` attribute, " "or override the `get_serializer_class()` method." % self.__class__.__name__ ) if self.request.method in ('POST', 'PUT'): return NotePOSTSerializer else: return self.serializer_class serializers.py class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ('id', 'username', 'first_name', 'last_name', 'email') class NoteSerializer(serializers.ModelSerializer): user = UserSerializer() class Meta: model = Note fields = ('id', 'content', 'timestamp', 'user') class NotePOSTSerializer(serializers.ModelSerializer): class Meta: model = Note fields = ('id', 'content', 'timestamp', 'user') class ArticleSerializer(serializers.ModelSerializer): notes = NoteSerializer(many=True, read_only=True) class Meta: model = Article fields = ('id', 'title', 'content', 'created', 'updated', 'notes')
I'm getting completely different errors, so I will just provide working code def to_representation(self, instance): rep = super().to_representation(instance) rep['user'] = UserSerializer(instance=User.objects.get(pk=instance.user_id)).data # UserSerializer(instance=instance) return rep