mirror of
https://github.com/zhtyyx/ioe.git
synced 2026-06-03 21:02:59 +08:00
174 lines
6.2 KiB
Python
174 lines
6.2 KiB
Python
from django import forms
|
||
from django.core.validators import FileExtensionValidator
|
||
from inventory.models import Product, Category, Inventory
|
||
import csv
|
||
import io
|
||
|
||
class BatchProductImportForm(forms.Form):
|
||
"""
|
||
批量导入商品表单
|
||
"""
|
||
file = forms.FileField(
|
||
label='CSV文件',
|
||
validators=[FileExtensionValidator(allowed_extensions=['csv'])],
|
||
help_text='请上传CSV格式文件,包含商品信息',
|
||
widget=forms.FileInput(attrs={'class': 'form-control'})
|
||
)
|
||
|
||
category = forms.ModelChoiceField(
|
||
queryset=Category.objects.all(),
|
||
label='默认分类',
|
||
required=False,
|
||
help_text='如果CSV中未指定分类,将使用此分类',
|
||
widget=forms.Select(attrs={'class': 'form-control form-select'})
|
||
)
|
||
|
||
update_existing = forms.BooleanField(
|
||
label='更新已存在商品',
|
||
required=False,
|
||
initial=False,
|
||
help_text='如果勾选,将更新已存在的商品信息',
|
||
widget=forms.CheckboxInput(attrs={'class': 'form-check-input'})
|
||
)
|
||
|
||
def clean_file(self):
|
||
file = self.cleaned_data.get('file')
|
||
if file:
|
||
# 检查CSV文件格式
|
||
try:
|
||
# 读取CSV文件
|
||
csv_file = file.read().decode('utf-8')
|
||
csv_data = csv.reader(io.StringIO(csv_file))
|
||
|
||
# 获取表头
|
||
headers = next(csv_data)
|
||
|
||
# 检查必要的列是否存在
|
||
required_columns = ['barcode', 'name', 'price', 'cost']
|
||
missing_columns = [col for col in required_columns if col not in headers]
|
||
|
||
if missing_columns:
|
||
raise forms.ValidationError(f"CSV文件缺少必要的列: {', '.join(missing_columns)}")
|
||
|
||
# 重置文件指针
|
||
file.seek(0)
|
||
|
||
except Exception as e:
|
||
raise forms.ValidationError(f"CSV文件格式错误: {str(e)}")
|
||
|
||
return file
|
||
|
||
class BatchInventoryUpdateForm(forms.Form):
|
||
"""
|
||
批量调整库存表单
|
||
"""
|
||
file = forms.FileField(
|
||
label='CSV文件',
|
||
validators=[FileExtensionValidator(allowed_extensions=['csv'])],
|
||
help_text='请上传CSV格式文件,包含商品条码和库存数量',
|
||
widget=forms.FileInput(attrs={'class': 'form-control'})
|
||
)
|
||
|
||
adjustment_type = forms.ChoiceField(
|
||
label='调整类型',
|
||
choices=[
|
||
('set', '设置为指定数量'),
|
||
('add', '增加指定数量'),
|
||
('subtract', '减少指定数量'),
|
||
],
|
||
initial='set',
|
||
widget=forms.RadioSelect(attrs={'class': 'form-check-input'})
|
||
)
|
||
|
||
notes = forms.CharField(
|
||
label='备注',
|
||
required=False,
|
||
widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),
|
||
help_text='批量调整的原因或说明'
|
||
)
|
||
|
||
def clean_file(self):
|
||
file = self.cleaned_data.get('file')
|
||
if file:
|
||
try:
|
||
# 读取CSV文件
|
||
csv_file = file.read().decode('utf-8')
|
||
csv_data = csv.reader(io.StringIO(csv_file))
|
||
|
||
# 获取表头
|
||
headers = next(csv_data)
|
||
|
||
# 检查必要的列是否存在
|
||
required_columns = ['barcode', 'quantity']
|
||
missing_columns = [col for col in required_columns if col not in headers]
|
||
|
||
if missing_columns:
|
||
raise forms.ValidationError(f"CSV文件缺少必要的列: {', '.join(missing_columns)}")
|
||
|
||
# 检查数据有效性
|
||
row_number = 1 # 表头是第1行
|
||
errors = []
|
||
|
||
for row in csv_data:
|
||
row_number += 1
|
||
if len(row) != len(headers):
|
||
errors.append(f"第{row_number}行: 列数不匹配")
|
||
continue
|
||
|
||
# 创建行数据字典
|
||
row_data = dict(zip(headers, row))
|
||
|
||
# 检查条码是否存在
|
||
barcode = row_data.get('barcode', '').strip()
|
||
if not barcode:
|
||
errors.append(f"第{row_number}行: 条码不能为空")
|
||
|
||
# 检查数量是否为有效数字
|
||
quantity = row_data.get('quantity', '').strip()
|
||
try:
|
||
quantity = int(quantity)
|
||
if quantity < 0 and self.cleaned_data.get('adjustment_type') == 'set':
|
||
errors.append(f"第{row_number}行: 设置库存时数量不能为负数")
|
||
except ValueError:
|
||
errors.append(f"第{row_number}行: 数量必须是整数")
|
||
|
||
if errors:
|
||
raise forms.ValidationError(errors)
|
||
|
||
# 重置文件指针
|
||
file.seek(0)
|
||
|
||
except Exception as e:
|
||
if not isinstance(e, forms.ValidationError):
|
||
raise forms.ValidationError(f"CSV文件处理错误: {str(e)}")
|
||
raise
|
||
|
||
return file
|
||
|
||
class ProductBatchDeleteForm(forms.Form):
|
||
"""
|
||
批量删除商品表单
|
||
"""
|
||
product_ids = forms.CharField(
|
||
widget=forms.HiddenInput(),
|
||
required=True
|
||
)
|
||
|
||
confirm = forms.BooleanField(
|
||
label='确认删除',
|
||
required=True,
|
||
help_text='我已了解此操作不可逆,并确认要删除选中的商品'
|
||
)
|
||
|
||
def clean_product_ids(self):
|
||
product_ids_str = self.cleaned_data.get('product_ids')
|
||
if not product_ids_str:
|
||
raise forms.ValidationError('未选择任何商品')
|
||
|
||
try:
|
||
product_ids = [int(id.strip()) for id in product_ids_str.split(',') if id.strip()]
|
||
if not product_ids:
|
||
raise forms.ValidationError('未选择任何商品')
|
||
return product_ids
|
||
except ValueError:
|
||
raise forms.ValidationError('商品ID格式错误') |