Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import io
- import qrcode
- import base64
- import os
- from PyPDF2 import PdfFileWriter, PdfFileReader
- from reportlab.lib.pagesizes import letter
- from reportlab.pdfgen import canvas
- from odoo import api, fields, models, SUPERUSER_ID, _
- from odoo.exceptions import AccessError, UserError, ValidationError
- from odoo.tools import float_is_zero, format_amount, format_date, html_keep_url, is_html_empty
- from odoo.tools.sql import create_index
- READONLY_FIELD_STATES = {
- state: [('readonly', True)]
- for state in {'review', 'approve', 'reject'}
- }
- LOCKED_FIELD_STATES = {
- state: [('readonly', True)]
- for state in {'approve', 'reject'}
- }
- # INVOICE_STATUS = [
- # ('upselling', 'Upselling Opportunity'),
- # ('invoiced', 'Fully Invoiced'),
- # ('to invoice', 'To Invoice'),
- # ('no', 'Nothing to Invoice')
- # ]
- class ImportPermit(models.Model):
- _name = 'import.permit'
- _inherit = ['portal.mixin', 'mail.thread', 'mail.activity.mixin', 'utm.mixin']
- # _inherit = ['mail.thread', 'mail.activity.mixin']
- _description = "Import Permit Request"
- _order = 'date_order desc, id desc'
- _check_company_auto = True
- _rec_name = 'permit_number'
- # _sql_constraints = [
- # ('date_requested_conditional_required',
- # "CHECK((state IN ('request', 'approve') AND date_requested IS NOT NULL) OR state NOT IN ('request', 'approved'))",
- # "A confirmed permit request requires a confirmation date."),
- # ]
- @property
- def _rec_names_search(self):
- if self._context.get('permit_show_applicant_name'):
- return ['name', 'applicant_id.name']
- return ['name']
- permit_number = fields.Char(
- string="Permit Number",
- required=True,
- copy=False,
- readonly=True,
- index='trigram',
- #states={'draft': [('readonly', False)]},
- state={'draft': [('readonly', False)]},
- default=lambda self: _('New')
- )
- company_id = fields.Many2one(
- comodel_name='res.company',
- required=True,
- index=True,
- tracking=True,
- default=lambda self: self.env.company
- )
- permit_type = fields.Selection(
- selection=[
- ('Drone', 'Drone'),
- ('General', 'General')
- ],
- # required=True,
- string='Permit Type',
- default='Drone', # Set the default value to 'Drone'
- tracking=True
- )
- state = fields.Selection(
- selection=[
- ('draft', 'Draft'),
- ('submit', 'Submitted'),
- ('review', 'Under Review'),
- ('approve', 'Approved'),
- ('reject', 'Rejected')
- ],
- string="Status",
- readonly=True,
- copy=False,
- index=True,
- tracking=3,
- default='draft'
- )
- @api.constrains('fees')
- def _check_fees(self):
- for record in self:
- if record.fees < 0:
- raise exceptions.ValidationError("Fees must be a positive value.")
- @api.model_create_multi
- def create(self, vals_list):
- for vals in vals_list:
- if 'company_id' in vals:
- self = self.with_company(vals['company_id'])
- if vals.get('permit_number', _("New")) == _("New"):
- seq_date = fields.Datetime.context_timestamp(
- self, fields.Datetime.to_datetime(vals['date_request'])
- ) if 'date_request' in vals else None
- vals['permit_number'] = self.env['ir.sequence'].next_by_code(
- 'import.permit',
- sequence_date=seq_date
- ) or _("New")
- return super().create(vals_list)
- applicant_id = fields.Many2one(
- comodel_name='res.partner',
- string="Customer",
- required=True,
- readonly=False,
- change_default=True,
- index=True,
- tracking=1,
- states=READONLY_FIELD_STATES,
- domain="[('type', '!=', 'private'), ('company_id', 'in', (False, company_id))]"
- # state={'review': [('readonly', True)], 'approve': [('readonly', True)], 'reject': [('readonly', True)]},
- # domain="[('type', '!=', 'private'), ('company_id', 'in', (False, company_id))]"
- )
- email = fields.Char(related='applicant_id.email', string="Email", tracking=True)
- fees = fields.Float(
- string="Fees",
- default=25.00,
- required=True,
- readonly=False,
- tracking=1,
- state={'review': [('readonly', True)], 'approve': [('readonly', True)], 'reject': [('readonly', True)]}
- )
- date_request = fields.Datetime(
- string="Request Date",
- required=True,
- readonly=True,
- index=True,
- default=fields.Datetime.now,
- states=LOCKED_FIELD_STATES,
- copy=False
- )
- paid_date = fields.Date(
- string="Paid Date",
- copy=False,
- readonly=True,
- state={'draft': [('readonly', False)]},
- index=True,
- default=fields.Date.context_today,
- tracking=2
- )
- attachment_ids = fields.Many2many(
- comodel_name='ir.attachment',
- relation='import_permit_attachment_rel',
- column1='import_permit_id',
- column2='attachment_id',
- string="Attachments",
- states=LOCKED_FIELD_STATES,
- help="Related Attachments"
- )
- certificate = fields.Binary(
- string="Certificate",
- readonly=True,
- state={'approve': [('readonly', False)]},
- attachment=True
- )
- certificate_filename = fields.Char(
- string="Certificate Filename",
- readonly=True,
- state={'approve': [('readonly', False)]}
- )
- mobile = fields.Char(related='applicant_id.mobile', string="Mobile", tracking=True)
- street = fields.Char(related='applicant_id.street', string="Address", tracking=True)
- street2 = fields.Char(related='applicant_id.street2', string="Address", tracking=True)
- city = fields.Char(related='applicant_id.city', string="Address", tracking=True)
- state_id = fields.Many2one(related='applicant_id.state_id', string="Address", tracking=True)
- zip = fields.Char(related='applicant_id.zip', string="Address", tracking=True)
- country_id = fields.Many2one(related='applicant_id.country_id', string="Address", tracking=True)
- birth_date = fields.Date(string='Birth Date', tracking=True)
- id_type = fields.Selection(
- [
- ('passport', 'Passport'),
- ('social', 'Social Security'),
- ('drivers', 'Drivers License')
- ],
- string="Identification Type",
- tracking=True
- )
- create_date = fields.Datetime( # Override of default create_date field from ORM
- string="Creation Date", index=True, readonly=True)
- date_requested = fields.Datetime(
- string="Requested Date",
- required=True, readonly=False, copy=False,
- states=READONLY_FIELD_STATES,
- help="Creation date of draft/sent permits,\nConfirmation date of confirmed requests.",
- default=fields.Datetime.now)
- id_number = fields.Char(string="Identification Number", tracking=True)
- permit_printed_by = fields.Many2one('res.users', readonly=True)
- permit_printed_on = fields.Datetime(readonly=True)
- requested_date = fields.Date(string="Requested Date", default=fields.Date.context_today)
- bank_account_info = fields.Many2one('res.partner.bank', string='Company Bank Account Information')
- approved_by = fields.Many2one('res.users', string='Approved By', default=lambda self: self.env.user, readonly=True)
- approved_date = fields.Datetime(string='Approved Date', readonly=True)
- approval_signature = fields.Binary(string="Signature", attachment=True, state={'approve': [('readonly', False)]})
- notes = fields.Text(string="Additional Notes", tracking=True)
- receipt = fields.Many2many('ir.attachment', string="Receipt", tracking=True)
- receipt_no = fields.Char(tracking=True)
- drone_permit_ids = fields.One2many(
- comodel_name='import.permit.drone',
- inverse_name='import_permit_id',
- string='Drone Permits'
- )
- general_permit_ids = fields.One2many(
- comodel_name='import.permit.general',
- inverse_name='import_permit_id',
- string='General Permits'
- )
- @api.depends('state')
- def _compute_is_locked(self):
- for record in self:
- record.is_locked = record.state in {'approve', 'reject'}
- is_locked = fields.Boolean(
- compute='_compute_is_locked',
- store=True,
- string='Is Locked',
- help="If True, the import permit is locked and cannot be edited."
- )
- def _prepare_certificate_values(self):
- self.ensure_one()
- if self.permit_type == 'Drone':
- permit_type_label = _("Drone Import Permit")
- else:
- permit_type_label = _("General Import Permit")
- certificate_values = {
- 'name': permit_type_label,
- 'permit_number': self.permit_number,
- 'applicant_name': self.applicant_id.name,
- 'fees': self.fees,
- }
- return certificate_values
- def _generate_certificate_pdf(self, certificate_values):
- self.ensure_one()
- # Create a new PDF document
- buffer = io.BytesIO()
- c = canvas.Canvas(buffer, pagesize=letter)
- # Set the font and font size
- c.setFont('Helvetica', 12)
- # Write the certificate details
- c.drawString(100, 700, certificate_values['name'])
- c.drawString(100, 670, _("Permit Number: {}".format(certificate_values['permit_number'])))
- c.drawString(100, 640, _("Applicant Name: {}".format(certificate_values['applicant_name'])))
- c.showPage()
- c.save()
- # Get the PDF buffer value
- pdf_buffer = buffer.getvalue()
- buffer.close()
- return pdf_buffer
- def _generate_certificate_qrcode(self, certificate_values):
- self.ensure_one()
- # Generate the QR code data
- qr_code_data = {
- 'Permit Number': certificate_values['permit_number'],
- 'Applicant Name': certificate_values['applicant_name'],
- 'Fees': str(certificate_values['fees']),
- }
- qr_code_string = str(qr_code_data)
- # Generate the QR code image
- qr_code_img = qrcode.make(qr_code_string)
- # Convert the image to a byte stream
- qr_code_byte_stream = io.BytesIO()
- qr_code_img.save(qr_code_byte_stream, format='PNG')
- qr_code_byte_stream.seek(0)
- # Get the base64 encoded value of the image byte stream
- qr_code_base64 = base64.b64encode(qr_code_byte_stream.getvalue()).decode('utf-8')
- return qr_code_base64
- def _send_certificate_email(self, certificate_pdf, email):
- self.ensure_one()
- # Create a temporary directory to store the PDF file
- temp_dir = '/tmp/certificate'
- os.makedirs(temp_dir, exist_ok=True)
- # Save the PDF file in the temporary directory
- certificate_path = os.path.join(temp_dir, 'certificate.pdf')
- with open(certificate_path, 'wb') as f:
- f.write(certificate_pdf)
- # Compose the email
- subject = _("Import Permit Certificate")
- body = _("Please find attached the import permit certificate.")
- # Attach the PDF file to the email
- attachments = [(os.path.basename(certificate_path), open(certificate_path, 'rb').read())]
- # Send the email
- self.env['mail.mail'].create({
- 'subject': subject,
- 'email_to': email,
- 'body': body,
- 'attachment_ids': attachments
- }).send()
- def action_approve(self):
- for permit in self:
- certificate_values = permit._prepare_certificate_values()
- certificate_pdf = permit._generate_certificate_pdf(certificate_values)
- permit.certificate = base64.b64encode(certificate_pdf)
- permit.certificate_filename = 'import_permit_certificate.pdf'
- permit.state = 'approve'
- # Send the certificate by email
- permit._send_certificate_email(certificate_pdf, permit.email)
- return True
- def action_reject(self):
- self.state = 'reject'
- def action_reset_draft(self):
- self.state = 'draft'
- def action_draft(self):
- self.write({'state': 'draft'})
- def action_submit(self):
- qr_data = {
- 'applicant_id': self.applicant_id.name,
- 'mobile': self.applicant_id.mobile,
- 'permit_number': self.permit_number,
- 'fees': self.fees,
- 'bank_account_info': self.bank_account_info.name if self.bank_account_info else None,
- }
- qr_img = qrcode.make(str(qr_data))
- img_buffer = io.BytesIO()
- qr_img.save(img_buffer, format='PNG')
- img_buffer.seek(0)
- img_data = base64.b64encode(img_buffer.read())
- self.write({'state': 'submit'})
- def action_review(self):
- self.write({'state': 'review'})
- class ImportPermitDrone(models.Model):
- _name = 'import.permit.drone'
- _description = 'Drone Import Permit'
- import_permit_id = fields.Many2one(
- comodel_name='import.permit',
- string='Import Permit',
- #required=True,
- ondelete='cascade',
- index=True
- )
- drone_type = fields.Char(string='Drone Type', tracking=True)
- drone_make = fields.Char(string='Make', tracking=True)
- drone_model = fields.Char(string='Model', tracking=True)
- drone_color = fields.Char(string='Color', tracking=True)
- num_engines = fields.Integer(string='Number of Engines', tracking=True)
- drone_serial_number = fields.Char(string='Serial Number', tracking=True)
- drone_quantity = fields.Integer(string="Quantity", tracking=True)
- documents = fields.Binary(string="Documents", tracking=True)
- documents_filename = fields.Char(string="Documents Filename")
- drone_stay_in_belize = fields.Selection(
- [('yes', 'Yes'), ('no', 'No')],
- string='Drone Stay in Belize',
- default='yes',
- tracking=True,
- state={'Draft': [('invisible', True)]}
- )
- departure_date = fields.Date(
- string='Departure Date',
- tracking=True,
- state={'Draft': [('required', True)]},
- help="The date when the drone is leaving Belize",
- attrs={'invisible': [('drone_stay_in_belize', '=', 'yes')]}
- )
- @api.onchange('documents')
- def _onchange_documents(self):
- if self.documents:
- self.documents_filename = "Documents"
- def open_document(self):
- self.ensure_one()
- return {
- 'type': 'ir.actions.act_url',
- 'url': f'/web/content/{self._name}/{self.id}/documents',
- 'target': 'self',
- }
- def _get_default_import_permit(self):
- # Get the default import permit based on your logic (e.g., current user, date, etc.)
- default_import_permit = self.env['import.permit'].search([...], limit=1)
- return default_import_permit.id
- class ImportPermitGeneral(models.Model):
- _name = 'import.permit.general'
- _description = 'General Import Permit'
- import_permit_id = fields.Many2one(
- comodel_name='import.permit',
- string='Import Permit',
- required=True,
- ondelete='cascade',
- index=True
- )
- imported_goods_type = fields.Char(string='Type', tracking=True)
- imported_goods_make = fields.Char(string='Make', tracking=True)
- imported_goods_model = fields.Char(string='Model', tracking=True)
- imported_goods_quantity = fields.Integer(string='Quantity', tracking=True)
- imported_goods_serial_number = fields.Char(string='Serial Number', tracking=True)
- documents = fields.Binary(string="Documents", tracking=True)
- documents_filename = fields.Char(string="Documents Filename")
- @api.onchange('documents')
- def _onchange_documents(self):
- if self.documents:
- self.documents_filename = "Documents"
- def open_document(self):
- self.ensure_one()
- return {
- 'type': 'ir.actions.act_url',
- 'url': f'/web/content/{self._name}/{self.id}/documents',
- 'target': 'self',
- }
Add Comment
Please, Sign In to add comment