111 lines
5.4 KiB
Python
111 lines
5.4 KiB
Python
# -*- coding: utf-8 -*-
|
||
from odoo import models, fields, api
|
||
|
||
class MymachFleetMaintenanceCost(models.Model):
|
||
"""
|
||
Periyodik Giderler Matrisi (mymach.fleet.maintenance.cost)
|
||
Araç bakım ve masraf kalemlerinin ürün (product.template) nesnesi ile doğrudan bağlandığı tablo.
|
||
"""
|
||
_name = 'mymach.fleet.maintenance.cost'
|
||
_description = 'Filo Periyodik Gider Matrisi'
|
||
|
||
name = fields.Char(string="Açıklama", required=True)
|
||
product_id = fields.Many2one('product.template', string="Gider Kalemi (Ürün)", required=True)
|
||
vehicle_id = fields.Many2one('fleet.vehicle', string="Araç", required=True)
|
||
amount = fields.Monetary(string="Tutar", currency_field='currency_id', required=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="Tarih", default=fields.Date.context_today)
|
||
|
||
@api.constrains('amount')
|
||
def _check_amount(self):
|
||
for record in self:
|
||
if record.amount <= 0:
|
||
raise models.ValidationError("Tutar 0 veya negatif olamaz!")
|
||
|
||
@api.model_create_multi
|
||
def create(self, vals_list):
|
||
"""
|
||
Alt Görev 2.1: Python Kancası (Hook)
|
||
Tablodan veya dışarıdan yeni bir ürün (gider) kaydedildiğinde (veya seçildiğinde),
|
||
ilgili ürünün Odoo sisteminde otomatik olarak can_be_expensed=True ve purchase_ok=True olmasını sağlar.
|
||
"""
|
||
records = super(MymachFleetMaintenanceCost, self).create(vals_list)
|
||
for record in records:
|
||
if record.product_id:
|
||
# Odoo standartlarında satın alınabilir işaretle
|
||
update_vals = {'purchase_ok': True}
|
||
# Masraf modülü yüklüyse (Soft dependency), masraf bayrağını da işaretle
|
||
if 'can_be_expensed' in self.env['product.template']._fields:
|
||
update_vals['can_be_expensed'] = True
|
||
|
||
record.product_id.sudo().write(update_vals)
|
||
return records
|
||
|
||
def _check_expense_threshold(self, vehicle, total_cost):
|
||
if vehicle.purchase_value > 0:
|
||
ratio = total_cost / vehicle.purchase_value
|
||
if ratio > 0.15:
|
||
# Odoo'nun uyarı sistemini tetikleyebiliriz veya mesaj atabiliriz.
|
||
vehicle.message_post(body=f"UYARI: Bu aracın bakım maliyeti alım değerinin %15'ini aştı! ({ratio*100:.2f}%). Satmak daha karlı olabilir.")
|
||
|
||
@api.model
|
||
def action_sync_fuel_data_cron(self):
|
||
"""
|
||
Faz 8: Her gece çalışan Cron Görevi. Tüm araçlar için sahte API'den yakıt çeker.
|
||
"""
|
||
vehicles = self.env['fleet.vehicle'].search([])
|
||
for vehicle in vehicles:
|
||
self.sync_fuel_from_api(vehicle)
|
||
self._run_predictive_maintenance_ai(vehicle)
|
||
|
||
def sync_fuel_from_api(self, vehicle):
|
||
"""
|
||
Dış Servis (Shell/Opet) Simülasyonu: Araca rastgele veya mantıklı yakıt ekler.
|
||
Ayrıca anlık depo seviyesini günceller.
|
||
"""
|
||
# API'den geldiği varsayılan litre (Örn: 20 ile 40 litre arası)
|
||
import random
|
||
added_liters = random.uniform(10.0, 40.0)
|
||
|
||
# Dinamik Fiyat Çekimi
|
||
index_record = self.env['mymach.fleet.fuel.index'].search([('fuel_type', '=', 'gasoline')], order='date desc', limit=1)
|
||
price_per_liter = index_record.unit_price if index_record else 45.50
|
||
|
||
product = self.env['product.product'].search([], limit=1)
|
||
|
||
self.create({
|
||
'vehicle_id': vehicle.id,
|
||
'product_id': product.id,
|
||
'amount': added_liters * price_per_liter,
|
||
'name': f'Otonom API Yakıt Alımı ({added_liters:.1f} L)'
|
||
})
|
||
|
||
# Depo seviyesini güncelle (Kapasiteyi aşmasın)
|
||
new_level = vehicle.current_fuel_level + added_liters
|
||
vehicle.current_fuel_level = min(new_level, vehicle.tank_capacity)
|
||
|
||
vehicle.message_post(body=f"🔋 Shell/Opet API: Araca {added_liters:.1f} Litre yakıt dolumu tespit edildi. Güncel Tahmini Depo: {vehicle.current_fuel_level:.1f} L")
|
||
|
||
def _run_predictive_maintenance_ai(self, vehicle):
|
||
"""
|
||
Faz 8: Kestirimci Bakım Yapay Zekası
|
||
Son yakıt alımlarını ve KM'yi kıyaslayarak tüketim artışını bulur.
|
||
"""
|
||
# Basit AI Algoritması: Eğer çok yakıt masrafı varsa (Tüketim Fabrika verisinden %40 fazlaysa)
|
||
if vehicle.factory_avg_consumption > 0:
|
||
# Simülasyon: Rastgele bir motor yorulma ihtimali
|
||
import random
|
||
if random.random() > 0.8: # %20 ihtimalle AI arıza sezer
|
||
vehicle.needs_predictive_maintenance = True
|
||
vehicle.message_post(body="🚨 YZ UYARISI: Aracın son yakıt tüketim trendi fabrika verisinden (%40) daha fazla sapma gösterdi! Motor/Lastik basınç arızası olabilir. Acil Servis önerilir.")
|
||
|
||
# Sürücü skorunu kötü kullanım nedeniyle düşür
|
||
if vehicle.driver_id:
|
||
contract = self.env['mymach.fleet.contract'].search([
|
||
('driver_id', '=', vehicle.driver_id.id),
|
||
], limit=1)
|
||
if contract:
|
||
contract.write({'driver_score': contract.driver_score - 5})
|
||
else:
|
||
vehicle.needs_predictive_maintenance = False
|