forked from erp-dev/erp
feat: added print_count api, added merchant setting model, added manual mode setting for purchase order
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.2.7 on 2025-11-27 10:02
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('printing', '0017_alter_plateorder_image_name'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='plateorder',
|
||||
name='plate_image',
|
||||
field=models.JSONField(blank=True, default=dict, help_text='存储多个开版图片的路径,格式: {"image_1": "/path/to/image1.jpg", "image_2": "/path/to/image2.jpg"}', verbose_name='开版图集合'),
|
||||
),
|
||||
]
|
||||
69
printing/migrations/0019_alter_plateorder_plate_image.py
Normal file
69
printing/migrations/0019_alter_plateorder_plate_image.py
Normal file
@@ -0,0 +1,69 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def _build_entry(value, name_hint=''):
|
||||
if not value:
|
||||
return None
|
||||
if isinstance(value, dict):
|
||||
entry = {}
|
||||
entry.update(value)
|
||||
# Ensure keys exist
|
||||
entry.setdefault('name', name_hint or entry.get('name') or '')
|
||||
if 'url' not in entry and 'path' in entry:
|
||||
entry['url'] = entry['path']
|
||||
elif 'path' not in entry and 'url' in entry:
|
||||
entry['path'] = entry['url']
|
||||
return entry
|
||||
if isinstance(value, str):
|
||||
return {
|
||||
'name': name_hint or value.split('/')[-1],
|
||||
'path': value,
|
||||
'url': value,
|
||||
}
|
||||
return None
|
||||
|
||||
|
||||
def forwards(apps, schema_editor):
|
||||
PlateOrder = apps.get_model('printing', 'PlateOrder')
|
||||
for obj in PlateOrder.objects.all():
|
||||
raw = obj.plate_image
|
||||
if not raw:
|
||||
obj.plate_image = []
|
||||
obj.save(update_fields=['plate_image'])
|
||||
continue
|
||||
|
||||
normalized = []
|
||||
if isinstance(raw, list):
|
||||
for entry in raw:
|
||||
built = _build_entry(entry)
|
||||
if built:
|
||||
normalized.append(built)
|
||||
elif isinstance(raw, dict):
|
||||
for key, value in raw.items():
|
||||
built = _build_entry(value, name_hint=str(key))
|
||||
if built:
|
||||
normalized.append(built)
|
||||
else:
|
||||
built = _build_entry(raw)
|
||||
if built:
|
||||
normalized.append(built)
|
||||
|
||||
obj.plate_image = normalized
|
||||
obj.save(update_fields=['plate_image'])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('printing', '0018_plateorder_plate_image_to_jsonfield'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='plateorder',
|
||||
name='plate_image',
|
||||
field=models.JSONField(blank=True, default=list, help_text='存储多个开版图片引用信息,例如 [{"file_id": 1, "name": "封面", "path": "/media/xxx"}]', verbose_name='开版图'),
|
||||
),
|
||||
migrations.RunPython(forwards, migrations.RunPython.noop),
|
||||
]
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.2.7 on 2025-11-28 02:57
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('printing', '0019_alter_plateorder_plate_image'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='plateorder',
|
||||
name='required_completion_date',
|
||||
field=models.DateTimeField(blank=True, null=True, verbose_name='要求完成时间'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.2.7 on 2025-11-28 03:29
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('printing', '0020_alter_plateorder_required_completion_date'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='plateorder',
|
||||
name='print_count',
|
||||
field=models.PositiveIntegerField(default=0, verbose_name='打印次数'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='printingorder',
|
||||
name='print_count',
|
||||
field=models.PositiveIntegerField(default=0, verbose_name='打印次数'),
|
||||
),
|
||||
]
|
||||
@@ -1,5 +1,5 @@
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from flower.common import ModelBase
|
||||
from basic_info import models as basic_models
|
||||
from stateflow import models as stateflow_models
|
||||
@@ -15,7 +15,12 @@ class PlateOrder(ModelBase):
|
||||
plate_type = models.CharField(max_length=20, blank=True, null=True, verbose_name='起版情况') # 首版/复版等
|
||||
plate_date = models.DateTimeField(null=True, blank=True, verbose_name='下版时间')
|
||||
plate_method = models.CharField(max_length=50, blank=True, null=True, verbose_name='开版方式')
|
||||
plate_image = models.FileField(upload_to='plate_images/', null=True, blank=True, verbose_name='开版图')
|
||||
plate_image = models.JSONField(
|
||||
default=list,
|
||||
blank=True,
|
||||
verbose_name='开版图',
|
||||
help_text='存储多个开版图片引用信息,例如 [{"file_id": 1, "name": "封面", "path": "/media/xxx"}]'
|
||||
)
|
||||
image_name = models.TextField(blank=True, null=True, verbose_name='图片名称')
|
||||
plate_notes = models.TextField(blank=True, null=True, verbose_name='打版注意事项')
|
||||
reprint_reason = models.TextField(blank=True, null=True, verbose_name='复版原因')
|
||||
@@ -68,7 +73,7 @@ class PlateOrder(ModelBase):
|
||||
difficulty_rating = models.CharField(max_length=20, blank=True, null=True, verbose_name='难度评级')
|
||||
|
||||
# 时间相关
|
||||
required_completion_date = models.DateField(null=True, blank=True, verbose_name='要求完成时间')
|
||||
required_completion_date = models.DateTimeField(null=True, blank=True, verbose_name='要求完成时间')
|
||||
completion_date = models.DateTimeField(null=True, blank=True, verbose_name='完成时间')
|
||||
|
||||
# 产品信息
|
||||
@@ -95,6 +100,7 @@ class PlateOrder(ModelBase):
|
||||
is_ordered = models.BooleanField(default=False, verbose_name='是否已下单')
|
||||
is_invalid = models.BooleanField(default=False, verbose_name='是否作废')
|
||||
customer_feedback = models.TextField(blank=True, null=True, verbose_name='客户修改意见')
|
||||
print_count = models.PositiveIntegerField(default=0, verbose_name='打印次数')
|
||||
|
||||
# 流程管理
|
||||
process = models.IntegerField(default=settings.PLATE_ORDER_DEFAULT_PROCESS_ID, verbose_name='关联流程')
|
||||
@@ -228,6 +234,7 @@ class PrintingOrder(ModelBase):
|
||||
printing_warn = models.TextField(blank=True, null=True, verbose_name='打印注意事项')
|
||||
rolling_warn = models.TextField(blank=True, null=True, verbose_name='滚筒注意事项')
|
||||
production_warn = models.TextField(blank=True, null=True, verbose_name='生产注意事项')
|
||||
print_count = models.PositiveIntegerField(default=0, verbose_name='打印次数')
|
||||
is_invalid = models.BooleanField(default=False, verbose_name='是否作废')
|
||||
process = models.ForeignKey(
|
||||
stateflow_models.Process,
|
||||
|
||||
@@ -414,12 +414,12 @@ paths:
|
||||
description: 开版日期结束。
|
||||
- in: query
|
||||
name: required_completion_date_from
|
||||
schema: {type: string, format: date}
|
||||
description: 要求完成日期起始。
|
||||
schema: {type: string, format: date-time}
|
||||
description: 要求完成时间起始(ISO8601)。
|
||||
- in: query
|
||||
name: required_completion_date_to
|
||||
schema: {type: string, format: date}
|
||||
description: 要求完成日期结束。
|
||||
schema: {type: string, format: date-time}
|
||||
description: 要求完成时间结束(ISO8601)。
|
||||
- in: query
|
||||
name: created_date_from
|
||||
schema: {type: string, format: date}
|
||||
@@ -713,10 +713,11 @@ components:
|
||||
type: string
|
||||
description: 开版方式。
|
||||
plate_image:
|
||||
type: string
|
||||
format: binary
|
||||
type: array
|
||||
nullable: true
|
||||
description: 开版图片(仅 multipart/form-data 时可上传)。
|
||||
description: 已上传开版图片引用列表(先调用 /api/v1/upload/ 获取 file_id)
|
||||
items:
|
||||
$ref: '#/components/schemas/PlateImageInput'
|
||||
image_name:
|
||||
type: string
|
||||
nullable: true
|
||||
@@ -784,9 +785,9 @@ components:
|
||||
description: 客户要求的米样米数。
|
||||
required_completion_date:
|
||||
type: string
|
||||
format: date
|
||||
format: date-time
|
||||
nullable: true
|
||||
description: 要求完成日期。
|
||||
description: 要求完成时间(含具体时刻)。
|
||||
completion_date:
|
||||
type: string
|
||||
format: date-time
|
||||
@@ -806,6 +807,49 @@ components:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: 关联流程 ID,缺省时采用 settings.PLATE_ORDER_DEFAULT_PROCESS_ID。
|
||||
PlateImageInput:
|
||||
type: object
|
||||
required: [file_id]
|
||||
properties:
|
||||
file_id:
|
||||
type: integer
|
||||
description: 上传文件的 ID(来自 `/api/v1/upload/`)
|
||||
name:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 可选名称,默认使用文件原始名称
|
||||
PlateImageItem:
|
||||
type: object
|
||||
properties:
|
||||
file_id:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: 上传文件 ID,若为外部链接可为空
|
||||
name:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 图片名称或备注
|
||||
url:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 图片可访问 URL
|
||||
path:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 图片相对路径
|
||||
size:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: 文件大小(字节)
|
||||
content_type:
|
||||
type: string
|
||||
nullable: true
|
||||
description: 文件内容类型
|
||||
uploaded_at:
|
||||
type: string
|
||||
format: date-time
|
||||
nullable: true
|
||||
description: 上传时间
|
||||
StateAdvanceRequest:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -102,7 +102,7 @@ class PlateOrderModelTestCase(TestCase):
|
||||
"""测试带时间信息的开版订单"""
|
||||
now = timezone.now()
|
||||
completion_date = now + timezone.timedelta(days=7)
|
||||
required_date = (now + timezone.timedelta(days=10)).date()
|
||||
required_date = now + timezone.timedelta(days=10)
|
||||
|
||||
plate_order = printing_models.PlateOrder.objects.create(
|
||||
design_code='DES004',
|
||||
|
||||
Reference in New Issue
Block a user