From 0f89c64af5f89c896b35e04fda886975c76dda69 Mon Sep 17 00:00:00 2001 From: vigneshhari Date: Thu, 26 Feb 2026 13:29:38 +0530 Subject: [PATCH 1/2] Add print templates config in facility --- care/emr/resources/facility/spec.py | 61 ++++++++++++++++++- care/emr/resources/patient/spec.py | 1 + .../0482_facility_print_templates.py | 18 ++++++ care/facility/models/facility.py | 2 + 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 care/facility/migrations/0482_facility_print_templates.py diff --git a/care/emr/resources/facility/spec.py b/care/emr/resources/facility/spec.py index 5cb0db567c..a066f7b58b 100644 --- a/care/emr/resources/facility/spec.py +++ b/care/emr/resources/facility/spec.py @@ -1,6 +1,8 @@ +from typing import Literal + from django.conf import settings from django.db.models.functions import Lower, Trim -from pydantic import UUID4, BaseModel, field_validator, model_validator +from pydantic import UUID4, BaseModel, Field, field_validator, model_validator from pydantic_core.core_schema import ValidationInfo from pydantic_extra_types.coordinate import Latitude, Longitude @@ -28,6 +30,59 @@ class FacilityBareMinimumSpec(EMRResource): id: UUID4 | None = None name: str +class PageMargin(BaseModel): + top: float = Field(ge=0) + bottom: float = Field(ge=0) + left: float = Field(ge=0) + right: float = Field(ge=0) + + +class PageConfig(BaseModel): + size: Literal["A4", "A5", "Letter", "Legal"] | None = None + orientation: Literal["portrait", "landscape"] | None = None + margin: PageMargin | None = None + + +class PrintSetupConfig(BaseModel): + autoPrint: bool | None = None + + +class LogoConfig(BaseModel): + url: str + width: float | None = None + height: float | None = None + alignment: Literal["left", "center", "right"] + + +class HeaderImageConfig(BaseModel): + url: str + height: float | None = None + + +class FooterImageConfig(BaseModel): + url: str | None = None + height: float | None = None + + +class BrandingConfig(BaseModel): + logo: LogoConfig | None = None + headerImage: HeaderImageConfig | None = None + footerImage: FooterImageConfig | None = None + + +class WatermarkConfig(BaseModel): + enabled: bool | None = None + text: str | None = None + opacity: float | None = Field(None, ge=0, le=1) + rotation: float | None = None + + +class PrintTemplate(BaseModel): + page: PageConfig | None = None + printSetup: PrintSetupConfig | None = None + branding: BrandingConfig | None = None + watermark: WatermarkConfig | None = None + class FacilityBaseSpec(FacilityBareMinimumSpec): description: str @@ -40,7 +95,6 @@ class FacilityBaseSpec(FacilityBareMinimumSpec): facility_type: str is_public: bool - DISCOUNT_CODE_COUNT_LIMIT = 100 DISCOUNT_MONETARY_COMPONENT_COUNT_LIMIT = 100 @@ -63,6 +117,7 @@ def validate_invoice_number_expression(cls, v): class FacilityCreateSpec(FacilityBaseSpec): geo_organization: UUID4 features: list[int] + print_templates: list[PrintTemplate] = [] @field_validator("name") @classmethod @@ -137,6 +192,8 @@ class FacilityRetrieveSpec(FacilityReadSpec, FacilityPermissionsMixin): extensions_schema_supply_delivery_order: dict = {} extensions_schema_account: dict = {} + print_templates: list[dict] = [] + @classmethod def perform_extra_serialization(cls, mapping, obj): super().perform_extra_serialization(mapping, obj) diff --git a/care/emr/resources/patient/spec.py b/care/emr/resources/patient/spec.py index 955b639530..c9748215b8 100644 --- a/care/emr/resources/patient/spec.py +++ b/care/emr/resources/patient/spec.py @@ -217,6 +217,7 @@ class PatientListSpec(PatientBaseSpec): instance_tags: list[dict] = [] facility_tags: list[dict] = [] + @classmethod def perform_extra_serialization(cls, mapping, obj, *args, **kwargs): mapping["id"] = obj.external_id diff --git a/care/facility/migrations/0482_facility_print_templates.py b/care/facility/migrations/0482_facility_print_templates.py new file mode 100644 index 0000000000..ca06873ef4 --- /dev/null +++ b/care/facility/migrations/0482_facility_print_templates.py @@ -0,0 +1,18 @@ +# Generated by Django 6.0 on 2026-02-26 07:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('facility', '0481_delete_asset_delete_assetbed_delete_bed_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='facility', + name='print_templates', + field=models.JSONField(default=dict), + ), + ] diff --git a/care/facility/models/facility.py b/care/facility/models/facility.py index 38ae713cc3..94955e4ac1 100644 --- a/care/facility/models/facility.py +++ b/care/facility/models/facility.py @@ -216,6 +216,8 @@ class Facility(BaseModel): max_length=1000, blank=True, null=True, default=None ) + print_templates = models.JSONField(default=dict) + class Meta: verbose_name_plural = "Facilities" From b45422f8f20133af79cbf802a5d2ab5fd42a93d5 Mon Sep 17 00:00:00 2001 From: vigneshhari Date: Thu, 26 Feb 2026 14:21:02 +0530 Subject: [PATCH 2/2] Add slug for print template, Fix linting --- care/emr/resources/facility/spec.py | 11 +++++++---- care/emr/resources/patient/spec.py | 1 - 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/care/emr/resources/facility/spec.py b/care/emr/resources/facility/spec.py index a066f7b58b..0e620d797c 100644 --- a/care/emr/resources/facility/spec.py +++ b/care/emr/resources/facility/spec.py @@ -30,6 +30,7 @@ class FacilityBareMinimumSpec(EMRResource): id: UUID4 | None = None name: str + class PageMargin(BaseModel): top: float = Field(ge=0) bottom: float = Field(ge=0) @@ -44,7 +45,7 @@ class PageConfig(BaseModel): class PrintSetupConfig(BaseModel): - autoPrint: bool | None = None + auto_print: bool | None = None class LogoConfig(BaseModel): @@ -66,8 +67,8 @@ class FooterImageConfig(BaseModel): class BrandingConfig(BaseModel): logo: LogoConfig | None = None - headerImage: HeaderImageConfig | None = None - footerImage: FooterImageConfig | None = None + header_image: HeaderImageConfig | None = None + footer_image: FooterImageConfig | None = None class WatermarkConfig(BaseModel): @@ -78,8 +79,9 @@ class WatermarkConfig(BaseModel): class PrintTemplate(BaseModel): + slug: str page: PageConfig | None = None - printSetup: PrintSetupConfig | None = None + print_setup: PrintSetupConfig | None = None branding: BrandingConfig | None = None watermark: WatermarkConfig | None = None @@ -95,6 +97,7 @@ class FacilityBaseSpec(FacilityBareMinimumSpec): facility_type: str is_public: bool + DISCOUNT_CODE_COUNT_LIMIT = 100 DISCOUNT_MONETARY_COMPONENT_COUNT_LIMIT = 100 diff --git a/care/emr/resources/patient/spec.py b/care/emr/resources/patient/spec.py index c9748215b8..955b639530 100644 --- a/care/emr/resources/patient/spec.py +++ b/care/emr/resources/patient/spec.py @@ -217,7 +217,6 @@ class PatientListSpec(PatientBaseSpec): instance_tags: list[dict] = [] facility_tags: list[dict] = [] - @classmethod def perform_extra_serialization(cls, mapping, obj, *args, **kwargs): mapping["id"] = obj.external_id