You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
425 lines
17 KiB
425 lines
17 KiB
# -*- coding: utf-8 -*-
|
|
#############################################################################
|
|
#
|
|
# Cybrosys Technologies Pvt. Ltd.
|
|
#
|
|
# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
|
|
# Author: Milind Mohan @ Cybrosys, (odoo@cybrosys.com)
|
|
# Mohammed Shahil M P @ Cybrosys, (odoo@cybrosys.com)
|
|
# You can modify it under the terms of the GNU AFFERO
|
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
|
|
#
|
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
|
|
# (AGPL v3) along with this program.
|
|
# If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
#############################################################################
|
|
#############################################################################
|
|
from datetime import datetime
|
|
from odoo import models, fields, api, _
|
|
from odoo.exceptions import UserError
|
|
import pytz
|
|
|
|
|
|
class MobileServiceShop(models.Model):
|
|
_name = 'mobile.service'
|
|
_rec_name = 'name'
|
|
_description = "Mobile Service"
|
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
|
|
|
name = fields.Char(string='Service Number', copy=False, default="New")
|
|
person_name = fields.Many2one('res.partner', string="Customer Name",
|
|
required=True)
|
|
contact_no = fields.Char(related='person_name.mobile',
|
|
string="Contact Number")
|
|
email_id = fields.Char(related='person_name.email', string="Email")
|
|
|
|
street = fields.Char(related='person_name.street', string="Address")
|
|
street2 = fields.Char(related='person_name.street2', string="Address")
|
|
city = fields.Char(related='person_name.city', string="Address")
|
|
state_id = fields.Many2one(related='person_name.state_id', string="Address")
|
|
zip = fields.Char(related='person_name.zip', string="Address")
|
|
country_id = fields.Many2one(related='person_name.country_id',
|
|
string="Address")
|
|
|
|
brand_name = fields.Many2one('mobile.brand', string="Mobile Brand")
|
|
is_in_warranty = fields.Boolean(
|
|
'In Warranty', default=False,
|
|
help="Specify if the product is in warranty.")
|
|
|
|
warranty_number = fields.Char(string="Warranty No ",
|
|
help="warranty details")
|
|
|
|
re_repair = fields.Boolean(
|
|
'Re-repair', default=False,
|
|
help="Re-repairing.")
|
|
|
|
imei_no = fields.Char(string="IMEI Number")
|
|
|
|
model_name = fields.Many2one('brand.model', string="Model",
|
|
domain="[('mobile_brand_name','=',brand_name)]")
|
|
image_medium = fields.Binary(related='model_name.image_medium', store=True,
|
|
attachment=True)
|
|
date_request = fields.Date(string="Requested date",
|
|
default=fields.Date.context_today)
|
|
return_date = fields.Date(string="Return date", required=True)
|
|
technician_name = fields.Many2one('res.users', string="Technician Name",
|
|
default=lambda self: self.env.user,
|
|
required=True)
|
|
service_state = fields.Selection(
|
|
[('draft', 'Draft'), ('assigned', 'Assigned'),
|
|
('completed', 'Completed'), ('returned', 'Returned'),
|
|
('not_solved', 'Not solved')],
|
|
string='Service Status', default='draft', track_visibility='always')
|
|
|
|
complaints_tree = fields.One2many('mobile.complaint.tree', 'complaint_id',
|
|
string='Complaints Tree')
|
|
|
|
product_order_line = fields.One2many('product.order.line',
|
|
'product_order_id',
|
|
string='Parts Order Lines')
|
|
|
|
internal_notes = fields.Text(string="Internal notes")
|
|
invoice_count = fields.Integer(compute='_invoice_count', string='# Invoice',
|
|
copy=False)
|
|
invoice_ids = fields.Many2many("account.move", string='Invoices',
|
|
compute="_get_invoiced", readonly=True,
|
|
copy=False)
|
|
|
|
first_payment_inv = fields.Many2one('account.move', copy=False)
|
|
|
|
first_invoice_created = fields.Boolean(string="First Invoice Created",
|
|
invisible=True, copy=False)
|
|
|
|
journal_type = fields.Many2one('account.journal', 'Journal', invisible=True,
|
|
default=lambda self: self.env[
|
|
'account.journal'].search(
|
|
[('code', '=', 'SERV')]))
|
|
|
|
company_id = fields.Many2one('res.company', 'Company',
|
|
default=lambda self: self.env[
|
|
'res.company']._company_default_get(
|
|
'mobile.service'))
|
|
|
|
@api.model
|
|
def _default_picking_transfer(self):
|
|
"""To get the default picking transfers"""
|
|
type_obj = self.env['stock.picking.type']
|
|
company_id = self.env.context.get(
|
|
'company_id') or self.env.user.company_id.id
|
|
types = type_obj.search([('code', '=', 'outgoing'),
|
|
('warehouse_id.company_id', '=', company_id)],
|
|
limit=1)
|
|
if not types:
|
|
types = type_obj.search(
|
|
[('code', '=', 'outgoing'), ('warehouse_id', '=', False)])
|
|
return types[:4]
|
|
|
|
stock_picking_id = fields.Many2one('stock.picking', string="Picking Id")
|
|
|
|
picking_transfer_id = fields.Many2one('stock.picking.type', 'Deliver To',
|
|
required=True,
|
|
default=_default_picking_transfer,
|
|
help="This will determine picking type of outgoing shipment")
|
|
|
|
picking_count = fields.Integer()
|
|
|
|
@api.onchange('return_date')
|
|
def check_date(self):
|
|
"""Check the return date and request date"""
|
|
if self.return_date != False:
|
|
return_date_string = datetime.strptime(str(self.return_date),
|
|
"%Y-%m-%d")
|
|
request_date_string = datetime.strptime(str(self.date_request),
|
|
"%Y-%m-%d")
|
|
if return_date_string < request_date_string:
|
|
raise UserError(
|
|
"Return date should be greater than requested date")
|
|
|
|
def approve(self):
|
|
"""assigning the Service Request to the corresponding user"""
|
|
self.service_state = 'assigned'
|
|
|
|
def complete(self):
|
|
"""Mark the service request as completed"""
|
|
self.service_state = 'completed'
|
|
|
|
def return_to(self):
|
|
"""The service request is returned to the client"""
|
|
self.service_state = 'returned'
|
|
|
|
def not_solved(self):
|
|
"""Mark the service request as not solved"""
|
|
self.service_state = 'not_solved'
|
|
|
|
def action_send_mail(self):
|
|
'''
|
|
This function opens a window to compose an email, with the edi sale template message loaded by default
|
|
'''
|
|
self.ensure_one()
|
|
ir_model_data = self.env['ir.model.data']
|
|
try:
|
|
template_id = ir_model_data._xmlid_lookup(
|
|
'mobile_service_shop.email_template_mobile_service')[2]
|
|
except ValueError:
|
|
template_id = False
|
|
try:
|
|
compose_form_id = ir_model_data._xmlid_lookup(
|
|
'mail.email_compose_message_wizard_form')[2]
|
|
except ValueError:
|
|
compose_form_id = False
|
|
ctx = {
|
|
'default_model': 'mobile.service',
|
|
'default_res_id': self.ids[0],
|
|
'default_use_template': bool(template_id),
|
|
'default_template_id': template_id,
|
|
'default_composition_mode': 'comment',
|
|
}
|
|
return {
|
|
'name': _('Compose Email'),
|
|
'type': 'ir.actions.act_window',
|
|
'view_mode': 'form',
|
|
'res_model': 'mail.compose.message',
|
|
'views': [(compose_form_id, 'form')],
|
|
'view_id': compose_form_id,
|
|
'target': 'new',
|
|
'context': ctx,
|
|
}
|
|
|
|
def return_advance(self):
|
|
inv_obj = self.env['account.move'].search(
|
|
[('invoice_origin', '=', self.name)])
|
|
inv_ids = []
|
|
for each in inv_obj:
|
|
inv_ids.append(each.id)
|
|
view_id = self.env.ref('account.view_move_form').id
|
|
|
|
if inv_ids:
|
|
if len(inv_ids) <= 1:
|
|
value = {
|
|
'view_mode': 'form',
|
|
'res_model': 'account.move',
|
|
'view_id': view_id,
|
|
'type': 'ir.actions.act_window',
|
|
'name': 'Invoice',
|
|
'res_id': inv_ids[0]
|
|
}
|
|
else:
|
|
value = {
|
|
'domain': str([('id', 'in', inv_ids)]),
|
|
'view_mode': 'tree,form',
|
|
'res_model': 'account.move',
|
|
'view_id': False,
|
|
'type': 'ir.actions.act_window',
|
|
'name': 'Invoice',
|
|
'res_id': inv_ids[0]
|
|
}
|
|
|
|
return value
|
|
else:
|
|
raise UserError("No invoice created")
|
|
|
|
def _invoice_count(self):
|
|
"""Calculating the number of invoices"""
|
|
invoice_ids = self.env['account.move'].search(
|
|
[('invoice_origin', '=', self.name)])
|
|
self.invoice_count = len(invoice_ids)
|
|
|
|
@api.model
|
|
def create(self, vals):
|
|
"""Creating sequence"""
|
|
if 'company_id' in vals:
|
|
vals['name'] = self.env['ir.sequence'].with_context(
|
|
force_company=self.env.user.company_id.id).next_by_code(
|
|
'mobile.service') or _('New')
|
|
else:
|
|
vals['name'] = self.env['ir.sequence'].next_by_code(
|
|
'mobile.service') or _('New')
|
|
vals['service_state'] = 'draft'
|
|
return super(MobileServiceShop, self).create(vals)
|
|
|
|
def unlink(self):
|
|
"""Supering the unlink function"""
|
|
for i in self:
|
|
if i.service_state != 'draft':
|
|
raise UserError(
|
|
_('You cannot delete an assigned service request'))
|
|
return super(MobileServiceShop, self).unlink()
|
|
|
|
def action_invoice_create_wizard(self):
|
|
"""opening a wizard to create invoice"""
|
|
return {
|
|
'name': _('Create Invoice'),
|
|
'view_mode': 'form',
|
|
'res_model': 'mobile.invoice',
|
|
'type': 'ir.actions.act_window',
|
|
'target': 'new'
|
|
}
|
|
|
|
def action_post_stock(self):
|
|
flag = 0
|
|
for order in self.product_order_line:
|
|
if order.product_uom_qty > order.qty_stock_move:
|
|
flag = 1
|
|
pick = {
|
|
'picking_type_id': self.picking_transfer_id.id,
|
|
'partner_id': self.person_name.id,
|
|
'origin': self.name,
|
|
'location_dest_id': self.person_name.property_stock_customer.id,
|
|
'location_id': self.picking_transfer_id.default_location_src_id.id,
|
|
}
|
|
|
|
picking = self.env['stock.picking'].create(pick)
|
|
self.stock_picking_id = picking.id
|
|
self.picking_count = len(picking)
|
|
moves = order.filtered(
|
|
lambda r: r.product_id.type in ['product',
|
|
'consu'])._create_stock_moves_transfer(
|
|
picking)
|
|
move_ids = moves._action_confirm()
|
|
move_ids._action_assign()
|
|
if order.product_uom_qty < order.qty_stock_move:
|
|
raise UserError(
|
|
_('Used quantity is less than quantity stock move posted. '))
|
|
if flag != 1:
|
|
raise UserError(_('Nothing to post stock move'))
|
|
if flag != 1:
|
|
raise UserError(_('Nothing to post stock move'))
|
|
|
|
def action_view_invoice(self):
|
|
self.ensure_one()
|
|
ctx = dict(
|
|
create=False,
|
|
)
|
|
action = {
|
|
'name': _("Invoices"),
|
|
'type': 'ir.actions.act_window',
|
|
'res_model': 'account.move',
|
|
'target': 'current',
|
|
'context': ctx
|
|
}
|
|
invoice_ids = self.env['account.move'].search(
|
|
[('invoice_origin', '=', self.name)])
|
|
inv_ids = []
|
|
for each in invoice_ids:
|
|
inv_ids.append(each.id)
|
|
if len(invoice_ids) == 1:
|
|
invoice = inv_ids and inv_ids[0]
|
|
action['res_id'] = invoice
|
|
action['view_mode'] = 'form'
|
|
action['views'] = [
|
|
(self.env.ref('account.view_move_form').id, 'form')]
|
|
else:
|
|
|
|
action['view_mode'] = 'tree,form'
|
|
action['domain'] = [('id', 'in', inv_ids)]
|
|
return action
|
|
|
|
def get_ticket(self):
|
|
self.ensure_one()
|
|
user = self.env['res.users'].browse(self.env.uid)
|
|
if user.tz:
|
|
tz = pytz.timezone(user.tz)
|
|
time = pytz.utc.localize(datetime.now()).astimezone(tz)
|
|
date_today = time.strftime("%Y-%m-%d %H:%M %p")
|
|
else:
|
|
date_today = datetime.strftime(datetime.now(),
|
|
"%Y-%m-%d %I:%M:%S %p")
|
|
complaint_text = ""
|
|
description_text = ""
|
|
complaint_id = self.env['mobile.complaint.tree'].search(
|
|
[('complaint_id', '=', self.id)])
|
|
if complaint_id:
|
|
for obj in complaint_id:
|
|
complaint = obj.complaint_type_tree
|
|
description = obj.description_tree
|
|
complaint_text = complaint.complaint_type + ", " + complaint_text
|
|
if description.description:
|
|
description_text = description.description + ", " + description_text
|
|
else:
|
|
for obj in complaint_id:
|
|
complaint = obj.complaint_type_tree
|
|
complaint_text = complaint.complaint_type + ", " + complaint_text
|
|
data = {
|
|
'ids': self.ids,
|
|
'model': self._name,
|
|
'date_today': date_today,
|
|
'date_request': self.date_request,
|
|
'date_return': self.return_date,
|
|
'sev_id': self.name,
|
|
'warranty': self.is_in_warranty,
|
|
'customer_name': self.person_name.name,
|
|
'imei_no': self.imei_no,
|
|
'technician': self.technician_name.name,
|
|
'complaint_types': complaint_text,
|
|
'complaint_description': description_text,
|
|
'mobile_brand': self.brand_name.brand_name,
|
|
'model_name': self.model_name.mobile_brand_models,
|
|
|
|
}
|
|
return self.env.ref(
|
|
'mobile_service_shop.mobile_service_ticket').report_action(self,
|
|
data=data)
|
|
|
|
|
|
class MobileBrand(models.Model):
|
|
_name = 'mobile.brand'
|
|
_rec_name = 'brand_name'
|
|
|
|
brand_name = fields.Char(string="Mobile Brand", required=True)
|
|
|
|
|
|
class MobileComplaintType(models.Model):
|
|
_name = 'mobile.complaint'
|
|
_rec_name = 'complaint_type'
|
|
|
|
complaint_type = fields.Char(string="Complaint Type", required=True)
|
|
|
|
|
|
class MobileComplaintTypeTemplate(models.Model):
|
|
_name = 'mobile.complaint.description'
|
|
_rec_name = 'description'
|
|
|
|
complaint_type_template = fields.Many2one('mobile.complaint',
|
|
string="Complaint Type Template",
|
|
required=True)
|
|
description = fields.Text(string="Complaint Description")
|
|
|
|
|
|
class MobileComplaintTree(models.Model):
|
|
_name = 'mobile.complaint.tree'
|
|
_rec_name = 'complaint_type_tree'
|
|
|
|
complaint_id = fields.Many2one('mobile.service')
|
|
|
|
complaint_type_tree = fields.Many2one('mobile.complaint', string="Category",
|
|
required=True)
|
|
description_tree = fields.Many2one('mobile.complaint.description',
|
|
string="Description",
|
|
domain="[('complaint_type_template','=',complaint_type_tree)]")
|
|
|
|
|
|
class MobileBrandModels(models.Model):
|
|
_name = 'brand.model'
|
|
_rec_name = 'mobile_brand_models'
|
|
|
|
mobile_brand_name = fields.Many2one('mobile.brand', string="Mobile Brand",
|
|
required=True)
|
|
mobile_brand_models = fields.Char(string="Model Name", required=True)
|
|
image_medium = fields.Binary(string='image', store=True, attachment=True)
|
|
|
|
|
|
class MobileServiceTermsAndConditions(models.Model):
|
|
_name = 'terms.conditions'
|
|
_rec_name = 'terms_id'
|
|
|
|
terms_id = fields.Char(String="Terms and condition", compute="_find_id")
|
|
terms_conditions = fields.Text(string="Terms and Conditions")
|
|
|
|
def _find_id(self):
|
|
self.terms_id = self.id or ''
|
|
|