Tower: upload laundry_management 19.0.19.0.4 (via marketplace)
This commit is contained in:
180
addons/laundry_management/models/laundry_dashboard.py
Normal file
180
addons/laundry_management/models/laundry_dashboard.py
Normal file
@@ -0,0 +1,180 @@
|
||||
from odoo import models, fields, api
|
||||
|
||||
|
||||
class LaundryDashboard(models.TransientModel):
|
||||
"""Live KPI dashboard — queries sale.order with is_laundry_order = True."""
|
||||
_name = 'laundry.dashboard'
|
||||
_description = 'Laundry Dashboard'
|
||||
|
||||
today_orders = fields.Integer(string="Today's Orders")
|
||||
today_revenue = fields.Monetary(string="Today's Revenue", currency_field='currency_id')
|
||||
today_collected = fields.Monetary(string='Collected Today', currency_field='currency_id')
|
||||
today_outstanding = fields.Monetary(string='Outstanding Today', currency_field='currency_id')
|
||||
|
||||
pending_count = fields.Integer(string='Pending Orders')
|
||||
ready_count = fields.Integer(string='Ready for Pickup')
|
||||
in_progress_count = fields.Integer(string='In Processing')
|
||||
draft_count = fields.Integer(string='Quotes / Draft')
|
||||
|
||||
session_is_open = fields.Boolean(string='Session Open')
|
||||
session_name = fields.Char(string='Session')
|
||||
session_opening_cash = fields.Monetary(string='Opening Float', currency_field='currency_id')
|
||||
session_sales = fields.Monetary(string='Session Sales', currency_field='currency_id')
|
||||
session_cash = fields.Monetary(string='Session Cash', currency_field='currency_id')
|
||||
session_bank = fields.Monetary(string='Session Bank', currency_field='currency_id')
|
||||
session_id = fields.Many2one('laundry.session', string='Session Link')
|
||||
|
||||
month_orders = fields.Integer(string='Orders This Month')
|
||||
month_revenue = fields.Monetary(string='Revenue This Month', currency_field='currency_id')
|
||||
month_paid = fields.Monetary(string='Collected This Month', currency_field='currency_id')
|
||||
|
||||
currency_id = fields.Many2one(
|
||||
'res.currency',
|
||||
default=lambda self: self.env.company.currency_id,
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _build(self):
|
||||
today = fields.Date.today()
|
||||
month_start = today.replace(day=1)
|
||||
company = self.env.company
|
||||
Order = self.env['sale.order']
|
||||
Payment = self.env['account.payment']
|
||||
|
||||
_base_domain = [
|
||||
('is_laundry_order', '=', True),
|
||||
('company_id', '=', company.id),
|
||||
]
|
||||
|
||||
# ── Today ──────────────────────────────────────────────────────
|
||||
today_orders = Order.search(_base_domain + [
|
||||
('date_order', '>=', fields.Datetime.to_datetime(today)),
|
||||
('state', 'not in', ['cancel', 'draft']),
|
||||
])
|
||||
today_invoices = today_orders.mapped('invoice_ids').filtered(
|
||||
lambda i: i.state == 'posted' and i.move_type == 'out_invoice'
|
||||
)
|
||||
today_revenue = sum(today_orders.mapped('amount_total'))
|
||||
today_outstanding = sum(
|
||||
max(i.amount_residual, 0.0) for i in today_invoices
|
||||
)
|
||||
today_collected = today_revenue - today_outstanding
|
||||
|
||||
# ── Pipeline (all active laundry orders) ──────────────────────
|
||||
pipeline = Order.search(_base_domain + [
|
||||
('state', '=', 'sale'),
|
||||
])
|
||||
pending_count = len(pipeline)
|
||||
ready_count = len(pipeline.filtered(lambda o: o.laundry_state == 'ready'))
|
||||
in_progress_count = len(pipeline.filtered(lambda o: o.laundry_state == 'processing'))
|
||||
draft_count = len(Order.search(_base_domain + [('state', '=', 'draft')]))
|
||||
|
||||
# ── Session ────────────────────────────────────────────────────
|
||||
session = self.env['laundry.session'].search([
|
||||
('state', '=', 'opened'),
|
||||
('company_id', '=', company.id),
|
||||
], limit=1)
|
||||
|
||||
# ── Month ──────────────────────────────────────────────────────
|
||||
month_orders = Order.search(_base_domain + [
|
||||
('date_order', '>=', fields.Datetime.to_datetime(month_start)),
|
||||
('state', 'not in', ['cancel', 'draft']),
|
||||
])
|
||||
month_invoices = month_orders.mapped('invoice_ids').filtered(
|
||||
lambda i: i.state == 'posted' and i.move_type == 'out_invoice'
|
||||
)
|
||||
month_revenue = sum(month_orders.mapped('amount_total'))
|
||||
month_outstanding = sum(max(i.amount_residual, 0.0) for i in month_invoices)
|
||||
month_paid = month_revenue - month_outstanding
|
||||
|
||||
return self.create({
|
||||
'today_orders' : len(today_orders),
|
||||
'today_revenue' : today_revenue,
|
||||
'today_collected' : max(today_collected, 0.0),
|
||||
'today_outstanding' : today_outstanding,
|
||||
'pending_count' : pending_count,
|
||||
'ready_count' : ready_count,
|
||||
'in_progress_count' : in_progress_count,
|
||||
'draft_count' : draft_count,
|
||||
'session_is_open' : bool(session),
|
||||
'session_name' : session.name if session else '',
|
||||
'session_opening_cash' : session.opening_cash if session else 0.0,
|
||||
'session_sales' : session.total_sales if session else 0.0,
|
||||
'session_cash' : session.total_cash if session else 0.0,
|
||||
'session_bank' : session.total_bank if session else 0.0,
|
||||
'session_id' : session.id if session else False,
|
||||
'month_orders' : len(month_orders),
|
||||
'month_revenue' : month_revenue,
|
||||
'month_paid' : max(month_paid, 0.0),
|
||||
})
|
||||
|
||||
@api.model
|
||||
def action_open_dashboard(self):
|
||||
rec = self._build()
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': 'Dashboard',
|
||||
'res_model': 'laundry.dashboard',
|
||||
'res_id': rec.id,
|
||||
'view_mode': 'form',
|
||||
'target': 'main',
|
||||
'flags': {'mode': 'readonly'},
|
||||
}
|
||||
|
||||
def action_refresh(self):
|
||||
return self.action_open_dashboard()
|
||||
|
||||
def action_new_order(self):
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': 'New Laundry Order',
|
||||
'res_model': 'sale.order',
|
||||
'view_mode': 'form',
|
||||
'target': 'current',
|
||||
'context': {
|
||||
'default_is_laundry_order': True,
|
||||
},
|
||||
}
|
||||
|
||||
def action_open_session(self):
|
||||
if self.session_id:
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': 'Session',
|
||||
'res_model': 'laundry.session',
|
||||
'res_id': self.session_id.id,
|
||||
'view_mode': 'form',
|
||||
}
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': 'Sessions',
|
||||
'res_model': 'laundry.session',
|
||||
'view_mode': 'list,form',
|
||||
}
|
||||
|
||||
def action_new_session(self):
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': 'New Session',
|
||||
'res_model': 'laundry.session',
|
||||
'view_mode': 'form',
|
||||
}
|
||||
|
||||
def action_view_ready_orders(self):
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': 'Ready for Pickup',
|
||||
'res_model': 'sale.order',
|
||||
'view_mode': 'list,form',
|
||||
'domain': [('is_laundry_order', '=', True), ('laundry_state', '=', 'ready')],
|
||||
}
|
||||
|
||||
def action_view_pending_orders(self):
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': 'Pending Orders',
|
||||
'res_model': 'sale.order',
|
||||
'view_mode': 'list,form',
|
||||
'domain': [('is_laundry_order', '=', True), ('state', '=', 'sale'),
|
||||
('laundry_state', 'not in', ['delivered'])],
|
||||
}
|
||||
Reference in New Issue
Block a user