-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Kevin Luna <[email protected]>
- Loading branch information
Showing
29 changed files
with
1,549 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
==== | ||
Lims | ||
==== | ||
|
||
.. | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!! This file is generated by oca-gen-addon-readme !! | ||
!! changes will be overwritten. !! | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!! source digest: sha256:05b7fd50b44f8d195624bc3de3642e125de904aa3b3dd42d9f5cebb7f4917ead | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png | ||
:target: https://odoo-community.org/page/development-status | ||
:alt: Beta | ||
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png | ||
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html | ||
:alt: License: LGPL-3 | ||
.. |badge3| image:: https://img.shields.io/badge/github-tegin%2Flims-lightgray.png?logo=github | ||
:target: https://github.com/tegin/lims/tree/14.0/lims | ||
:alt: tegin/lims | ||
|
||
|badge1| |badge2| |badge3| | ||
|
||
This module allows to manage a Laboratory from an odoo instance. | ||
|
||
It implements a simple LIMS for your company. | ||
|
||
**Table of contents** | ||
|
||
.. contents:: | ||
:local: | ||
|
||
Usage | ||
===== | ||
|
||
1. A sampler user will create a sample from `LIMS > Sample > Samples` | ||
1. Add a sample date, customer and sample type | ||
2. Add the different analysis you will do | ||
3. Receive the sample | ||
2. An analyst user will review al the samples to analyze and will set the value. | ||
Once it has been set, he will submit the results | ||
3. A verifier user will verify all the results. | ||
The verifier must be different than the analyst | ||
|
||
Known issues / Roadmap | ||
====================== | ||
|
||
The following characteristics are still Work In Progress: | ||
|
||
* Usage of worklist | ||
* Integration with devices | ||
* Integration with sales / accounting | ||
* Calculations | ||
* Quality controls | ||
* Batching of samples | ||
* Sample storage | ||
|
||
Bug Tracker | ||
=========== | ||
|
||
Bugs are tracked on `GitHub Issues <https://github.com/tegin/lims/issues>`_. | ||
In case of trouble, please check there if your issue has already been reported. | ||
If you spotted it first, help us to smash it by providing a detailed and welcomed | ||
`feedback <https://github.com/tegin/lims/issues/new?body=module:%20lims%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. | ||
|
||
Do not contact contributors directly about support or help with technical issues. | ||
|
||
Credits | ||
======= | ||
|
||
Authors | ||
~~~~~~~ | ||
|
||
* Dixmit | ||
* Creu Blanca | ||
|
||
Contributors | ||
~~~~~~~~~~~~ | ||
|
||
* Dixmit | ||
* Enric Tobella | ||
|
||
Maintainers | ||
~~~~~~~~~~~ | ||
|
||
This module is part of the `tegin/lims <https://github.com/tegin/lims/tree/14.0/lims>`_ project on GitHub. | ||
|
||
You are welcome to contribute. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import models |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Copyright 2023 Dixmit | ||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). | ||
|
||
{ | ||
"name": "Lims", | ||
"summary": """ | ||
Laboratory Information Management System""", | ||
"version": "14.0.1.0.0", | ||
"license": "LGPL-3", | ||
"author": "Dixmit, Creu Blanca,Odoo Community Association (OCA)", | ||
"website": "https://github.com/tegin/lims", | ||
"depends": ["product"], | ||
"data": [ | ||
"security/security.xml", | ||
"security/ir.model.access.csv", | ||
"data/ir_sequence_data.xml", | ||
"views/menu.xml", | ||
"views/lims_department.xml", | ||
"views/lims_sample_type.xml", | ||
"views/lims_sample.xml", | ||
"views/lims_analysis.xml", | ||
"views/product_template.xml", | ||
], | ||
"demo": ["demo/demo.xml"], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<?xml version="1.0" encoding="UTF-8" ?> | ||
<!-- | ||
Copyright 2023 Dixmit | ||
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). | ||
--> | ||
<odoo noupdate="1"> | ||
<record id="seq_lims_sample" model="ir.sequence" forcecreate="1"> | ||
<field name="name">LIMS Sample sequence</field> | ||
<field name="code">lims.sample</field> | ||
<field name="prefix">SPL</field> | ||
<field name="padding">6</field> | ||
</record> | ||
<record id="seq_lims_analysis" model="ir.sequence" forcecreate="1"> | ||
<field name="name">LIMS Analysis sequence</field> | ||
<field name="code">lims.analysis</field> | ||
<field name="prefix">LA</field> | ||
<field name="padding">6</field> | ||
</record> | ||
</odoo> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<!-- Copyright 2023 Dixmit | ||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). --> | ||
<odoo noupdate="1"> | ||
<record model="lims.sample.type" id="lims_blood_sample_type"> | ||
<field name="name">Blood</field> | ||
</record> | ||
<record model="lims.department" id="lims_hematology_department"> | ||
<field name="name">Hematology</field> | ||
<field name="user_ids" eval="[(4, ref('base.user_admin'))]" /> | ||
</record> | ||
</odoo> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from . import lims_sample | ||
from . import lims_sample_type | ||
from . import lims_department | ||
from . import lims_analysis | ||
from . import res_users | ||
from . import product_template |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
# Copyright 2023 Dixmit | ||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). | ||
|
||
from odoo import _, api, fields, models | ||
from odoo.exceptions import AccessDenied | ||
|
||
|
||
class LimsAnalysis(models.Model): | ||
_name = "lims.analysis" | ||
_description = "Analysis" | ||
_check_company_auto = True | ||
|
||
identifier = fields.Char(required=True, default="/", readonly=True) | ||
sample_id = fields.Many2one("lims.sample", required=True) | ||
company_id = fields.Many2one( | ||
"res.company", related="sample_id.company_id", store=True | ||
) | ||
state = fields.Selection( | ||
[ | ||
("registered", "Registered"), | ||
("to_analyze", "To Analyze"), | ||
("to_be_verified", "To be verified"), | ||
("verified", "Verified"), | ||
("rejected", "Rejected"), | ||
], | ||
required=True, | ||
default="registered", | ||
readonly=True, | ||
) | ||
product_id = fields.Many2one( | ||
"product.product", | ||
required=True, | ||
domain=[("laboratory_ok", "=", True)], | ||
readonly=True, | ||
states={"registered": [("readonly", False)]}, | ||
) | ||
name = fields.Char( | ||
required=True, | ||
readonly=True, | ||
states={"registered": [("readonly", False)]}, | ||
) | ||
analyst_id = fields.Many2one("res.users", readonly=True) | ||
capture_date = fields.Datetime(readonly=True) | ||
submitted_date = fields.Datetime() | ||
verified_by = fields.Many2one("res.users", readonly=True) | ||
due_date = fields.Datetime(readonly=True) | ||
verification_date = fields.Datetime(readonly=True) | ||
uom_id = fields.Many2one( | ||
"uom.uom", | ||
readonly=True, | ||
states={"registered": [("readonly", False)]}, | ||
) | ||
progress = fields.Float(compute="_compute_progress", store=True) | ||
can_verify = fields.Boolean(compute="_compute_can_verify") | ||
value = fields.Char( | ||
readonly=True, | ||
states={"to_analyze": [("readonly", False)]}, | ||
) | ||
# TODO: Replace this for something better. isn't it? | ||
|
||
_sql_constraints = [ | ||
( | ||
"identifier_unique", | ||
"unique(identifier, company_id)", | ||
"Sample identifier must be unique", | ||
) | ||
] | ||
|
||
@api.onchange("product_id") | ||
def _onchange_product(self): | ||
for record in self: | ||
if not record.product_id: | ||
continue | ||
record.name = record.product_id.name | ||
record.uom_id = record.product_id.laboratory_uom_id | ||
|
||
@api.model_create_multi | ||
def create(self, mvals): | ||
for vals in mvals: | ||
if vals.get("identifier", "/") == "/": | ||
vals["identifier"] = self._get_identifier(vals) | ||
return super().create(mvals) | ||
|
||
def _get_identifier(self, vals): | ||
return ( | ||
self.env["ir.sequence"] | ||
.with_context(force_company=vals.get("company_id", self.env.company.id)) | ||
.next_by_code("lims.analysis") | ||
or "/" | ||
) | ||
|
||
@api.model | ||
def _add_missing_default_values(self, values): | ||
defaults = super()._add_missing_default_values(values) | ||
product = self.env["product.product"].browse(defaults["product_id"]) | ||
if "uom_id" not in values: | ||
defaults["uom_id"] = product.laboratory_uom_id.id | ||
if values.get("name"): | ||
defaults["name"] = product.name | ||
return defaults | ||
|
||
def _receive_sample(self): | ||
for record in self: | ||
record.write(record._receive_sample_vals()) | ||
|
||
def _receive_sample_vals(self): | ||
return { | ||
"state": "to_analyze", | ||
} | ||
|
||
def analyze_action(self): | ||
if not self.env.user.has_group("lims.group_lims_analyst"): | ||
raise AccessDenied(_("You are not allowed to analyze this")) | ||
for record in self.filtered(lambda r: r.state == "to_analyze"): | ||
record.write(record._analyze_action_vals()) | ||
self.mapped("sample_id").check_to_verify() | ||
|
||
def _analyze_action_vals(self): | ||
return { | ||
"state": "to_be_verified", | ||
"analyst_id": self.env.user.id, | ||
"submitted_date": fields.Datetime.now(), | ||
} | ||
|
||
def verify_action(self): | ||
if not self.env.user.has_group("lims.group_lims_verifier"): | ||
raise AccessDenied(_("You are not allowed to verify an analysis")) | ||
for record in self.filtered(lambda r: r.can_verify): | ||
record.write(record._verify_action_vals()) | ||
self.mapped("sample_id").check_verify() | ||
|
||
def _verify_action_vals(self): | ||
return { | ||
"state": "verified", | ||
"verified_by": self.env.user.id, | ||
"verification_date": fields.Datetime.now(), | ||
} | ||
|
||
@api.depends("state") | ||
def _compute_progress(self): | ||
for record in self: | ||
record.progress = record._get_progress() | ||
|
||
def final_states(self): | ||
return ["verified"] | ||
|
||
def _get_progress(self): | ||
if self.state in self.final_states(): | ||
return 100 | ||
if self.state == "to_be_verified": | ||
return 50 | ||
return 0 | ||
|
||
@api.depends_context("uid") | ||
@api.depends("state", "analyst_id") | ||
def _compute_can_verify(self): | ||
verify_param = int( | ||
self.env["ir.config_parameter"] | ||
.sudo() | ||
.get_param("lims.unforce_double_verification_manager"), | ||
) and self.env.user.has_group("lims.group_lims_manager") | ||
for record in self: | ||
record.can_verify = record.state == "to_be_verified" and ( | ||
verify_param or record.analyst_id != self.env.user | ||
) | ||
|
||
def retract_action(self): | ||
if not self.env.user.has_group("lims.group_lims_verifier"): | ||
raise AccessDenied( | ||
_("You are not allowed to retract an analysis to be verified") | ||
) | ||
for record in self.filtered(lambda r: r.state == "to_be_verified"): | ||
record.write(record._retract_action_vals()) | ||
|
||
def _retract_action_vals(self): | ||
return { | ||
"state": "to_analyze", | ||
"analyst_id": False, | ||
"submitted_date": False, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Copyright 2023 Dixmit | ||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). | ||
|
||
from odoo import fields, models | ||
|
||
|
||
class LimsDepartment(models.Model): | ||
|
||
_name = "lims.department" | ||
_description = "Department" | ||
|
||
name = fields.Char(required=True) | ||
active = fields.Boolean(default=True) | ||
user_ids = fields.Many2many("res.users") |
Oops, something went wrong.