111 lines
5.1 KiB
Python
111 lines
5.1 KiB
Python
# -*- coding: utf-8 -*-
|
||
import datetime
|
||
from odoo import models, fields, api
|
||
|
||
class MymachFleetFine(models.Model):
|
||
"""
|
||
Otonom HGS, Ceza ve Park Gider Yönetimi Modeli
|
||
Güvenlik ihlalleriyle entegre olarak giderlerin şahsi mi yoksa şirket gideri mi olduğunu saptar.
|
||
"""
|
||
_name = 'mymach.fleet.fine'
|
||
_description = 'Filo Trafik Ceza ve HGS Yönetimi'
|
||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||
|
||
name = fields.Char(string="Geçiş/Ceza Fiş Numarası (Örn: HGS-981298)", required=True, tracking=True)
|
||
charge_type = fields.Selection([
|
||
('tax', 'Vergi Gideri'),
|
||
('insurance', 'Zorunlu Trafik Sigortası'),
|
||
('casco', 'Kasko Sigortası'),
|
||
('repair', 'Onarım / Hasar Gideri'),
|
||
('maintenance', 'Bakım Gideri'),
|
||
('rental', 'Kira Masrafı'),
|
||
('hgs', 'HGS / Otoyol Geçiş Ücreti'),
|
||
('fine', 'Trafik Cezası'),
|
||
('parking', 'Otopark Ücreti'),
|
||
('other', 'Diğer')
|
||
], string="Gider Tipi", required=True, default='hgs', tracking=True)
|
||
other_charge_type_name = fields.Char(string="Diğer Gider Açıklaması", tracking=True)
|
||
|
||
vehicle_id = fields.Many2one('fleet.vehicle', string="Araç", required=True, tracking=True)
|
||
driver_id = fields.Many2one('res.partner', string="Sürücü", related='vehicle_id.driver_id', store=True)
|
||
|
||
amount = fields.Monetary(string="Tutar", currency_field='currency_id', required=True, tracking=True)
|
||
currency_id = fields.Many2one('res.currency', string="Para Birimi", default=lambda self: self.env.ref('base.TRY', raise_if_not_found=False) or self.env.company.currency_id)
|
||
date = fields.Date(string="İşlem Tarihi", default=fields.Date.context_today, required=True, tracking=True)
|
||
|
||
is_personal_violation = fields.Boolean(
|
||
string="Şahsi Kullanım İhlali mi?",
|
||
compute="_compute_personal_violation",
|
||
store=True,
|
||
tracking=True
|
||
)
|
||
|
||
state = fields.Selection([
|
||
('draft', 'Taslak'),
|
||
('confirmed', 'Onaylandı'),
|
||
('deducted', 'Bordroya / Cari Hesaba Yansıtıldı')
|
||
], string="Durum", default='draft', tracking=True)
|
||
|
||
@api.depends('vehicle_id', 'date')
|
||
def _compute_personal_violation(self):
|
||
"""
|
||
Eğer ceza gününde araçla ilgili bir güvenlik ihlali logu (in_office_moving veya exception) varsa
|
||
otomatik olarak şahsi ihlal olarak işaretlenir.
|
||
"""
|
||
for record in self:
|
||
if record.vehicle_id and record.date:
|
||
# O gün bu araca ait ihlal logu var mı?
|
||
date_start = datetime.datetime.combine(record.date, datetime.time.min)
|
||
date_end = datetime.datetime.combine(record.date, datetime.time.max)
|
||
log_exists = self.env['mymach.fleet.security.log'].search([
|
||
('vehicle_id', '=', record.vehicle_id.id),
|
||
('status', 'in', ['in_office_moving', 'exception']),
|
||
('datetime', '>=', fields.Datetime.to_string(date_start)),
|
||
('datetime', '<=', fields.Datetime.to_string(date_end))
|
||
], limit=1)
|
||
record.is_personal_violation = bool(log_exists)
|
||
else:
|
||
record.is_personal_violation = False
|
||
|
||
@api.constrains('amount')
|
||
def _check_amount(self):
|
||
for record in self:
|
||
if record.amount <= 0:
|
||
raise models.ValidationError("Tutar 0 veya negatif olamaz!")
|
||
|
||
def action_confirm(self):
|
||
for record in self:
|
||
if record.state != 'draft':
|
||
raise models.ValidationError("Sadece taslak halindeki kayıtlar onaylanabilir!")
|
||
record.write({'state': 'confirmed'})
|
||
|
||
def action_deduct_to_payroll(self):
|
||
"""
|
||
Eğer şahsi ihlalse, tutarı bordro/cari borç olarak yansıtır.
|
||
Burada basitlik adına ilgili güvenlik loguna ceza bedeli olarak yazar ve durumu güncelleriz.
|
||
"""
|
||
for record in self:
|
||
if record.state != 'confirmed':
|
||
raise models.ValidationError("Sadece onaylanmış kayıtlar yansıtılabilir!")
|
||
if not record.is_personal_violation:
|
||
continue
|
||
|
||
date_start = datetime.datetime.combine(record.date, datetime.time.min)
|
||
date_end = datetime.datetime.combine(record.date, datetime.time.max)
|
||
log = self.env['mymach.fleet.security.log'].search([
|
||
('vehicle_id', '=', record.vehicle_id.id),
|
||
('status', 'in', ['in_office_moving', 'exception']),
|
||
('datetime', '>=', fields.Datetime.to_string(date_start)),
|
||
('datetime', '<=', fields.Datetime.to_string(date_end))
|
||
], limit=1)
|
||
|
||
if log:
|
||
log.write({'deduction_amount': record.amount})
|
||
|
||
if record.driver_id:
|
||
record.driver_id.message_post(
|
||
body=f"🚨 <b>Şahsi Kullanım İhlal Cezası:</b> {record.date} tarihinde gerçekleşen ihlal nedeniyle {record.amount} {record.currency_id.name} tutarındaki ceza/ücret cari hesabınıza borç olarak yansıtılmıştır."
|
||
)
|
||
|
||
record.write({'state': 'deducted'})
|