Skip to content
Open

Main #1252

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
526 changes: 526 additions & 0 deletions pharma_control_center/README.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pharma_control_center/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
40 changes: 40 additions & 0 deletions pharma_control_center/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
'name': 'Pharma Control Center',
'version': '1.0',
'summary': 'Pharmacy Dashboard, Medicines, Inventory & Operations',
'sequence': 10,
'description': """
Pharma Control Center
=====================
Central system for pharmacy operations:
- Medicine catalog with batch, expiry, price, stock
- Dashboard showing total medicines and stock value
- Role‑based access (Patient, Doctor, Manager)
""",
'category': 'Healthcare/Pharmacy',
'author': "Muhammad Qasim Shabbir AI developer.",
'website': 'https://www.odoo.com/app/invoicing',
'depends': [
'base_setup',
'product',
'account',
'sale',
],
'data': [
'security/groups.xml',
'security/pharmacy_security.xml',
'security/pharmacy_patient_security.xml',
'security/sale_order_security.xml',
'security/ir.model.access.csv',
'data/demo_patients.xml',
'data/demo_medicines.xml',
'views/pharma_control_center_views.xml', # root menu defined here
'views/pharmacy_medicine_views.xml',
'views/pharmacy_patient_views.xml', # now includes the menuitem
'views/pharmacy_category_views.xml',
'views/pharmacy_order_views.xml',
],
'installable': True,
'application': True,
'license': 'LGPL-3',
}
52 changes: 52 additions & 0 deletions pharma_control_center/data/demo_medicines.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data noupdate="1">
<!-- Create a demo category first -->
<record id="demo_category_painkiller" model="pharmacy.category">
<field name="name">Painkiller</field>
<field name="code">PAIN</field>
<field name="description">Medicines for pain relief</field>
</record>

<!-- Demo medicine with white license (OTC) -->
<record id="demo_medicine_1" model="pharmacy.medicine">
<field name="name">Paracetamol 500mg</field>
<field name="batch_number">BATCH-001</field>
<field name="expiry_date">2025-12-31</field>
<field name="price">5.99</field>
<field name="cost_price">3.50</field>
<field name="quantity">100</field>
<field name="license_category">white</field>
<field name="category_id" ref="demo_category_painkiller"/>
<field name="storage_location">room_temp</field>
<field name="dosage">1 tablet every 4-6 hours</field>
</record>

<!-- Optional: Add blue (limited) and green (full) medicines -->
<record id="demo_medicine_2" model="pharmacy.medicine">
<field name="name">Amoxicillin 500mg</field>
<field name="batch_number">BATCH-002</field>
<field name="expiry_date">2026-06-30</field>
<field name="price">12.99</field>
<field name="cost_price">7.25</field>
<field name="quantity">50</field>
<field name="license_category">blue</field>
<field name="category_id" ref="demo_category_painkiller"/>
<field name="storage_location">cold</field>
<field name="dosage">1 capsule every 8 hours</field>
</record>

<record id="demo_medicine_3" model="pharmacy.medicine">
<field name="name">Morphine Sulphate</field>
<field name="batch_number">BATCH-003</field>
<field name="expiry_date">2025-08-15</field>
<field name="price">49.99</field>
<field name="cost_price">25.00</field>
<field name="quantity">10</field>
<field name="license_category">green</field>
<field name="category_id" ref="demo_category_painkiller"/>
<field name="storage_location">room_temp</field>
<field name="dosage">As prescribed by doctor</field>
</record>
</data>
</odoo>
52 changes: 52 additions & 0 deletions pharma_control_center/data/demo_patients.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data noupdate="1">
<!-- Create a demo category first -->
<record id="demo_category_painkiller" model="pharmacy.category">
<field name="name">Painkiller</field>
<field name="code">PAIN</field>
<field name="description">Medicines for pain relief</field>
</record>

<!-- Demo medicine with white license (OTC) -->
<record id="demo_medicine_1" model="pharmacy.medicine">
<field name="name">Paracetamol 500mg</field>
<field name="batch_number">BATCH-001</field>
<field name="expiry_date">2025-12-31</field>
<field name="price">5.99</field>
<field name="cost_price">3.50</field>
<field name="quantity">100</field>
<field name="license_category">white</field>
<field name="category_id" ref="demo_category_painkiller"/>
<field name="storage_location">room_temp</field>
<field name="dosage">1 tablet every 4-6 hours</field>
</record>

<!-- Optional: Add blue (limited) and green (full) medicines -->
<record id="demo_medicine_2" model="pharmacy.medicine">
<field name="name">Amoxicillin 500mg</field>
<field name="batch_number">BATCH-002</field>
<field name="expiry_date">2026-06-30</field>
<field name="price">12.99</field>
<field name="cost_price">7.25</field>
<field name="quantity">50</field>
<field name="license_category">blue</field>
<field name="category_id" ref="demo_category_painkiller"/>
<field name="storage_location">cold</field>
<field name="dosage">1 capsule every 8 hours</field>
</record>

<record id="demo_medicine_3" model="pharmacy.medicine">
<field name="name">Morphine Sulphate</field>
<field name="batch_number">BATCH-003</field>
<field name="expiry_date">2025-08-15</field>
<field name="price">49.99</field>
<field name="cost_price">25.00</field>
<field name="quantity">10</field>
<field name="license_category">green</field>
<field name="category_id" ref="demo_category_painkiller"/>
<field name="storage_location">room_temp</field>
<field name="dosage">As prescribed by doctor</field>
</record>
</data>
</odoo>
4 changes: 4 additions & 0 deletions pharma_control_center/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from . import pharma_medicine
from . import pharmacy_category
from . import pharmacy_patient
from . import pharma_control_center
146 changes: 146 additions & 0 deletions pharma_control_center/models/pharma_control_center.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
from odoo import models, fields, api, _
from datetime import date, timedelta

class PharmaControlCenter(models.Model):
_name = "pharma.control.center"
_description = "Pharma Control Center"

name = fields.Char(string="Name", required=True, default="Pharmacy Dashboard")
description = fields.Text(string="Description")
last_updated = fields.Datetime(string="Last Updated", default=fields.Datetime.now)

# Medicine statistics
total_medicines = fields.Integer(
string="Total Medicines", compute="_compute_statistics", store=False
)
total_stock_quantity = fields.Integer(
string="Total Stock Quantity", compute="_compute_statistics", store=False
)
stock_value = fields.Float(
string="Stock Value", compute="_compute_statistics", store=False
)
out_of_stock_count = fields.Integer(
string="Out of Stock Medicines", compute="_compute_statistics", store=False
)
low_stock_count = fields.Integer(
string="Low Stock (< 10 units)", compute="_compute_statistics", store=False
)
expiring_soon_count = fields.Integer(
string="Expiring Within 30 Days", compute="_compute_statistics", store=False
)
expired_count = fields.Integer(
string="Expired Medicines", compute="_compute_statistics", store=False
)

# Patient statistics
total_patients = fields.Integer(
string="Total Patients", compute="_compute_statistics", store=False
)
my_patients = fields.Integer(
string="My Patients", compute="_compute_statistics", store=False
)
patient_ids = fields.One2many(
'pharmacy.patient',
string="Patients",
compute='_compute_patient_ids',
readonly=True
)

# Today's orders summary
today_order_total_qty = fields.Float(
string="Total Quantity Today",
compute="_compute_today_orders_summary",
store=False
)
today_order_total_amount = fields.Float(
string="Total Sales Today",
compute="_compute_today_orders_summary",
store=False
)

@api.depends()
def _compute_statistics(self):
Medicine = self.env['pharmacy.medicine']
Patient = self.env['pharmacy.patient']
today = date.today()
thirty_days_later = today + timedelta(days=30)

for record in self:
# Medicine stats
all_meds = Medicine.search([])
record.total_medicines = len(all_meds)
record.total_stock_quantity = sum(med.quantity for med in all_meds)
record.stock_value = sum(med.quantity * med.price for med in all_meds)
record.out_of_stock_count = sum(1 for med in all_meds if med.quantity == 0)
record.low_stock_count = sum(1 for med in all_meds if 0 < med.quantity < 10)
record.expiring_soon_count = sum(
1 for med in all_meds
if med.expiry_date and med.expiry_date <= thirty_days_later and med.expiry_date > today
)
record.expired_count = sum(
1 for med in all_meds if med.expiry_date and med.expiry_date < today
)

# Patient stats
if Patient:
record.total_patients = Patient.search_count([])
if self.env.user.has_group('pharma_control_center.group_pharmacy_doctor'):
record.my_patients = Patient.search_count([('doctor_id', '=', self.env.user.id)])
else:
record.my_patients = 0
else:
record.total_patients = 0
record.my_patients = 0

@api.depends()
def _compute_patient_ids(self):
Patient = self.env['pharmacy.patient']
for record in self:
if self.env.user.has_group('pharma_control_center.group_pharmacy_doctor'):
record.patient_ids = Patient.search([('doctor_id', '=', self.env.user.id)])
elif self.env.user.has_group('pharma_control_center.group_pharmacy_manager'):
record.patient_ids = Patient.search([])
else:
record.patient_ids = False

@api.depends()
def _compute_today_orders_summary(self):
"""Compute total quantity and amount for today's orders.
Non‑managers see only their own orders."""
today = fields.Date.today()
tomorrow = today + timedelta(days=1)
domain = [
('order_id.date_order', '>=', today),
('order_id.date_order', '<', tomorrow),
('order_id.state', 'not in', ['cancel'])
]
if not self.env.user.has_group('pharma_control_center.group_pharmacy_manager'):
domain.append(('create_uid', '=', self.env.user.id))
order_lines = self.env['sale.order.line'].search(domain)
self.today_order_total_qty = sum(order_lines.mapped('product_uom_qty'))
self.today_order_total_amount = sum(order_lines.mapped('price_subtotal'))

def action_view_today_orders(self):
"""Open a list of today's order lines."""
today = fields.Date.today()
tomorrow = today + timedelta(days=1)
domain = [
('order_id.date_order', '>=', today),
('order_id.date_order', '<', tomorrow),
('order_id.state', 'not in', ['cancel'])
]
if not self.env.user.has_group('pharma_control_center.group_pharmacy_manager'):
domain.append(('create_uid', '=', self.env.user.id))

# Use the custom view
view = self.env.ref('pharma_control_center.view_sale_order_line_today_list', raise_if_not_found=False)
view_id = view.id if view else False
return {
'type': 'ir.actions.act_window',
'name': "Today's Orders",
'res_model': 'sale.order.line',
'view_mode': 'list,form',
'target': 'current',
'domain': domain,
'views': [(view_id, 'list')] if view_id else [(False, 'list')],
}
Loading