Skip to content
Open
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
56 changes: 56 additions & 0 deletions av_tools/av_tools/doctype/av_tools_settings/av_tools_settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@
"enable_trade_in",
"item_remaining_qty_section",
"enable_validate_item_remaining_qty",
"camera_capture_section",
"enable_camera_capture_override",
"camera_capture_column_break",
"camera_capture_ideal_width",
"camera_capture_ideal_height",
"camera_capture_min_width",
"camera_capture_min_height",
"parallel_approval_section",
"enable_multi_approval_document",
"approval_doctype"
Expand Down Expand Up @@ -173,6 +180,55 @@
"fieldname": "enable_validate_item_remaining_qty",
"fieldtype": "Check",
"label": "Enable Item Remaining Qty Validation"
},
{
"fieldname": "camera_capture_section",
"fieldtype": "Section Break",
"label": "Camera Capture"
},
{
"default": "0",
"description": "Improve browser camera capture by applying AV Tools camera constraints before a photo is taken.",
"fieldname": "enable_camera_capture_override",
"fieldtype": "Check",
"label": "Enable Camera Capture Override"
},
{
"depends_on": "eval:doc.enable_camera_capture_override == 1",
"fieldname": "camera_capture_column_break",
"fieldtype": "Column Break"
},
{
"default": "1920",
"depends_on": "eval:doc.enable_camera_capture_override == 1",
"description": "Preferred capture width requested from the browser camera stream.",
"fieldname": "camera_capture_ideal_width",
"fieldtype": "Int",
"label": "Ideal Width"
},
{
"default": "1080",
"depends_on": "eval:doc.enable_camera_capture_override == 1",
"description": "Preferred capture height requested from the browser camera stream.",
"fieldname": "camera_capture_ideal_height",
"fieldtype": "Int",
"label": "Ideal Height"
},
{
"default": "0",
"depends_on": "eval:doc.enable_camera_capture_override == 1",
"description": "Optional minimum width. Leave 0 to avoid enforcing a minimum width.",
"fieldname": "camera_capture_min_width",
"fieldtype": "Int",
"label": "Minimum Width"
},
{
"default": "0",
"depends_on": "eval:doc.enable_camera_capture_override == 1",
"description": "Optional minimum height. Leave 0 to avoid enforcing a minimum height.",
"fieldname": "camera_capture_min_height",
"fieldtype": "Int",
"label": "Minimum Height"
},
{
"fieldname": "parallel_approval_section",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import json
from contextlib import contextmanager
from typing import ClassVar
from unittest.mock import patch

import frappe
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
from erpnext.stock.get_item_details import get_item_details as original_get_item_details
from frappe.core.doctype.user.test_user import test_user
from frappe.tests.utils import FrappeTestCase

from av_tools.av_tools.doctype.av_tools_settings.av_tools_settings import AVToolsSettings
from av_tools.av_tools_hooks.capture import get_capture_settings
from av_tools.av_tools_hooks.generic_erp_behavior_overrides import (
close_or_unclose_purchase_orders,
get_item_details,
Expand All @@ -15,20 +20,24 @@
)
from av_tools.patches.v1_0.migrate_generic_erp_behavior_overrides import (
SETTINGS_DOCTYPE,
)
from av_tools.patches.v1_0.migrate_generic_erp_behavior_overrides import (
execute as migrate_generic_settings,
)
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
from erpnext.stock.get_item_details import get_item_details as original_get_item_details


class TestAVToolsSettings(AccountsTestMixin, FrappeTestCase):
settings_defaults = {
settings_defaults: ClassVar[dict[str, object]] = {
"allow_reopen_of_po_based_on_role": 0,
"role_to_reopen_po": "",
"allow_reopen_of_material_request_based_on_role": 0,
"role_to_reopen_material_request": "",
"override_sales_invoice_qty": 0,
"enable_camera_capture_override": 0,
"camera_capture_ideal_width": 1920,
"camera_capture_ideal_height": 1080,
"camera_capture_min_width": 0,
"camera_capture_min_height": 0,
}
test_company_name = "Rubis Technical Services Limited"
test_supplier_name = "AV Tools Test Supplier"
Expand Down Expand Up @@ -147,12 +156,15 @@ def test_patch_migrates_settings_idempotently(self):
"override_sales_invoice_qty": 1,
}

with patch(
"av_tools.patches.v1_0.migrate_generic_erp_behavior_overrides.source_settings_doctype_exists",
return_value=True,
), patch(
"av_tools.patches.v1_0.migrate_generic_erp_behavior_overrides.get_source_values",
return_value=expected_values,
with (
patch(
"av_tools.patches.v1_0.migrate_generic_erp_behavior_overrides.source_settings_doctype_exists",
return_value=True,
),
patch(
"av_tools.patches.v1_0.migrate_generic_erp_behavior_overrides.get_source_values",
return_value=expected_values,
),
):
migrate_generic_settings()
migrate_generic_settings()
Expand Down Expand Up @@ -324,3 +336,45 @@ def make_item_details_args(self):
"ignore_pricing_rule": 1,
"qty": 1,
}


class TestAVToolsCaptureSettings(FrappeTestCase):
settings_defaults: ClassVar[dict[str, object]] = {
"enable_camera_capture_override": 0,
"camera_capture_ideal_width": 1920,
"camera_capture_ideal_height": 1080,
"camera_capture_min_width": 0,
"camera_capture_min_height": 0,
}

def setUp(self):
frappe.set_user("Administrator")
self.set_settings()

def tearDown(self):
frappe.set_user("Administrator")
self.set_settings()
frappe.db.rollback()
super().tearDown()

def set_settings(self, **overrides):
values = {**self.settings_defaults, **overrides}
for fieldname, value in values.items():
frappe.db.set_single_value(SETTINGS_DOCTYPE, fieldname, value)

def test_get_capture_settings_uses_single_doctype_values(self):
self.set_settings(
enable_camera_capture_override=1,
camera_capture_ideal_width=2560,
camera_capture_ideal_height=1440,
camera_capture_min_width=1280,
camera_capture_min_height=720,
)

settings = get_capture_settings()

self.assertTrue(settings["enabled"])
self.assertEqual(settings["ideal_width"], 2560)
self.assertEqual(settings["ideal_height"], 1440)
self.assertEqual(settings["min_width"], 1280)
self.assertEqual(settings["min_height"], 720)
48 changes: 48 additions & 0 deletions av_tools/av_tools_hooks/capture.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import frappe
from frappe.utils import cint

SETTINGS_DOCTYPE = "AV Tools Settings"
DEFAULT_CAPTURE_SETTINGS = {
"enabled": False,
"ideal_width": 1920,
"ideal_height": 1080,
"min_width": 0,
"min_height": 0,
}


def _sanitize_positive_int(value, default=0):
value = cint(value)
if value > 0:
return value
return default


def _get_capture_settings():
settings = DEFAULT_CAPTURE_SETTINGS.copy()

try:
values = frappe.db.get_singles_dict(SETTINGS_DOCTYPE) or {}
except Exception:
return settings

settings["enabled"] = bool(cint(values.get("enable_camera_capture_override")))
settings["ideal_width"] = _sanitize_positive_int(
values.get("camera_capture_ideal_width"), DEFAULT_CAPTURE_SETTINGS["ideal_width"]
)
settings["ideal_height"] = _sanitize_positive_int(
values.get("camera_capture_ideal_height"), DEFAULT_CAPTURE_SETTINGS["ideal_height"]
)
settings["min_width"] = _sanitize_positive_int(
values.get("camera_capture_min_width"), DEFAULT_CAPTURE_SETTINGS["min_width"]
)
settings["min_height"] = _sanitize_positive_int(
values.get("camera_capture_min_height"), DEFAULT_CAPTURE_SETTINGS["min_height"]
)

return settings


@frappe.whitelist()
def get_capture_settings():
return _get_capture_settings()
1 change: 1 addition & 0 deletions av_tools/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"/assets/av_tools/js/financial_statements_override.js",
"/assets/av_tools/js/ai_assist.js",
"/assets/av_tools/js/parallel_approval.js",
"av_tools.bundle.js",
]
app_include_css = "/assets/av_tools/css/theme.css"

Expand Down
1 change: 1 addition & 0 deletions av_tools/public/av_tools.bundle.js
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
import "./js/financial_statements_override";
import "./js/capture_override";
Loading
Loading