Skip to content

Commit ec8da09

Browse files
author
John75SunCity
committed
fix: Remove SQL constraints on code length, gracefully handle existing data
- Removed SQL constraint 'code_length_check' from records.department - Softened Python validation to auto-clean codes (no length enforcement) - Updated customer_code_display to handle any length (takes first 4 chars) - Portal barcode generation now uses re.sub to sanitize all codes - Codes are recommended to be 4 chars but existing data is handled gracefully
1 parent a1cbcc2 commit ec8da09

File tree

3 files changed

+36
-33
lines changed

3 files changed

+36
-33
lines changed

records_management/controllers/portal.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2575,11 +2575,13 @@ def portal_container_create(self, **post):
25752575
import re
25762576

25772577
# Get 4-char company code (prefer customer_code field, fallback to ref)
2578-
if partner.customer_code and len(partner.customer_code) == 4:
2579-
company_code = partner.customer_code.upper()
2578+
# Always take first 4 alphanumeric chars and pad if needed
2579+
if partner.customer_code:
2580+
company_code = re.sub(r'[^A-Za-z0-9]', '', partner.customer_code).upper()[:4].ljust(4, '0')
2581+
elif partner.ref:
2582+
company_code = re.sub(r'[^A-Za-z0-9]', '', partner.ref).upper()[:4].ljust(4, '0')
25802583
else:
2581-
raw_company_ref = partner.ref or 'CUST'
2582-
company_code = re.sub(r'[^A-Za-z0-9]', '', raw_company_ref).upper()[:4].ljust(4, '0')
2584+
company_code = 'CUST'
25832585

25842586
# Build barcode prefix based on department hierarchy
25852587
barcode_prefix = f'TMP-{company_code}'
@@ -2591,15 +2593,17 @@ def portal_container_create(self, **post):
25912593
if department_id:
25922594
department = request.env['records.department'].sudo().browse(int(department_id))
25932595
if department.exists():
2594-
# Get 4-char department code (should already be validated as 4 chars)
2595-
dept_code = (department.code or 'DEPT').upper()[:4].ljust(4, '0')
2596+
# Get 4-char department code (take first 4 chars, pad if needed)
2597+
raw_code = department.code or 'DEPT'
2598+
dept_code = re.sub(r'[^A-Za-z0-9]', '', raw_code).upper()[:4].ljust(4, '0')
25962599
barcode_prefix += f'-{dept_code}'
25972600

25982601
# Check if this department has a parent (making it a child dept)
25992602
if department.parent_department_id:
26002603
# This IS a child department - get parent code too
26012604
parent_dept = department.parent_department_id
2602-
parent_code = (parent_dept.code or 'PRNT').upper()[:4].ljust(4, '0')
2605+
raw_parent = parent_dept.code or 'PRNT'
2606+
parent_code = re.sub(r'[^A-Za-z0-9]', '', raw_parent).upper()[:4].ljust(4, '0')
26032607
# Rebuild prefix: TMP-COMPANY-PARENT-CHILD
26042608
barcode_prefix = f'TMP-{company_code}-{parent_code}-{dept_code}'
26052609

records_management/models/records_department.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -89,29 +89,27 @@ class RecordsDepartment(models.Model):
8989
('name_company_uniq', 'unique(name, company_id)', 'Department name must be unique per company.'),
9090
('code_company_uniq', 'unique(code, company_id)', 'Department code must be unique per company.'),
9191
('name_partner_uniq', 'UNIQUE(name, partner_id, company_id)', 'The department name must be unique per customer.'),
92-
('code_length_check', 'CHECK(LENGTH(code) = 4)', 'Department code must be exactly 4 characters.'),
92+
# NOTE: No length constraint - we recommend 4 chars but gracefully handle existing data
9393
]
9494

9595
# ============================================================================
9696
# VALIDATION
9797
# ============================================================================
9898
@api.constrains('code')
9999
def _check_code_format(self):
100-
"""Ensure department code is exactly 4 alphanumeric characters."""
100+
"""
101+
Normalize department code to uppercase alphanumeric.
102+
Recommends 4 characters but gracefully handles existing data by
103+
auto-truncating or padding to 4 chars for barcode generation.
104+
"""
101105
import re
102106
for dept in self:
103107
if dept.code:
104-
# Remove any non-alphanumeric and check length
105-
clean_code = re.sub(r'[^A-Za-z0-9]', '', dept.code)
106-
if len(clean_code) != 4:
107-
raise ValidationError(
108-
_("Department code must be exactly 4 alphanumeric characters.\n"
109-
"Examples: HR01, LGL1, FIN2, ACCT\n"
110-
"Current value: '%s' (%d chars)") % (dept.code, len(dept.code))
111-
)
112-
# Auto-uppercase and clean
113-
if dept.code != clean_code.upper():
114-
dept.code = clean_code.upper()
108+
# Remove any non-alphanumeric and uppercase
109+
clean_code = re.sub(r'[^A-Za-z0-9]', '', dept.code).upper()
110+
# Auto-fix: just clean and uppercase, don't enforce length
111+
if clean_code and dept.code != clean_code:
112+
dept.code = clean_code
115113

116114
# ============================================================================
117115
# COMPUTE METHODS

records_management/models/res_partner.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -299,11 +299,14 @@ def _compute_customer_code_display(self):
299299
"""
300300
Compute the 4-character code used in temp barcodes.
301301
Priority: customer_code > ref (sanitized) > 'CUST'
302+
Always returns exactly 4 characters (truncated or padded).
302303
"""
303304
import re
304305
for partner in self:
305-
if partner.customer_code and len(partner.customer_code) == 4:
306-
partner.customer_code_display = partner.customer_code.upper()
306+
if partner.customer_code:
307+
# Take first 4 alphanumeric chars, pad if needed
308+
clean_code = re.sub(r'[^A-Za-z0-9]', '', partner.customer_code).upper()[:4]
309+
partner.customer_code_display = clean_code.ljust(4, '0') if clean_code else 'CUST'
307310
elif partner.ref:
308311
# Sanitize ref to alphanumeric only, take first 4 chars
309312
clean_ref = re.sub(r'[^A-Za-z0-9]', '', partner.ref).upper()[:4]
@@ -313,20 +316,18 @@ def _compute_customer_code_display(self):
313316

314317
@api.constrains('customer_code')
315318
def _check_customer_code_format(self):
316-
"""Ensure customer code is exactly 4 alphanumeric characters if set."""
319+
"""
320+
Normalize customer code to uppercase alphanumeric.
321+
Recommends 4 characters but gracefully handles existing data.
322+
"""
317323
import re
318324
for partner in self:
319325
if partner.customer_code:
320-
clean_code = re.sub(r'[^A-Za-z0-9]', '', partner.customer_code)
321-
if len(clean_code) != 4:
322-
raise ValidationError(
323-
_("Customer Code must be exactly 4 alphanumeric characters.\\n"
324-
"Examples: 0915, CITY, PASO, ABC1\\n"
325-
"Current value: '%s' (%d chars)") % (partner.customer_code, len(partner.customer_code))
326-
)
327-
# Auto-uppercase and clean
328-
if partner.customer_code != clean_code.upper():
329-
partner.customer_code = clean_code.upper()
326+
# Remove any non-alphanumeric and uppercase
327+
clean_code = re.sub(r'[^A-Za-z0-9]', '', partner.customer_code).upper()
328+
# Auto-fix: just clean and uppercase, don't enforce length
329+
if clean_code and partner.customer_code != clean_code:
330+
partner.customer_code = clean_code
330331

331332
@api.depends('department_ids')
332333
def _compute_department_count(self):

0 commit comments

Comments
 (0)