odoo/ext/3rd-party-addons/mobikul/models/mobikul.py

1353 lines
60 KiB
Python
Executable File

# -*- coding: utf-8 -*-
##########################################################################
#
# Copyright (c) 2015-Present Webkul Software Pvt. Ltd. (<https://webkul.com/>)
#
##########################################################################
from ast import literal_eval
from odoo import api, fields, models, _, SUPERUSER_ID
from odoo.tools.translate import html_translate
# import datetime
from odoo.exceptions import UserError
import random
import string
import inspect
import json
from .fcmAPI import FCMAPI
from datetime import datetime, timedelta
import logging
_logger = logging.getLogger(__name__)
from odoo.addons.base.ir.ir_mail_server import MailDeliveryException
def _displayWithCurrency(lang_obj, amount, symbol, position):
fmt = "%.{0}f".format(2) # currency.decimal_places
# lang = cls.env['res.lang']._lang_get(cls.env.context.get('lang') or 'en_US')
formatted_amount = lang_obj.format(fmt, amount , grouping=True, monetary=True) # currency.round(amount)
# _logger.info("-------%s"%formatted_amount)
return "%s%s"%(symbol,formatted_amount) if position=="before" else "%s%s"%(formatted_amount,symbol)
@api.model
def _lang_get(cls):
return cls.env['res.lang'].get_installed()
def _default_unique_key(size, chars=string.ascii_uppercase + string.digits):
return ''.join(random.choice(chars) for x in range(size))
def _get_image_url(base_url, model_name, record_id, field_name, width=0, height=0):
""" Returns a local url that points to the image field of a given browse record. """
if base_url and not base_url.endswith("/"):
base_url = base_url+"/"
if width or height:
return '%sweb/image/%s/%s/%s/%sx%s'% (base_url, model_name, record_id, field_name, width, height)
else:
return '%sweb/image/%s/%s/%s'% (base_url, model_name, record_id, field_name)
def _getProductData(p_data, base_url, currency_symbol, currency_position, lang_obj):
result = []
for prod in p_data:
result.append({
'templateId' :prod['id'] or '',
'name' :prod['name'] or '',
'priceUnit' :_displayWithCurrency(lang_obj, prod['lst_price'] or 0, currency_symbol, currency_position),
'priceReduce' :prod['price'] < prod['lst_price'] and _displayWithCurrency(lang_obj, prod['price'] or 0, currency_symbol, currency_position) or "",
'productId' :prod['product_variant_id'] and prod['product_variant_id'][0] or '',
'productCount' :prod['product_variant_count'] or 0,
'description' :prod['description_sale'] or '',
'thumbNail' :_get_image_url(base_url, 'product.template', prod['id'],'image')
})
return result
def _get_product_fields():
return ['name','product_variant_id','product_variant_count','price','description_sale','lst_price','website_price']
def _get_product_domain():
return [("sale_ok", "=", True), ("is_mobikul_available", "=", True)]
# def authenticate_request(fn):
# def ret_fn(*args, **kwargs):
# # userdata = inspect.getargspec(fn)
# # result = args[0].authenticate(args[1].get('usr'),args[1].get('pwd'))
# return "result %r %r"%(str(args), str(kwargs))
# if not result['success']:
# return "result %r %r "%(args, kwargs)
# else:
# return fn(*args,**kwargs)
# return ret_fn
class Mobikul(models.Model):
_name = "mobikul"
_description = "Mobikul Model"
@api.model
def _create_so(self, partner, local):
local = local or {}
result = {"success":True}
addr = partner.address_get(['delivery'])
so_data = {
'partner_id': partner.id,
'pricelist_id': self._context.get('pricelist'),
'payment_term_id': partner.property_payment_term_id.id,
'team_id': local.get("teamId"),
'partner_invoice_id': partner.id,
'partner_shipping_id': addr['delivery'],
'user_id': local.get("salespersonId"),
}
company = self.env['product.pricelist'].browse(self._context.get('pricelist')).sudo().company_id
if company:
so_data['company_id'] = company.id
result['order'] = self.env['sale.order'].sudo().create(so_data)
partner.write({'last_website_so_id': result['order'].id})
result['cartId']=result['order'].id
return result
@api.model
def _create_so_line(self, order, Product, qty=1):
result = {"success":True}
SaleOrderLineSudo = self.env['sale.order.line'].sudo()
product_context = dict(self.env.context)
product_context.setdefault('lang', order.partner_id.lang)
product_context.update({
'partner': order.partner_id.id,
'quantity': qty,
'date': order.date_order,
'pricelist': order.pricelist_id.id,
})
product = Product.with_context(product_context)
so_line_data = {
'name':product.name,
'product_id': product.id,
'product_uom_qty': qty,
'order_id': order.id,
'product_uom': product.uom_id.id,
'price_unit': product.price,
}
order_line = SaleOrderLineSudo.create(so_line_data)
order_line.product_id_change()
order_line.product_uom_change()
order_line._onchange_discount()
return result
# @api.multi
# def _get_line_description(self, order, product_id, attributes=None):
# if not attributes:
# attributes = {}
# product = self.env['product.product'].with_context(product_context).browse(product_id)
# name = product.display_name
# # add untracked attributes in the name
# untracked_attributes = []
# for k, v in attributes.items():
# # attribute should be like 'attribute-48-1' where 48 is the product_id, 1 is the attribute_id and v is the attribute value
# attribute_value = self.env['product.attribute.value'].sudo().browse(int(v))
# if attribute_value and not attribute_value.attribute_id.create_variant:
# untracked_attributes.append(attribute_value.name)
# if untracked_attributes:
# name += '\n%s' % (', '.join(untracked_attributes))
# if product.description_sale:
# name += '\n%s' % (product.description_sale)
# return name
@api.model
def _validate(self, api_key,context=None):
context = context or {}
response = {'success':False, 'responseCode':0, 'message':_('Unknown Error !!!')}
if not api_key:
response['message'] = _('Invalid/Missing Api Key !!!')
return response
try:
# Get Mobikul Conf
mobikul = self.env['mobikul'].sudo().search([], limit=1)
if not mobikul:
response['responseCode'] = 1
response['message'] = _("Mobikul Configuration not found !!!")
elif mobikul.api_key != api_key:
response['responseCode'] = 1
response['message'] = _("API Key is invalid !!!")
else:
response['success'] = True
response['responseCode'] = 2
response['message'] = _('Login successfully.')
response['lang'] = context.get('lang') or mobikul.default_lang and mobikul.default_lang.code or "en_US"
response['itemsPerPage'] = mobikul.product_limit
response['pricelist'] = mobikul.pricelist_id and mobikul.pricelist_id.id or 1
response['local'] = {
'currencySymbol':mobikul.pricelist_id and mobikul.pricelist_id.currency_id and mobikul.pricelist_id.currency_id.symbol or "",
'currencyPosition':mobikul.pricelist_id and mobikul.pricelist_id.currency_id and mobikul.pricelist_id.currency_id.position or "",
'teamId':mobikul.salesteam_id and mobikul.salesteam_id.id or False,
'salespersonId':mobikul.salesperson_id and mobikul.salesperson_id.id or False,
'lang_obj':self.env['res.lang']._lang_get(response['lang'])
}
response['addons'] = self.check_mobikul_addons()
except Exception as e:
response['responseCode'] = 3
response['message'] = _("Login Failed:")+"%r"%e.message or e.name
return response
@api.model
def _get_image_url(self, model_name, record_id, field_name, width=0, height=0, context=None):
""" Returns a local url that points to the image field of a given browse record. """
context = context or {}
if context.get('base_url',"") and not context['base_url'].endswith("/"):
context['base_url'] = context['base_url'] + "/"
if width or height:
return '%sweb/image/%s/%s/%s/%sx%s'% (context.get('base_url'), model_name, record_id, field_name, width, height)
else:
return '%sweb/image/%s/%s/%s'% (context.get('base_url'), model_name, record_id, field_name)
@api.model
def _get_cat_info(self, categ_obj, context=None):
context = context or {}
cat_data = {
"category_id":categ_obj.id,
"name":categ_obj.name or "",
"children":[],
"banner":self._get_image_url('mobikul.category',categ_obj.id,'banner', context=context),
"icon":self._get_image_url('mobikul.category',categ_obj.id,'icon', context=context),
}
return cat_data
@api.model
def _recursive_cats(self, categ_obj, context=None):
context = context or {}
data = self._get_cat_info(categ_obj, context)
if categ_obj.child_id:
for cat_child in categ_obj.child_id:
data['children'].append(self._recursive_cats(cat_child, context))
return data
@api.model
def fetch_categories(self, context=None):
context = context or {}
all_cats = []
if context.get('website_category',False):
return all_cats
else:
cat_obj = self.env['mobikul.category'].sudo()
top_cats = cat_obj.search([('parent_id','=',False)])
for top_cat in top_cats:
all_cats.append(self._recursive_cats(top_cat, context))
return all_cats
@api.model
def fetch_featured_categories(self, context=None):
context = context or {}
all_fcats = []
if context.get('website_category',False):
return all_fcats
else:
cat_obj = self.env['mobikul.category'].sudo()
f_cats = cat_obj.search([('type','=','featured')])
for f_cat in f_cats:
temp_f = {
'categoryName':f_cat.name or "",
'categoryId':f_cat.id
}
temp_f['url'] = self._get_image_url('mobikul.category',f_cat.id,'icon', context=context)
all_fcats.append(temp_f)
return all_fcats
@api.model
def fetch_product_sliders(self,context=None):
context = context or {}
allProductSliders = []
pSlider_obj = self.env['mobikul.product.slider'].sudo()
p_sliders = pSlider_obj.search([])
for p_slider in p_sliders:
products = p_slider.get_product_data(context)['products']
if not len(products):
continue
temp_s = {
'title':p_slider.name or "",
'item_display_limit':p_slider.item_display_limit,
'slider_mode':p_slider.slider_mode or "",
'product_img_position':p_slider.product_img_position or "",
'products':products,
'url':"/mobikul/sliderProducts/%d"%p_slider.id,
# 'color':p_slider.bk_color or ""
}
if p_slider.display_banner:
temp_s['backImage'] = self._get_image_url('mobikul.product.slider',p_slider.id,'banner', context=context)
allProductSliders.append(temp_s)
return allProductSliders
@api.model
def fetch_user_info(self, user_obj, context=None):
context = context or {}
temp_i = {
'customerBannerImage': self._get_image_url('res.partner',user_obj.partner_id.id,'banner_image', context=context),
'customerProfileImage': self._get_image_url('res.partner',user_obj.partner_id.id,'image', context=context),
'cartId': user_obj.partner_id.last_website_so_id and user_obj.partner_id.last_website_so_id.id or '',
# 'cartCount': user_obj.partner_id.last_website_so_id and user_obj.partner_id.last_website_so_id.cart_count or 0,
'themeCode': '?',
'customerName': user_obj.partner_id.name or "",
'customerEmail': user_obj.login or "",
'customerLang': user_obj.partner_id.lang.split('_')[0],
}
# if context.has_key('website') and context['website']:
# temp_i['cartId'] = user_obj.partner_id.last_website_so_id and user_obj.partner_id.last_website_so_id.id or ''
# temp_i['cartCount'] = user_obj.partner_id.last_website_so_id and user_obj.partner_id.last_website_so_id.cart_count or 0
# else:
# temp_i['cartId'] = user_obj.partner_id.last_mobikul_so_id and user_obj.partner_id.last_mobikul_so_id.id or ''
# temp_i['cartCount'] = user_obj.partner_id.last_mobikul_so_id and user_obj.partner_id.last_mobikul_so_id.cart_count or 0
return temp_i
@api.model
def authenticate(self, credentials, detailed = False, isSocialLogin=False, context=None):
context = context or {}
response = {'success':False, 'responseCode':0, 'message':_('Unknown Error !!!')}
user = False
if not isinstance(credentials, dict):
response['message'] = _('Data is not in Dictionary format !!!')
return response
if isSocialLogin:
if not all(k in credentials for k in ('authProvider','authUserId')):
response['message'] = _('Insufficient data to authenticate !!!')
return response
provider = self._getAuthProvider(credentials['authProvider'])
try:
user = self.env['res.users'].sudo().search([('oauth_uid', '=', credentials['authUserId']),('oauth_provider_id', '=', provider)])
if not user:
response['responseCode'] = 1
response['message'] = _("Social-Login: No such record found.")
except Exception as e:
response['responseCode'] = 3
response['message'] = _("Social-Login Failed.")
response['details'] = "%r"%e
else:
if not all(k in credentials for k in ('login','pwd')):
response['message'] = _('Insufficient data to authenticate !!!')
return response
try:
user = self.env['res.users'].sudo().search([('login', '=', credentials['login'])])
if user:
user.sudo(user.id).check_credentials(credentials['pwd'])
else:
response['responseCode'] = 1
response['message'] = _("Invalid email address.")
except Exception as e:
user = False
response['responseCode'] = 3
response['message'] = _("Login Failed.")
response['details'] = "%r"%e
if user:
try:
response['success'] = True
response['responseCode'] = 2
response['customerId'] = user.partner_id.id
response['userId'] = user.id
response['cartCount'] = user.partner_id.last_website_so_id and user.partner_id.last_website_so_id.cart_count or 0
response['message'] = _('Login successfully.')
if self.check_mobikul_addons().get('website_sale_wishlist'):
response['WishlistCount'] = len(user.partner_id.wishlist_ids)
if self.check_mobikul_addons().get('email_verification'):
response['is_email_verified'] = user.wk_token_verified
if self.check_mobikul_addons().get('odoo_marketplace'):
response['is_seller'] = user.partner_id.seller
if user.partner_id.seller:
response['seller_state'] = self.check_seller_state(user)
if detailed:
response.update(self.fetch_user_info(user, context=context))
except Exception as e:
response['responseCode'] = 3
response['message'] = _("Login Failed.")
response['details'] = "%r"%e
return response
def check_seller_state(self,user):
user_groupObj = self.env['ir.model.data'].sudo()
user_group_ids = user.groups_id.ids
xml_ids = ["marketplace_seller_group","marketplace_officer_group","marketplace_manager_group"]
mp_state = "pending"
for xml_id in xml_ids:
if user_groupObj.get_object_reference('odoo_marketplace', xml_id)[1] in user_group_ids:
mp_state = "approved"
break
return mp_state
def check_mobikul_addons(self):
result = {}
ir_model_obj = self.env['ir.module.module'].sudo()
result['website_sale_wishlist'] = ir_model_obj.search([('state', '=', 'installed'),('name', '=', 'website_sale_wishlist')]) and True or False
result['review'] = ir_model_obj.search([('state', '=', 'installed'),('name', '=', 'wk_review')]) and True or False
result['email_verification'] = ir_model_obj.search([('state', '=', 'installed'),('name', '=', 'email_verification')]) and True or False
result['odoo_marketplace'] = ir_model_obj.search([('state', '=', 'installed'),('name', '=', 'odoo_marketplace')]) and True or False
result['website_sale_delivery'] = ir_model_obj.search([('state', '=', 'installed'),('name', '=', 'website_sale_delivery')]) and True or False
return result
def email_verification_defaults(self):
return self.env['email.verification.config'].sudo().get_values()
def review_defaults(self):
return self.env['website.review.config'].sudo().get_values()
@api.model
def homePage(self, cust_data, context):
context = context or {}
response = {}
# Get base url
# if not context.has_key("base_url"):
if not 'base_url' in context:
context['base_url'] = self.env['ir.config_parameter'].get_param('web.base.url')
# Get Mobikul Conf
mobikul = self.env['mobikul'].sudo().search([], limit=1)
# Get all Categories
response['categories'] = self.fetch_categories(context=context)
# Get all Banners
response['bannerImages'] = self.fetch_banners(context=context)
# Get all Featured categories
response['featuredCategories'] = self.fetch_featured_categories(context=context)
#Get all Product Sliders
response['productSliders'] = self.fetch_product_sliders(context=context)
return response
@api.model
def fetch_banners(self, context=None):
context = context or {}
all_banners = []
MobBanners = self.env['mobikul.banners'].sudo().search_read([])
for banner in MobBanners:
temp_d = {
"bannerName": banner['name'],
"bannerType": banner['banner_action'],
"id": '',
}
if banner['banner_action']=="product":
temp_d['id'] = banner["product_id"][0]
elif banner['banner_action']=="category":
temp_d['id'] = banner["category_id"][0]
elif banner['banner_action']=="custom":
temp_d['domain'] = "[('id','in',%r)]"%banner["product_ids"]
if banner['image']:
temp_d['url'] = self._get_image_url('mobikul.banners',banner['id'],'image', context=context)
else:
temp_d['url'] = banner['url']
all_banners.append(temp_d)
# else:
# response['message'] = "No active banners found !!!"
# response['error_message'] = "Create some Banners, re-verify their publishing date."
return all_banners
@api.model
def resetPassword(self, login):
response = {'success':False}
# MobikulConfigParam = self.search_read([], limit=1)[0]
# if MobikulConfigParam['reset_password_enabled']:
try:
if login:
self.env['res.users'].sudo().reset_password(login)
response['success'] = True
response['message'] = _("An email has been sent with credentials to reset your password")
else:
response['message'] = _("No login provided.")
except Exception as e:
# response['message'] = _("There is some error occurred. Please try again after some time.")
response['message'] = _("Invalid Username/Email.")
# else:
# response['message'] = "Error: Permission not granted !!!"
return response
@api.model
def _getAuthProvider(self, provider):
if provider=="GMAIL":
google_provider = self.env.ref('auth_oauth.provider_google')
return google_provider and google_provider.id or False
elif provider=="FACEBOOK":
facebook_provider = self.env.ref('auth_oauth.provider_facebook')
return facebook_provider and facebook_provider.id or False
elif provider=="TWITTER":
twitter_provider = self.env.ref('auth_oauth.provider_twitter')
return twitter_provider and twitter_provider.id or False
return False
@api.model
def _doSignup(self, data):
template_user_id = literal_eval(self.env['ir.config_parameter'].get_param('auth_signup.template_user_id', 'False'))
template_user = self.env['res.users'].browse(template_user_id)
if not template_user.exists(): return [False, 'Invalid template user']
values = { key: data.get(key) for key in ('login', 'name') }
values['email'] = data.get('email') or values.get('login')
# values['lang'] = self.lang
values['active'] = True
no_invitation_mail = True
if data.get('isSocialLogin',False):
values['oauth_uid'] = data.get('authUserId',"")
values['oauth_access_token'] = data.get('authToken',"")
values['oauth_provider_id'] = self._getAuthProvider(data.get('authProvider',""))
values['email'] = values.get('email','provider_%s_user_%s' % (values['oauth_provider_id'], values['oauth_uid']))
values['password'] = data.get("password",values['oauth_uid'])
if self.check_mobikul_addons().get('email_verification'):
values['wk_token_verified'] = True
if not values['oauth_uid'] or not values['oauth_provider_id'] or not values['name'] or not values['email']:
return [False,"Insufficient data to authenticate."]
else:
values['password'] = data.get('password',"")
no_invitation_mail = values['password'] and True or False
if not values['name'] or not values['email']:
return [False,"Insufficient data to authenticate."]
# if not all(values.itervalues()): return [False,"The form was not properly filled in."]
# if values.get('password') != data.get('confirm_password'): return [False, "Passwords do not match; please retype them."]
try:
with self.env.cr.savepoint():
if self.check_mobikul_addons().get('odoo_marketplace') and data.get('is_seller'):
seller_msg = self.isMarketplaceSignup(template_user,values,data)
if seller_msg.get('status'):
return [True, seller_msg.get('user').id, seller_msg.get('user').partner_id.id,seller_msg.get('msg')]
else:
return [False,_("Seller profile 'url_handler' is not unique or absent.")]
else:
user = template_user.with_context(no_reset_password=no_invitation_mail).copy(values)
return [True, user.id, user.partner_id.id," "]
except Exception as e:
# copy may failed if asked login is not available.
# return [False,"Error: %r"%e]
return [False,_("There is some problem in creating account. Please try again later.")]
return [False, "Unknown Error"]
def isMarketplaceSignup(self,template_user,values,data):
if data.get('url_handler') and self.checkSellerUniqueUrl(data.get('url_handler')):
user = template_user.with_context(no_reset_password=True).copy(values)
if user:
self.set_marketplace_group_user(user)
# user.partner_id.country = "India"
user.partner_id.seller = True
user.partner_id.url_handler = data.get('url_handler')
user.partner_id.country_id = data.get('country_id')
return {'status':True,'msg':_("Seller created successfully"),'user':user}
else:
{"status": False, "msg": _("Something went wrong please try again.")}
else:
return {"status": False, "msg": _("Seller profile 'url_handler' is not unique or absent.")}
def set_marketplace_group_user(self,userObj):
user_group_id = self.env['ir.model.data'].get_object_reference('odoo_marketplace', 'marketplace_draft_seller_group')[1]
groups_obj = self.env["res.groups"].browse(user_group_id)
if groups_obj:
for group_obj in groups_obj:
group_obj.write({"users": [(4, userObj.id, 0)]})
return True
else:
return False
def checkSellerUniqueUrl(self,url):
if url:
check_url_existObj = self.env['res.partner'].sudo().search([('url_handler','=',url)],limit=1)
if len(check_url_existObj) == 0:
return True
else:
return False
else:
return False
@api.model
def signUp(self, form_data):
response = {'success':False}
# MobikulConfigParam = self.search_read([], limit=1)[0]
# if MobikulConfigParam['signup_enabled']:
try:
if form_data.get('isSocialLogin',False):
provider = self._getAuthProvider(form_data['authProvider'])
user = self.env['res.users'].sudo().search([('oauth_uid', '=', form_data['authUserId']),('oauth_provider_id', '=', provider)])
if user:
response['success'] = True
response['message'] = _("Login Successfully.")
response['userId'] = user.id
response['customerId'] = user.partner_id.id
return response
if 'login' in form_data:
if self.env['res.users'].sudo().search([("login", "=",form_data['login'])]):
# response['message'] = _("Another user is already registered using this email address.")
response['message'] = _("This mail is already registered with us. ")
else:
result = self._doSignup(form_data)
if result[0]:
response['success'] = True
# response['message'] = "An invitation has been sent to mentioned email, please accept it and set your password to complete the registration process."
# response['message'] = "A validation e-mail has been sent to your e-mail address."
response['message'] = _("Created Successfully.")
response['userId'] = result[1]
response['customerId'] = result[2]
response['seller_message'] =result[3]
else:
response['message'] = _("Could not create a new account: ")+"%s"%result[1]
else:
response['message'] = _("No login provided.")
except Exception as e:
response['message'] = _("Could not create a new account.:")+" %r"%e.message or e.name
# else:
# response['message'] = "Error: Permission not granted !!!"
return response
@api.model
def getDefaultData(self):
IrConfigParam = self.env['ir.config_parameter']
temp = {}
temp['allow_resetPwd'] = literal_eval(IrConfigParam.get_param('auth_signup.reset_password', 'False'))
temp['allow_signup'] = literal_eval(IrConfigParam.get_param('auth_signup.allow_uninvited', 'False'))
temp['allow_guestCheckout'] = literal_eval(IrConfigParam.get_param('mobikul.allow_guest', 'False'))
temp['allow_gmailSign'] = literal_eval(IrConfigParam.get_param('mobikul.gmail_signin', 'False'))
temp['allow_facebookSign'] = literal_eval(IrConfigParam.get_param('mobikul.facebook_signin', 'False'))
temp['allow_twitterSign'] = literal_eval(IrConfigParam.get_param('mobikul.twitter_signin', 'False'))
data = self.check_mobikul_addons()
#temp['allow_module_website_wishlist'] = data.get("wishlist")
temp['allowShipping'] = data.get("website_sale_delivery")
return temp
def _default_order_mail_template(self):
return self.env.ref('sale.email_template_edi_sale').id
def fetch_products(self, **kwargs):
"""
Extra Parameters: domain, limit, fields, offset, order
"""
domain = _get_product_domain()
result = {'offset':kwargs.get('offset',0)}
try:
if 'domain' in kwargs:
domain += literal_eval(kwargs['domain'])
except:
pass
if 'search' in kwargs:
for s in kwargs['search'].split(" "):
domain += [('name', 'ilike', s)]
if 'cid' in kwargs:
domain += [('mobikul_categ_ids', 'child_of', int(kwargs['cid']))]
ProductObj = self.env['product.template'].sudo()
result['tcount'] = ProductObj.search_count(domain)
product_data = ProductObj.search_read(domain, limit=kwargs.get('limit',5), offset=result["offset"], order=kwargs.get('order',0), fields=_get_product_fields())
result['products'] = _getProductData(product_data, kwargs.get('base_url', self._get_base_url()), kwargs.get('currencySymbol'), kwargs.get('currencyPosition'), kwargs.get('lang_obj'))
return result
def _get_base_url(self):
return self.env['ir.config_parameter'].get_param('web.base.url')
def _default_language(self):
lc = self.env['ir.default'].get('res.partner', 'lang')
dl = self.env['res.lang'].search([('code', '=', lc)], limit=1)
return dl.id if dl else self.env['res.lang'].search([]).ids[0]
def _active_languages(self):
return self.env['res.lang'].search([]).ids
def add_to_cart(self,partner,product_id,set_qty,add_qty,response):
PartnerObj = self.env['res.partner'].sudo()
Partner = PartnerObj.browse(partner)
if Partner:
Product = self.env['product.product'].sudo().search([('id','=',product_id)])
if Product:
last_order = Partner.last_website_so_id
if last_order:
flag = 0
for line in last_order.order_line:
if line.product_id == Product:
if set_qty:
line.product_uom_qty = set_qty
line.product_uom_change()
line._onchange_discount()
flag = 1
elif add_qty:
line.product_uom_qty+=int(add_qty)
line.product_uom_change()
line._onchange_discount()
flag = 1
else:
flag = -1
result = {'message':'Insufficient data.', 'success':False}
if not flag:
#Create order line
self._create_so_line(last_order, Product, int(add_qty))
flag = True
if flag==1:
result = {'message':'Added Successfully.','productName':Product.display_name, 'success':True}
result['cartCount'] = last_order.cart_count
return result
else:
#create Order
local = response.get('local',{})
res = self._create_so(Partner, local)
self._create_so_line(res['order'], Product, int(add_qty))
result = {'message':'Added Successfully.','cartCount':res['order'].cart_count,'productName':Product.display_name, 'success':True}
return result
else:
result = {'success':False, 'message':'Insufficient data.'}
return result
else:
result = {'success':False, 'message':'Account not found !!!'}
return result
def sellerDashboardData(self,seller_Obj):
prdObj = self.env['product.template'].sudo()
SaleOrderLine = self.env['sale.order.line'].sudo()
approved_count = prdObj.search_count([('marketplace_seller_id', '=', seller_Obj.id), ('status', '=', 'approved')])
pending_count = prdObj.search_count([('marketplace_seller_id', '=', seller_Obj.id), ('status', '=', 'pending')])
rejected_count = prdObj.search_count([('marketplace_seller_id', '=', seller_Obj.id), ('status', '=', 'rejected')])
new_sol_count = SaleOrderLine.search_count([('marketplace_seller_id', '=', seller_Obj.id), ('marketplace_state', '=', 'new')])
approved_sol_count = SaleOrderLine.search_count([('marketplace_seller_id', '=', seller_Obj.id), ('marketplace_state', '=', 'approved')])
shipped_sol_count = SaleOrderLine.search_count([('marketplace_seller_id', '=', seller_Obj.id), ('marketplace_state', '=', 'shipped')])
temp = {
"approved_productCount":approved_count,
"pending_productCount":pending_count,
"rejected_productCount":rejected_count,
"new_solCount":new_sol_count,
"approved_solCount":approved_sol_count,
"shipped_solCount":shipped_sol_count,
"total":{
"label":"Total Amount",
"value":seller_Obj.total_mp_payment
},
"balance":{
"label": "Balance Amount",
"value":seller_Obj.balance_mp_payment
},
}
return temp
def easy_date(self,time=False):
"""
Get a datetime object or a timestamp and return a
easy read string like 'Just now', 'Yesterday', '3 months ago',
'Year ago'.
"""
now = datetime.now()
if type(time) is str:
time = fields.Datetime.from_string(time)
if type(time) is int:
diff = now - datetime.fromtimestamp(time)
elif isinstance(time,datetime):
diff = now - time
elif not time:
diff = now - now
second_diff = diff.seconds
day_diff = diff.days
if day_diff < 0:
return ''
if day_diff == 0:
if second_diff < 10:
return "just now"
if second_diff < 60:
return str(second_diff) + " seconds ago"
if second_diff < 120:
return "a minute ago"
if second_diff < 3600:
return str(second_diff / 60) + " minutes ago"
if second_diff < 7200:
return "an hour ago"
if second_diff < 86400:
return str(second_diff / 3600) + " hours ago"
if day_diff == 1:
return "Yesterday"
if day_diff < 7:
return str(day_diff) + " days ago"
if day_diff < 31:
return str(day_diff / 7) + " weeks ago"
if day_diff < 365:
return str(day_diff / 30) + " months ago"
return str(day_diff / 365) + " years ago"
def _getdefaultWebsite_id(self):
website_id = self.env['website'].search([], limit=1)
return website_id.id
name = fields.Char('Mobikul App Title', default="Mobikul App", required=1)
salesperson_id = fields.Many2one('res.users', string='Default Salesperson')
salesteam_id = fields.Many2one('crm.team', string='Default Sales Team')
api_key = fields.Char(string='API Secret key', default="dummySecretKey", required=1)
fcm_api_key = fields.Char(string='FCM Api key')
color_scheme = fields.Selection([
('default', 'Default'),
('red-green', 'Red-Green'),
('light-green', 'Light Green'),
('deep-purple-pink', 'Deep Purple-Pink'),
('blue-orange', 'Blue Orange'),
('light-blue-red', 'Light Blue-Red')],
string='Color Scheme', required=True,
default='default',
help="Color Options for your Mobikul App.")
email_verify = fields.Boolean(default=True, string='Verify Email on signUp', help="A verification email will send to the user after signup to cross-check user`s identity.")
default_lang = fields.Many2one('res.lang', string='Default Language', default=_default_language,
help="If the selected language is loaded in the mobikul, all documents related to "
"this contact will be printed in this language. If not, it will be English.")
language_ids = fields.Many2many('res.lang', 'mobikul_lang_rel', 'mobikul_id', 'lang_id', 'Languages', default=_active_languages)
pricelist_id = fields.Many2one('product.pricelist', string='Default Pricelist')
currency_id = fields.Many2one('res.currency', related='pricelist_id.currency_id', string='Default Currency', readonly=True)
order_mail_template = fields.Many2one('mail.template', string='Confirmation Email', readonly=True, default=_default_order_mail_template, help="Email sent to customer at the end of the checkout process")
product_limit = fields.Integer(default=10, string='Limit Products per page', help='Used in Pagination', required=1)
website_id = fields.Many2one('website', default=_getdefaultWebsite_id,help="select website id for the app")
@api.multi
def unlink(self):
raise UserError(_('You cannot remove/deactivate this Configuration.'))
class MobikulBanners(models.Model):
_name = 'mobikul.banners'
_description = 'Mobikul Banner Class'
_order = "sequence, name"
name = fields.Char('Title', required=True, translate=True)
active = fields.Boolean(default=True)
description = fields.Text('Description', translate=True)
image = fields.Binary('Image', attachment=True)
banner_action = fields.Selection([
('product', 'Open Product Page'),
('category', 'Open Category Page'),
('custom', 'Open Custom Collection Page'),
('none', 'Do nothing')],
string='Action to be triggered', required=True,
default='none',
help="Define what action will be triggerred when click/touch on the banner.")
product_id = fields.Many2one('product.template', string='Choose Product')
category_id = fields.Many2one('mobikul.category', string='Choose Category')
product_ids = fields.Many2many('product.template', string='Choose Products')
url = fields.Char('Image URL', help="Static URL of Banner Image, used when banner`s image is not present.")
date_published = fields.Datetime('Publish Date')
date_expired = fields.Datetime('Expiration Date')
sequence = fields.Integer(default=10, help='Display order')
total_views = fields.Integer('Total # Views', default=0, readonly=1)
@api.model
def create(self, values):
if not values.get('image') and not values.get('url'):
raise UserError(_('Please upload Banner`s Image or enter Image URL'))
if not values.get('date_published'):
values['date_published'] = datetime.now()
return super(MobikulBanners, self).create(values)
# crone for auto inactive expire banners
@api.model
def process_inactive_mobikul_banner(self):
banner = self.sudo().search([])
inactive_MobBanners = []
for b in banner:
if b.date_expired:
if fields.Date.from_string(fields.Datetime.now()) > fields.Date.from_string(b.date_expired):
inactive_MobBanners.append(b)
for i in inactive_MobBanners:
i.active = False
# method to check expire banners
@api.model
def remove_expireBanners(self):
banner = self.sudo().search([])
MobBanners = []
for b in banner:
if b.date_expired:
if fields.Date.from_string(fields.Datetime.now()) <= fields.Date.from_string(b.date_expired):
MobBanners.append(b)
else:
MobBanners.append(b)
return MobBanners
class MobikulCategory(models.Model):
_name = 'mobikul.category'
_description = 'Mobikul Category'
_order = "sequence, name"
name = fields.Char(required=True, translate=True)
active = fields.Boolean(default=True)
parent_id = fields.Many2one('mobikul.category', string='Parent Category', index=True)
child_id = fields.One2many('mobikul.category', 'parent_id', string='Children Categories')
banner = fields.Binary('Banner', attachment=True)
icon = fields.Binary('Icon', attachment=True)
sequence = fields.Integer(default=10, help='Display order')
complete_name = fields.Char(
'Complete Name', compute='_compute_complete_name',
store=True)
type = fields.Selection([
('featured', 'Featured Category'),
('normal', 'Normal')], 'Category Type', default='normal',
help="A Featured category is a category that can be used ...")
#this field is added for mobikul category merge
website_cat_id = fields.Many2one('product.public.category', 'Webiste Category')
@api.depends('name', 'parent_id.complete_name')
def _compute_complete_name(self):
for category in self:
if category.parent_id:
category.complete_name = '%s / %s' % (category.parent_id.complete_name, category.name)
else:
category.complete_name = category.name
@api.constrains('parent_id')
def check_parent_id(self):
if not self._check_recursion():
raise ValueError(_('Error ! You cannot create recursive categories.'))
@api.multi
def name_get(self):
res = []
for category in self:
names = [category.name]
parent_category = category.parent_id
while parent_category:
names.append(parent_category.name)
parent_category = parent_category.parent_id
res.append((category.id, ' / '.join(reversed(names))))
return res
# method call from server action
@api.model
def sync_category(self):
action = self.env.ref('mobikul.mobikul_sync_cat_action').read()[0]
action['views'] = [(self.env.ref('mobikul.mobikul_sync_cat_form').id, 'form')]
action['context'] = self._context
return action
# def _compute_products(self):
# read_group_res = self.env['product.template'].read_group([('categ_id', 'in', self.ids)], ['categ_id'], ['categ_id'])
# group_data = dict((data['categ_id'][0], data['categ_id_count']) for data in read_group_res)
# for categ in self:
# categ.product_count = group_data.get(categ.id, 0)
class MobikulSyncCategory(models.Model):
_name = "mobikul.sync.category"
sync_type = fields.Selection([
('name', 'Only Name'),
('name_seq', 'Name and Sequence'),
('name_parent', 'Name and Parent Category'),
('name_parent_seq', 'Name, Parent Category and Sequence'), ], 'Sync Type', default='name_parent_seq',
help="Sync mobikul category on the basis of Selection")
def show_msg_wizard(self, msg):
partial_id = self.env['wk.wizard.message'].create({'text': msg})
return {
'name': "Message",
'view_mode': 'form',
'view_id': False,
'view_type': 'form',
'res_model': 'wk.wizard.message',
'res_id': partial_id.id,
'type': 'ir.actions.act_window',
'nodestroy': True,
'target': 'new',
}
@api.multi
def sync_mobikul_cat_with_web_cat(self):
isCatMerge = self.env['ir.module.module'].sudo().search(
[('state', '=', 'installed'), ('name', '=', 'mobikul_cat_merge')]) and True or False
if isCatMerge:
mobikul_catg_ids = self.env['mobikul.category'].search([("id","in",self._context.get('active_ids'))])
if not self.sync_type:
raise UserError(_("Please select the Sync Type."))
for mob_cat in mobikul_catg_ids:
if mob_cat.website_cat_id.id:
if self.sync_type == "name":
mob_cat.name = mob_cat.website_cat_id.name
elif self.sync_type == "name_parent":
mob_cat.name = mob_cat.website_cat_id.name
mob_cat.parent_id = mob_cat.website_cat_id.parent_id.mobikul_cat_id.id
elif self.sync_type == "name_parent_seq":
mob_cat.name = mob_cat.website_cat_id.name
mob_cat.parent_id = mob_cat.website_cat_id.parent_id.mobikul_cat_id.id
mob_cat.sequence = mob_cat.website_cat_id.sequence
elif self.sync_type == "name_seq":
mob_cat.name = mob_cat.website_cat_id.name
mob_cat.sequence = mob_cat.website_cat_id.sequence
else:
_logger.info("MESAGE :Website category is not present in Mobikul Caegory")
if self.sync_type == "name":
message = "Done! name are synced with mobikul category from Website category."
elif self.sync_type == "name_seq":
message = "Done! name and sequence are synced with mobikul category from Website category."
elif self.sync_type == "name_parent":
message = "Done! name and parent category are synced with mobikul categories from Website category."
elif self.sync_type == "name_parent_seq":
message = "Done! name, sequence and parent category are synced with mobikul categories from Website category."
else:
message = "Install the Mobikul Category Merge Module First"
return self.show_msg_wizard(message)
class MobikulPushNotificationTemplate(models.Model):
_name = 'mobikul.push.notification.template'
_description = 'Mobikul Push Notification Templates'
_order = "name"
def _addMe(self, data):
self.env["mobikul.notification.messages"].sudo().create(data)
return True
def _get_key(self):
mobikul = self.env['mobikul'].sudo().search([], limit=1)
return mobikul and mobikul.fcm_api_key or ""
@api.model
def _pushMe(self,key, payload_data, data=False):
status = True
summary = ""
try:
push_service = FCMAPI(api_key=key)
summary = push_service.send([payload_data])
if data:
self._addMe(data)
except Exception as e:
status = False
summary = "Error: %r"%e
return [status,summary]
@api.model
def _send(self, to_data, customer_id=False, max_limit=20):
"""
to_data = dict(to or registration_ids)
"""
if type(to_data)!=dict:
return False
if not to_data.get("to",False) and not to_data.get("registration_ids",False):
if not customer_id:
return False
reg_data = self.env['fcm.registered.devices'].sudo().search_read([('customer_id','=',customer_id)],limit=max_limit, fields=['token'])
if not reg_data:
return False
to_data = {
"registration_ids":[r['token'] for r in reg_data]
}
notification = dict(title=self.notification_title, body=self.notification_body)
if self.notification_color:
notification['color'] = self.notification_color
if self.notification_tag:
notification['tag'] = self.notification_tag
fcm_payload = dict(notification=notification)
fcm_payload.update(to_data)
data_message = dict(type="",id="",domain="",image="",name="")
if self.banner_action == 'product':
data_message['type'] = 'product'
data_message['id'] = self.product_id.id
data_message['name'] = self.product_id.name
elif self.banner_action == 'category':
data_message['type'] = 'category'
data_message['id'] = self.category_id.id
data_message['name'] = self.category_id.name
elif self.banner_action == 'custom':
data_message['type'] = 'custom'
data_message['domain'] = "[('id','in',%s)]"%self.product_ids.ids
data_message['name'] = self.notification_title
else:
data_message['type'] = 'none'
data_message['image'] = _get_image_url(self._context.get('base_url'), 'mobikul.push.notification.template', self.id,'image')
data_message['notificationId'] = random.randint(1, 99999)
fcm_payload['data'] = data_message
if customer_id:
data = dict(
title=self.notification_title, body=self.notification_body, customer_id=customer_id,
banner=self.image, datatype='default'
)
return self._pushMe(self._get_key(), json.dumps(fcm_payload).encode('utf8'), customer_id and data or False)
name = fields.Char('Name', required=True, translate=True)
notification_color = fields.Char('Color',default='PURPLE')
notification_tag = fields.Char('Tag')
notification_title = fields.Char('Title', required=True, translate=True)
active = fields.Boolean(default=True, copy=False)
notification_body = fields.Text('Body', translate=True)
image = fields.Binary('Image', attachment=True)
banner_action = fields.Selection([
('product', 'Open Product Page'),
('category', 'Open Category Page'),
('custom', 'Open Custom Collection Page'),
('none', 'Do nothing')],
string='Action', required=True,
default='none',
help="Define what action will be triggerred when click/touch on the banner.")
product_id = fields.Many2one('product.template', string='Choose Product')
product_ids = fields.Many2many('product.template', string='Choose Products')
category_id = fields.Many2one('mobikul.category', string='Choose Category')
device_id = fields.Many2one('fcm.registered.devices', string='Select Device')
total_views = fields.Integer('Total # Views', default=0, readonly=1, copy=False)
condition = fields.Selection([
('signup', 'Customer`s SignUp'),
('orderplaced',"Order Placed")
], string='Condition', required=True, default='signup')
@api.multi
def dry_run(self):
self.ensure_one()
to_data = dict(to=self.device_id and self.device_id.token or "")
result = self._send(to_data, self.device_id and self.device_id.customer_id and self.device_id.customer_id.id or False)
# raise UserError('Result: %r'%result)
@api.multi
def copy(self, default=None):
self.ensure_one()
default = dict(default or {}, name=_('%s(copy)') % self.name)
return super(MobikulPushNotificationTemplate, self).copy(default)
class MobikulPushNotification(models.Model):
_name = 'mobikul.push.notification'
_description = 'Mobikul Push Notification'
_order = "activation_date, name"
_inherit = ['mobikul.push.notification.template']
@api.model
def parse_n_push(self, max_limit=20, registration_ids=None):
to_data = dict()
if self.notification_type == 'token-auto':
reg_data = self.env['fcm.registered.devices'].sudo().search_read(limit=max_limit, fields=['token'])
registration_ids = [r['token'] for r in reg_data]
elif self.notification_type == 'token-manual':
registration_ids = [d.token for d in self.device_ids]
elif self.notification_type == 'topic':
to_data['to'] = '/topics/%s' % self.topic_id.name
else:
return [False,"Insufficient Data"]
if registration_ids:
if len(registration_ids) > 1:
to_data['registration_ids'] = registration_ids
else:
to_data['to'] = registration_ids[0]
return self._send(to_data)
summary = fields.Text('Summary', readonly=True)
activation_date = fields.Datetime('Activation Date', copy=False)
notification_type = fields.Selection([
('token-auto', 'Token-Based(All Reg. Devices)'),
('token-manual', 'Token-Based(Selected Devices)'),
('topic', 'Topic-Based'),
],
string='Type', required=True,
default='token-auto')
topic_id = fields.Many2one('fcm.registered.topics', string='Choose Topic')
device_ids = fields.Many2many('fcm.registered.devices', string='Choose Devices/Customers')
state = fields.Selection([
('draft', 'Draft'),
('confirm', 'Confirm'),
('hold', 'Hold'),
('error', 'Error'),
('done', 'Done'),
('cancel', 'Cancelled'),
], string='Status', readonly=True, copy=False, index=True, track_visibility='onchange', default='draft')
@api.multi
def action_cancel(self):
for record in self:
record.state = 'cancel'
return True
@api.multi
def action_confirm(self):
for record in self:
record.state = 'confirm'
return True
@api.multi
def action_draft(self):
for record in self:
record.state = 'draft'
return True
@api.multi
def action_hold(self):
for record in self:
record.state = 'hold'
return True
@api.multi
def push_now(self):
for record in self:
response = record.parse_n_push()
record.state = response[0] and 'done' or 'error'
record.summary = response[1]
return True
@api.multi
def duplicate_me(self):
self.ensure_one()
action = self.env.ref('mobikul.mobikul_push_notification_action').read()[0]
action['views'] = [(self.env.ref('mobikul.mobikul_push_notification_view_form').id, 'form')]
action['res_id'] = self.copy().id
return action
class MobikulProductSlider(models.Model):
_name = 'mobikul.product.slider'
_description = 'Mobikul Product Slider'
_order = "sequence"
@api.multi
def _products_count(self):
r = {}
for slider in self:
slider.product_count = r.get(slider.id, len(slider.get_product_data({'count':True})))
return r
@api.multi
def action_view_products(self):
products = self.get_product_data({'count':True})
action = self.env.ref('mobikul.mobikul_product_template_action').read()[0]
action['domain'] = [('id', 'in', products)]
return action
@api.multi
def get_product_data(self,context=None):
context=context or {}
if not 'base_url' in context:
context['base_url'] = self.env['ir.config_parameter'].get_param('web.base.url')
orderBy = context.get('order',None)
mlimit = context.get('limit',self.item_limit)
moffset = context.get('offset',0)
prod_obj = self.env['product.template'].sudo()
product_filter = _get_product_domain()
if self.product_selection == "manual":
product_filter.append(('id','in',self.product_ids._ids))
elif self.product_based_on == 'new':
orderBy = 'id desc'
elif self.product_based_on == 'iCategory':
product_filter.append(('categ_id','=',self.icategory_id and self.icategory_id.id or False))
elif self.product_based_on == 'wCategory':
product_filter.append(('public_categ_ids','=',self.wcategory_id and self.wcategory_id.id or False))
elif self.product_based_on == 'mCategory':
product_filter.append(('mobikul_categ_ids','=',self.mcategory_id and self.mcategory_id.id or False))
all_prods = prod_obj.search(product_filter, order=orderBy)
if 'count' in context:
return all_prods._ids
else:
product_data = prod_obj.search_read(product_filter, limit=mlimit, fields=_get_product_fields(), offset=moffset, order=orderBy)
result = {'tcount':len(all_prods),'offset':moffset}
result['products'] = _getProductData(product_data, context.get('base_url'), context.get('currencySymbol'), context.get('currencyPosition'), context.get('lang_obj'))
return result
name = fields.Char('Slider Title', required=True, translate=True)
active = fields.Boolean(default=True)
sequence = fields.Integer(default=10, help='Display order', required=True)
description = fields.Text('Description', translate=True)
display_banner = fields.Boolean('Display Banner', default=False)
banner = fields.Binary('Banner', attachment=True)
url = fields.Char('Link URL', help="Used when someone click on banner/view-all button.")
product_ids = fields.Many2many('product.template', string='Choose Products')
total_views = fields.Integer('Total # Views', default=0, readonly=1)
item_limit = fields.Integer('Maximum no. of products in a slider', default=5, required=True)
item_display_limit = fields.Integer('Display no. of Products in a slider(per row)', default=5, required=True)
product_img_position = fields.Selection([
('center', 'Center'),
('left', 'Left'),
('right', 'Right'),
],
string='Product Image Position', required=True,
default='center')
slider_mode = fields.Selection([
('default', 'Default(Slide)'),
('fixed', 'Fixed'),
],
string='Slider Mode', required=True,
default='default',
help="Define which type of behaviour you want with your Slider.")
product_selection = fields.Selection([
('manual', 'Manual'),
('automatic', 'Automatic'),
],
string='Selection Criteria', required=True, default='automatic')
product_based_on = fields.Selection([
('new', 'Newly created'),
('iCategory', 'Internal Category'),
('mCategory', 'Mobikul Category'),
('wCategory', 'Website Category'),
],
string='Based on', default='new')
mcategory_id = fields.Many2one('mobikul.category', string='Mobikul Category')
wcategory_id = fields.Many2one('product.public.category', string='Website Category')
icategory_id = fields.Many2one('product.category', string='Internal Category')
product_count = fields.Integer(compute='_products_count', string='# Products')
bk_color = fields.Char('Background Color')
class FcmRegisteredDevices(models.Model):
_name = 'fcm.registered.devices'
_description = 'All Registered Devices on FCM for Push Notifications.'
_order = 'write_date desc'
@api.multi
def name_get(self):
res = []
for record in self:
name = record.customer_id and record.customer_id.name or ''
res.append((record.id, "%s(DeviceId:%s)"%(name,record.device_id)))
return res
name = fields.Char('Name')
token = fields.Text('FCM Registration ID', readonly=True)
device_id = fields.Char('Device Id', readonly=True)
customer_id = fields.Many2one('res.partner', string="Customer", readonly=True, index=True)
active = fields.Boolean(default=True, readonly=True)
# write_date = fields.Datetime(string='Last Update', readonly=True, help="Date on which this entry is created.")
description = fields.Text('Description', readonly=True)
class FcmRegisteredTopics(models.Model):
_name = 'fcm.registered.topics'
_description = 'All Registered Topics for Push Notifications.'
name = fields.Char('Topic Name', required=True)
class MobikulNotificationMessages(models.Model):
_name = 'mobikul.notification.messages'
_description = 'Mobikul Notification Messages'
name = fields.Char('Message Name')
title = fields.Char('Title')
subtitle = fields.Char('Subtitle')
body = fields.Text('Body')
icon = fields.Binary('Icon')
banner = fields.Binary('Banner')
is_read = fields.Boolean('Is Read',default=False, readonly=True)
customer_id = fields.Many2one('res.partner', string="Customer", index=True)
active = fields.Boolean(default=True, readonly=True)
period = fields.Char('Period',compute='_compute_period')
datatype = fields.Selection([
('default', 'Default'),
('order','Order')],
string='Data Type', required=True,
default='default',
help="Notification Messages Data Type for your Mobikul App.")
def _compute_period(self):
for i in self:
i.period = self.env['mobikul'].easy_date(i.create_date)