mirror of
https://github.com/inventree/InvenTree.git
synced 2026-11-10 02:47:49 +00:00
[bug] date import (#13225)
- Handle date values during data import - reported via sentry.io
This commit is contained in:
1 parent
8f668657b3
commit
2497dd5425
2 files changed
+49
-4
No files matched your search
@@ -2,7 +2,7 @@
|
||||
|
||||
import json
|
||||
from collections import OrderedDict
|
||||
from datetime import datetime
|
||||
from datetime import date, datetime
|
||||
from typing import Optional
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
@@ -859,23 +859,44 @@ class DataImportRow(models.Model):
|
||||
if commit:
|
||||
self.save()
|
||||
|
||||
def convert_date_field(self, value: str) -> Optional[str]:
|
||||
"""Convert an incoming date field to the correct format for the database."""
|
||||
def convert_date_field(self, value) -> Optional[str]:
|
||||
"""Convert an incoming date field to the correct format for the database.
|
||||
|
||||
The value may be a string (CSV / JSON import), or a native date / datetime
|
||||
object (Excel import via tablib/openpyxl returns date-formatted cells as
|
||||
datetime.datetime objects).
|
||||
"""
|
||||
if value in [None, '']:
|
||||
return None
|
||||
|
||||
# Native date / datetime objects (note: datetime is a subclass of date)
|
||||
if isinstance(value, date):
|
||||
return value.strftime('%Y-%m-%d')
|
||||
|
||||
value = str(value).strip()
|
||||
|
||||
if not value:
|
||||
return None
|
||||
|
||||
# Attempt conversion using accepted formats
|
||||
date_formats = ['%Y-%m-%d', '%d/%m/%Y', '%m/%d/%Y', '%Y/%m/%d']
|
||||
|
||||
for fmt in date_formats:
|
||||
try:
|
||||
dt = datetime.strptime(value.strip(), fmt)
|
||||
dt = datetime.strptime(value, fmt)
|
||||
|
||||
# If the date is valid, convert it to the standard format and return
|
||||
return dt.strftime('%Y-%m-%d')
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
# Full ISO-8601 datetime string - e.g. a native datetime which has been
|
||||
# round-tripped through DjangoJSONEncoder when row_data was saved
|
||||
try:
|
||||
return datetime.fromisoformat(value).strftime('%Y-%m-%d')
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# If none of the formats matched, return the original value
|
||||
return value
|
||||
|
||||
|
||||
@@ -143,6 +143,30 @@ class ImporterTest(ImporterMixin, InvenTreeTestCase):
|
||||
row = DataImportRow.objects.get(session=session, row_index=0)
|
||||
self.assertEqual(row.row_data['COMMENT'], '2024-05-01T12:30:00')
|
||||
|
||||
def test_convert_date_field(self):
|
||||
"""Test conversion of date values for import.
|
||||
|
||||
Regression test for a Sentry crash: "'datetime.datetime' object has no
|
||||
attribute 'strip'". Excel imports provide date cells as native datetime
|
||||
objects, which convert_date_field() previously assumed to be strings.
|
||||
"""
|
||||
row = DataImportRow(row_index=0, row_data={})
|
||||
|
||||
for value, expected in [
|
||||
(None, None),
|
||||
('', None),
|
||||
(' ', None),
|
||||
(datetime.datetime(2024, 5, 1, 12, 30), '2024-05-01'),
|
||||
(datetime.date(2024, 5, 1), '2024-05-01'),
|
||||
# Native datetime after round-trip through DjangoJSONEncoder
|
||||
('2024-05-01T12:30:00', '2024-05-01'),
|
||||
(' 2024-05-01 ', '2024-05-01'),
|
||||
('01/05/2024', '2024-05-01'),
|
||||
('2024/05/01', '2024-05-01'),
|
||||
('not a date', 'not a date'),
|
||||
]:
|
||||
self.assertEqual(row.convert_date_field(value), expected, msg=value)
|
||||
|
||||
def test_import_header_whitespace(self):
|
||||
"""Test that column headers with leading/trailing whitespace are handled correctly.
|
||||
|
||||
|
||||
Reference in new issue
Block a user