diff --git a/apps/asm/__init__.py b/apps/asm/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/asm/admin.py b/apps/asm/admin.py new file mode 100644 index 00000000..8c38f3f3 --- /dev/null +++ b/apps/asm/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/apps/asm/apps.py b/apps/asm/apps.py new file mode 100644 index 00000000..44ce63a4 --- /dev/null +++ b/apps/asm/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AsmConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'apps.asm' diff --git a/apps/asm/migrations/0001_initial.py b/apps/asm/migrations/0001_initial.py new file mode 100644 index 00000000..ba325653 --- /dev/null +++ b/apps/asm/migrations/0001_initial.py @@ -0,0 +1,51 @@ +# Generated by Django 3.2.12 on 2025-12-12 02:26 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('system', '0006_auto_20241213_1249'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Asset', + fields=[ + ('id', models.CharField(editable=False, help_text='主键ID', max_length=20, primary_key=True, serialize=False, verbose_name='主键ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')), + ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), + ('code', models.CharField(max_length=50, unique=True, verbose_name='固定资产编号')), + ('name', models.CharField(max_length=100, verbose_name='固定资产名称')), + ('model', models.CharField(blank=True, max_length=100, null=True, verbose_name='资产型号')), + ('quantity', models.IntegerField(default=1, verbose_name='数量')), + ('price', models.DecimalField(decimal_places=2, max_digits=12, verbose_name='资产原值/单价(元)')), + ('net_value', models.DecimalField(decimal_places=2, max_digits=12, verbose_name='净值')), + ('asm_user', models.CharField(blank=True, max_length=50, null=True, verbose_name='使用人')), + ('keeper', models.CharField(blank=True, max_length=100, null=True, verbose_name='使用保管人')), + ('useful_life', models.IntegerField(blank=True, null=True, verbose_name='使用年限(年)')), + ('location', models.CharField(blank=True, max_length=100, null=True, verbose_name='存放地点')), + ('department', models.CharField(blank=True, max_length=100, null=True, verbose_name='存放部门')), + ('vendor', models.CharField(blank=True, max_length=100, null=True, verbose_name='客商')), + ('category', models.CharField(blank=True, max_length=100, null=True, verbose_name='固定资产类别')), + ('start_date', models.DateField(blank=True, null=True, verbose_name='启用日期')), + ('expire_date', models.DateField(blank=True, null=True, verbose_name='到期日期')), + ('unit', models.CharField(blank=True, max_length=50, null=True, verbose_name='计量单位')), + ('remark', models.TextField(blank=True, null=True, verbose_name='备注')), + ('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='asset_belong_dept', to='system.dept', verbose_name='所属部门')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='asset_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='asset_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/apps/asm/migrations/0002_asset_ticket.py b/apps/asm/migrations/0002_asset_ticket.py new file mode 100644 index 00000000..4d77dc8d --- /dev/null +++ b/apps/asm/migrations/0002_asset_ticket.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.12 on 2025-12-12 06:20 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('wf', '0005_workflow_cate'), + ('asm', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='asset', + name='ticket', + field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='asset_ticket', to='wf.ticket', verbose_name='关联工单'), + ), + ] diff --git a/apps/asm/migrations/__init__.py b/apps/asm/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/asm/models.py b/apps/asm/models.py new file mode 100644 index 00000000..758103a9 --- /dev/null +++ b/apps/asm/models.py @@ -0,0 +1,31 @@ +from apps.utils.models import CommonADModel, CommonBDModel +from django.db import models + +class AssetAudit(CommonBDModel): + org = models. + asset_data = models.JSONField(verbose_name='资产信息', blank=True, null=True) + ticket = models.OneToOneField('wf.ticket', verbose_name='关联工单', + on_delete=models.SET_NULL, related_name='asset_ticket', null=True, blank=True, db_constraint=False) + + def __str__(self): + return f"{self.code} - {self.name}" + + +class Asset(CommonADModel): + code = models.CharField('固定资产编号',max_length=50, unique=True) + name = models.CharField('固定资产名称',max_length=100) + model = models.CharField("资产型号", max_length=100, blank=True, null=True) + quantity = models.IntegerField("数量", default=1) + price = models.DecimalField("资产原值/单价(元)", max_digits=12, decimal_places=2) + net_value = models.DecimalField("净值", max_digits=12, decimal_places=2) + asm_user = models.CharField("使用人", max_length=50, blank=True, null=True) + keeper = models.CharField("使用保管人", max_length=100, blank=True, null=True) + useful_life = models.IntegerField("使用年限(年)", blank=True, null=True) + location = models.CharField("存放地点", max_length=100, blank=True, null=True) + department = models.CharField("存放部门", max_length=100, blank=True, null=True) + vendor = models.CharField("客商", max_length=100, blank=True, null=True) + category = models.CharField("固定资产类别", max_length=100, blank=True, null=True) + start_date = models.DateField("启用日期", blank=True, null=True) + expire_date = models.DateField("到期日期", blank=True, null=True) + unit = models.CharField("计量单位", max_length=50, blank=True, null=True) + remark = models.TextField("备注", blank=True, null=True) \ No newline at end of file diff --git a/apps/asm/serializers.py b/apps/asm/serializers.py new file mode 100644 index 00000000..ab862374 --- /dev/null +++ b/apps/asm/serializers.py @@ -0,0 +1,16 @@ +from apps.asm.models import Asset, AssetLog +from apps.utils.serializers import CustomModelSerializer +from apps.utils.constants import EXCLUDE_FIELDS_DEPT + +class AssetSerializer(CustomModelSerializer): + class Meta: + model = Asset + fields = '__all__' + read_only_fields = EXCLUDE_FIELDS_DEPT + + +class AssetlogSerializer(CustomModelSerializer): + class Meta: + model = AssetLog + fields = '__all__' + read_only_fields = EXCLUDE_FIELDS_DEPT \ No newline at end of file diff --git a/apps/asm/tests.py b/apps/asm/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/apps/asm/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/apps/asm/urls.py b/apps/asm/urls.py new file mode 100644 index 00000000..bdd751ce --- /dev/null +++ b/apps/asm/urls.py @@ -0,0 +1,12 @@ +from django.urls import path, include +from rest_framework.routers import DefaultRouter +from apps.asm.views import AssetViewSet, AssetLogViewSet + +API_BASE_URL = 'api/asm/' + +router = DefaultRouter() +router.register('asset', AssetViewSet, basename='asset') +router.register('assetlog', AssetLogViewSet, basename='assetlog') +urlpatterns = [ + path(API_BASE_URL, include(router.urls)), +] \ No newline at end of file diff --git a/apps/asm/views.py b/apps/asm/views.py new file mode 100644 index 00000000..c0594c06 --- /dev/null +++ b/apps/asm/views.py @@ -0,0 +1,36 @@ +from apps.wf.mixins import TicketMixin +from apps.utils.viewsets import CustomModelViewSet +from apps.asm.models import Asset, AssetLog +from rest_framework.exceptions import ParseError +from apps.asm.serializers import AssetSerializer, AssetlogSerializer +from apps.wf.models import Ticket + +class AssetAuditViewSet(TicketMixin, CustomModelViewSet): + """ + list: 固定资产审核 + + 固定资产审核 + """ + queryset = Asset.objects.all() + serializer_class = AssetSerializer + search_fields = ['assetlog'] + workflow_key = 'wf_asset' + + @staticmethod + def add_asset(ticket:Ticket, transition, new_ticket_data: dict): + asset = Asset.objects.get(ticket=ticket) + if AssetLog.objects.filter(code=asset.code).exists(): + raise ParseError('资产名称已存在') + AssetLog.objects.create(**new_ticket_data) + + +class AssetViewSet(CustomModelViewSet): + """ + list: 固定资产台账 + + 固定资产台账 + """ + queryset = Asset.objects.all() + serializer_class = AssetlogSerializer + search_fields = ['name', 'code', 'category'] + filterset_fields = ['category'] diff --git a/apps/ofm/models.py b/apps/ofm/models.py index 24ea3852..8494a103 100644 --- a/apps/ofm/models.py +++ b/apps/ofm/models.py @@ -26,6 +26,7 @@ class Mroom(CommonADModel): location = models.CharField('位置', max_length=100) capacity = models.PositiveIntegerField('容纳人数') + class MroomBooking(CommonBDModel): """TN: 会议室预定信息""" # belong_dept 是预定部门 diff --git a/apps/ofm/services.py b/apps/ofm/services.py index 6addbf7a..10f2cdc4 100644 --- a/apps/ofm/services.py +++ b/apps/ofm/services.py @@ -29,10 +29,10 @@ def mroombooking_reject(ticket: Ticket, transition, new_ticket_data: dict): ins = MroomBooking.objects.get(id=new_ticket_data['t_id']) MroomSlot.objects.filter(booking=ins).update(is_inuse=False) -def bind_lendingseal(ticket: Ticket, transition, new_ticket_data: dict): - ins = LendingSeal.objects.get(id=new_ticket_data['t_id']) - ins.actual_return_date = None +def bind_lendingseal(ticket: Ticket): ticket_data = ticket.ticket_data + ins = LendingSeal.objects.get(id=ticket_data['t_id']) + ins.actual_return_date = None ticket_data.update({ 't_model': 'LendingSeal', 't_id': ins.id, diff --git a/server/settings.py b/server/settings.py index b3b51179..4b37f2eb 100755 --- a/server/settings.py +++ b/server/settings.py @@ -87,6 +87,7 @@ INSTALLED_APPS = [ 'apps.wpmw', 'apps.ofm', 'apps.srm', + 'apps.asm', ] MIDDLEWARE = [ diff --git a/server/urls.py b/server/urls.py index bfde6f72..d83709ff 100755 --- a/server/urls.py +++ b/server/urls.py @@ -77,6 +77,7 @@ urlpatterns = [ path('', include('apps.wpmw.urls')), path('', include('apps.ofm.urls')), path('', include('apps.srm.urls')), + path('', include('apps.asm.urls')), # 前端页面入口 path('', TemplateView.as_view(template_name="index.html")),