🔍 Code Extractor

class Delivery_documents

Maturity: 50

A class that generates delivery documentation (slip and label) as Word documents by querying a Neo4j database for study and customer information and populating predefined templates.

File:
/tf/active/vicechatdev/resources/documents.py
Lines:
15 - 147
Complexity:
complex

Purpose

This class automates the creation of delivery documentation for laboratory studies. It connects to a Neo4j graph database to retrieve study, customer, site, and organ sample information, then generates two Word documents: a detailed delivery slip listing all samples and a delivery label with barcode. The documents are created in-memory as BytesIO objects for immediate use or download without writing to disk.

Source Code

class Delivery_documents():
    """
    Creates a Delivery Slip and Delivery Label Word document using templates
    
    Parameters
    ----------
    site : str
        The site the delivery is to be made to
    study : str
        A string of the study UID
        
    See Also
    --------
    docxtpl
    """
    def __init__(self, study, site='Diepenbeek'):
        self.graph = Graph(config.DB_ADDR, auth=config.DB_AUTH, name=config.DB_NAME)
        self.study_uid = study
        self.site = self.graph.run(f"MATCH (s:Site {{N:'{site}'}}) RETURN s").evaluate()
        self.grab_data()
        self.generate_slip()
        self.generate_label()
        
        
    def address_to_string(self, address):
        return f"{address['Street']} {address['Number']}\n\t\t\t{address['ZIP']}, {address['City']}\n\t\t\t{address['Country']}"
        
    def grab_data(self):
        """
        Gather the user and study data to populate the word templates
        """
        self.study = self.graph.run(f"MATCH (s:Study {{UID:'{self.study_uid}'}}) return s").evaluate()
        self.customer = self.graph.run(f"MATCH (c:Customer)-->(:Study {{UID:'{self.study_uid}'}}) RETURN c").evaluate()
        df = self.graph.run(f"""
        MATCH (:Study {{UID:'{self.study_uid}'}})-->(g:Group)-->(e:ExpItem)-->(o:Organ)
        WITH o, g.N as Group, e.N as Sample, o.N as Organ, o.Alias as Alias, o.external_N as ID
        ORDER BY Sample, (CASE WHEN EXISTS(o.Order) THEN o.Order ELSE Organ END)
        RETURN Group, Sample, Organ, ID, Alias""").to_data_frame()
        df = df.dropna(axis=1, how='all') #drops Alias column of its completely empty
        self.df = df.fillna('') #replaces ugly 'NaN' without beautiful empty rows
            
        
    def generate_slip(self):
        """
        Populates the delivery slip template file, creates a virtual word document.
        
        Attributes
        ----------
        slip : io.BytesIO
            Virtual Word document containing the delivery slip
        """
        delivery_slip = DocxTemplate('./templates/Delivery_slip_tpl.docx')
        contact_dict = json.loads(self.study['Contact'])
        name=contact_dict['Name']
        mail=contact_dict['Mail']
        number=contact_dict['Number']
        site_address_dict = json.loads(self.site['Address'])
        site_address = self.address_to_string(site_address_dict)
        address_dict = json.loads(self.customer['Address'])
        address = self.address_to_string(address_dict)
        int_study = self.study['N']
        ext_study = self.study['external_N']
        #comprehension makes a list of dictionaries, where each dictionary has 2 keys, one for organ type one for count. 
        # table_content = [dict(zip(('organ','count'), i)) for i in self.data['Organ'].value_counts().items()]
        # self.df.sort_values(by=['group','sample'], inplace=True)
        print(self.df.columns)
        if 'Alias' in self.df.columns:
            table_content = [dict(zip(('group','sample','organ','id','alias'), i)) for _, i in self.df.iterrows()]
            alias = True
        else:
            table_content = [dict(zip(('group','sample','organ','id'), i)) for _, i in self.df.iterrows()]
            alias = False
        context = {
            'ext_study':ext_study,
            'int_study':int_study,
            'site_address':site_address,
            'name':name,
            'Alias':alias,
            'tbl_contents': table_content,
            'address': address,
            'contact':name,
            'mail':mail,
            'number':number,
            'recv_location':f"{site_address_dict['Street']} {site_address_dict['Number']}",
            'send_party':name,
            'send_location': address_dict['City']
        }
        delivery_slip.render(context)
        self.slip = io.BytesIO()
        delivery_slip.save(self.slip)
        self.slip.seek(0)
        
    def generate_label(self):
        """
        Populates the delivery label template file, creates a virtual word document.
        
        Attributes
        ----------
        label : io.BytesIO
            Virtual Word document of the delivery label
        """
        def uid2image(uid):
            encoded = encode(uid.encode('utf-8'))
            image = Image.frombytes('RGB', (encoded.width, encoded.height), encoded.pixels)
            return image
        def image2file(image):
            image_file = io.BytesIO()
            image.save(image_file, format="PNG")
            return image_file
        image = uid2image(self.study_uid)
        image_file = image2file(image)
        delivery_label = DocxTemplate('./templates/Delivery_label_tpl.docx')
        contact_dict = json.loads(self.study['Contact'])
        name=contact_dict['Name']
        mail=contact_dict['Mail']
        number=contact_dict['Number']
        site_address_dict = json.loads(self.site['Address'])
        site_address = self.address_to_string(site_address_dict)
        address_dict = json.loads(self.customer['Address'])
        address = self.address_to_string(address_dict)
        context = {
            'barcode': InlineImage(delivery_label, image_file),
            'site_address': site_address,
            'name':name,
            'address': address,
            'contact':name,
            'mail':mail,
            'number':number,
        }
        delivery_label.render(context)
        self.label = io.BytesIO()
        delivery_label.save(self.label)
        self.label.seek(0)

Parameters

Name Type Default Kind
bases - -

Parameter Details

study: The unique identifier (UID) string for the study. This is used to query the Neo4j database for all related study information, customer details, and sample/organ data.

site: The name of the delivery site location. Defaults to 'Diepenbeek'. This is used to query the database for the site's address information that will appear on the delivery documents.

Return Value

The constructor returns an instance of Delivery_documents with two main attributes: 'slip' (io.BytesIO object containing the delivery slip Word document) and 'label' (io.BytesIO object containing the delivery label Word document). Both documents are ready to be saved to disk or sent as file downloads.

Class Interface

Methods

__init__(self, study: str, site: str = 'Diepenbeek') -> None

Purpose: Initializes the class, connects to Neo4j database, retrieves all necessary data, and automatically generates both delivery slip and label documents

Parameters:

  • study: The unique identifier (UID) string for the study
  • site: The name of the delivery site location (defaults to 'Diepenbeek')

Returns: None - sets up instance with slip and label attributes

address_to_string(self, address: dict) -> str

Purpose: Converts an address dictionary to a formatted multi-line string suitable for document display

Parameters:

  • address: Dictionary containing address fields: 'Street', 'Number', 'ZIP', 'City', 'Country'

Returns: Formatted string with address components separated by newlines and tabs

grab_data(self) -> None

Purpose: Queries the Neo4j database to retrieve study, customer, and organ/sample data, storing results in instance attributes

Returns: None - populates self.study, self.customer, and self.df attributes

generate_slip(self) -> None

Purpose: Generates the delivery slip Word document by populating the template with study and sample data

Returns: None - creates self.slip attribute as io.BytesIO containing the Word document

generate_label(self) -> None

Purpose: Generates the delivery label Word document with barcode by populating the template with study contact and address information

Returns: None - creates self.label attribute as io.BytesIO containing the Word document

Attributes

Name Type Description Scope
graph Graph Neo4j database connection object used for querying study, customer, and site data instance
study_uid str The unique identifier for the study being processed instance
site Node Neo4j node object containing site information including address instance
study Node Neo4j node object containing study information including internal/external study numbers and contact details instance
customer Node Neo4j node object containing customer information including address instance
df pandas.DataFrame DataFrame containing organized sample/organ data with columns: Group, Sample, Organ, ID, and optionally Alias instance
slip io.BytesIO In-memory Word document containing the generated delivery slip, ready for reading or saving instance
label io.BytesIO In-memory Word document containing the generated delivery label with barcode, ready for reading or saving instance

Dependencies

  • neo4j_driver
  • config
  • docx
  • pylibdmtx
  • docxtpl
  • PIL
  • plotly
  • json
  • io
  • datetime

Required Imports

from neo4j_driver import *
import config
from docx import Document
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.shared import RGBColor, Pt, Length, Inches, Cm
from docx.enum.table import WD_ROW_HEIGHT_RULE
from pylibdmtx.pylibdmtx import decode, encode
from docxtpl import DocxTemplate, InlineImage
from PIL import Image
import plotly.express as px
import json
import io
import datetime as dt

Usage Example

# Ensure config.py has DB_ADDR, DB_AUTH, DB_NAME defined
# Ensure template files exist in ./templates/ directory

# Create delivery documents for a study
delivery_docs = Delivery_documents(study='STUDY-12345-UID', site='Diepenbeek')

# Save the delivery slip to a file
with open('delivery_slip.docx', 'wb') as f:
    f.write(delivery_docs.slip.read())

# Save the delivery label to a file
with open('delivery_label.docx', 'wb') as f:
    f.write(delivery_docs.label.read())

# Or use in a web framework to send as download
# return send_file(delivery_docs.slip, as_attachment=True, download_name='slip.docx')

Best Practices

  • The class automatically generates both documents upon instantiation, so be aware that database queries and document generation happen immediately in __init__
  • The slip and label BytesIO objects have their file pointers at position 0 (via seek(0)), ready for reading
  • If you need to read the BytesIO objects multiple times, call seek(0) before each read operation
  • Ensure the Neo4j database connection is available and the database schema matches expected node types and properties
  • Template files must exist at the specified paths before instantiation or the class will fail
  • The class expects specific JSON structure in database fields (Contact, Address) - ensure data integrity
  • The generated documents are held in memory; for large-scale operations, consider memory management
  • The class does not provide methods to regenerate documents - create a new instance if you need fresh documents

Similar Components

AI-powered semantic similarity - components with related functionality:

  • class print_client 50.8% similar

    A class that generates formatted print messages for different types of laboratory objects (Parblock, Organ, Study, Slide, Reagent) by querying a Neo4j graph database and building a pipe-delimited message string.

    From: /tf/active/vicechatdev/resources/printclient.py
  • class Cassette_Printer 47.6% similar

    A class that generates and saves cassette label images for printing by writing cassette information to a shared folder monitored by a Windows virtual PC.

    From: /tf/active/vicechatdev/resources/printers.py
  • function create_document_version 46.4% similar

    Creates a new controlled document in a document management system with versioning, audit trails, and relationship management in a Neo4j graph database.

    From: /tf/active/vicechatdev/CDocs copy/controllers/document_controller.py
  • class Study_overview 45.7% similar

    A class that generates comprehensive study overview reports by querying a Neo4j graph database and producing Excel files with ID mappings, audit logs, and Gantt chart visualizations of study progress.

    From: /tf/active/vicechatdev/resources/documents.py
  • class DocumentTraining 45.6% similar

    A model class that manages training requirements and assignments for controlled documents, including enabling/disabling training, assigning training to users, and tracking training status.

    From: /tf/active/vicechatdev/CDocs/models/training.py
← Back to Browse