1
0
forked from erp-dev/erp

feat: mission category

This commit is contained in:
2026-04-14 00:03:22 +08:00
parent 9512132bb9
commit 0167478a25
18 changed files with 852 additions and 354 deletions

View File

@@ -194,3 +194,33 @@ class VehicleTransportRecordAdmin(AdminBase):
list_display = ('driver_name', 'contact_number', 'delivery_date')
search_fields = ('driver_name', 'contact_number')
list_filter = ('vehicle_type',)
class TransportVehicleMaterialCapacityInline(admin.TabularInline):
model = models.TransportVehicleMaterialCapacity
extra = 0
fields = ('material_name', 'capacity')
@admin.register(models.TransportVehicle)
class TransportVehicleAdmin(AdminBase):
inlines = [TransportVehicleMaterialCapacityInline]
list_display = ('name', 'license_plate')
search_fields = ('name', 'license_plate')
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for obj in formset.deleted_objects:
obj.delete()
for instance in instances:
if isinstance(instance, models.TransportVehicleMaterialCapacity):
instance.merchant = form.instance.merchant
instance.save()
formset.save_m2m()
@admin.register(models.TransportVehicleMaterialCapacity)
class TransportVehicleMaterialCapacityAdmin(AdminBase):
list_display = ('transport_vehicle', 'material_name', 'capacity')
search_fields = ('transport_vehicle__name', 'transport_vehicle__license_plate', 'material_name')
list_filter = ('transport_vehicle',)

View File

@@ -0,0 +1,45 @@
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('basic_info', '0025_customer_uniq_customer_merchant_name'),
]
operations = [
migrations.CreateModel(
name='TransportVehicle',
fields=[
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('id', models.BigAutoField(primary_key=True, serialize=False)),
('name', models.CharField(max_length=100, verbose_name='车辆名称')),
('license_plate', models.CharField(max_length=20, verbose_name='车牌号码')),
('merchant', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='transport_vehicles', to='basic_info.merchant', verbose_name='所属商户')),
],
options={
'verbose_name': '运输车辆',
'verbose_name_plural': '运输车辆',
'unique_together': {('merchant', 'license_plate')},
},
),
migrations.CreateModel(
name='TransportVehicleMaterialCapacity',
fields=[
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
('id', models.BigAutoField(primary_key=True, serialize=False)),
('material_name', models.CharField(max_length=100, verbose_name='物料名')),
('capacity', models.PositiveIntegerField(verbose_name='容量(条)')),
('merchant', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='transport_vehicle_material_capacities', to='basic_info.merchant', verbose_name='所属商户')),
('transport_vehicle', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='material_capacities', to='basic_info.transportvehicle', verbose_name='运输车辆')),
],
options={
'verbose_name': '运输车辆物料容量',
'verbose_name_plural': '运输车辆物料容量',
'unique_together': {('transport_vehicle', 'material_name')},
},
),
]

View File

@@ -574,6 +574,42 @@ class VehicleTransportRecord(ModelBase):
verbose_name_plural = '司机车次'
class TransportVehicle(ModelBase):
id = models.BigAutoField(primary_key=True)
merchant = models.ForeignKey('Merchant', on_delete=models.PROTECT, related_name='transport_vehicles', verbose_name='所属商户')
name = models.CharField(max_length=100, verbose_name='车辆名称')
license_plate = models.CharField(max_length=20, verbose_name='车牌号码')
def __str__(self):
return f'{self.name} ({self.license_plate})'
class Meta:
verbose_name = '运输车辆'
verbose_name_plural = '运输车辆'
unique_together = ('merchant', 'license_plate')
class TransportVehicleMaterialCapacity(ModelBase):
id = models.BigAutoField(primary_key=True)
merchant = models.ForeignKey('Merchant', on_delete=models.PROTECT, related_name='transport_vehicle_material_capacities', verbose_name='所属商户')
transport_vehicle = models.ForeignKey(
TransportVehicle,
on_delete=models.CASCADE,
related_name='material_capacities',
verbose_name='运输车辆',
)
material_name = models.CharField(max_length=100, verbose_name='物料名')
capacity = models.PositiveIntegerField(verbose_name='容量(条)')
def __str__(self):
return f'{self.transport_vehicle.name}-{self.material_name}:{self.capacity}'
class Meta:
verbose_name = '运输车辆物料容量'
verbose_name_plural = '运输车辆物料容量'
unique_together = ('transport_vehicle', 'material_name')
class MerchantSettingTypeEnum(models.TextChoices):
"""商户设置类型枚举"""
STR = 'str', '字符串'

View File

@@ -7,7 +7,7 @@ from django.core.exceptions import ValidationError
from .models import (
Merchant, MerchantTypeEnum, WareHouse, WarehouseTypeEnum,
WareHouseModeEnum, EmployeeType, Employee, EmployeeStatusEnum,
FrontendPage, FrontendPageTypeEnum
FrontendPage, FrontendPageTypeEnum, TransportVehicle, TransportVehicleMaterialCapacity
)
@@ -171,6 +171,45 @@ class EmployeeTypeTestCase(TestCase):
self.assertEqual(emp_type.employees.count(), 2)
class TransportVehicleTestCase(TestCase):
def setUp(self):
self.merchant = Merchant.objects.create(
name='运输商户',
type=MerchantTypeEnum.STORE
)
def test_create_transport_vehicle_with_material_capacity(self):
vehicle = TransportVehicle.objects.create(
merchant=self.merchant,
name='9.6米厢车',
license_plate='浙A12345'
)
capacity = TransportVehicleMaterialCapacity.objects.create(
merchant=self.merchant,
transport_vehicle=vehicle,
material_name='棉布',
capacity=120
)
self.assertEqual(vehicle.license_plate, '浙A12345')
self.assertEqual(str(vehicle), '9.6米厢车 (浙A12345)')
self.assertEqual(capacity.capacity, 120)
self.assertEqual(vehicle.material_capacities.count(), 1)
def test_transport_vehicle_license_plate_unique_per_merchant(self):
TransportVehicle.objects.create(
merchant=self.merchant,
name='一号车',
license_plate='浙A99999'
)
with self.assertRaises(Exception):
TransportVehicle.objects.create(
merchant=self.merchant,
name='二号车',
license_plate='浙A99999'
)
class FrontendPageTestCase(TestCase):
"""测试前端页面模型"""