forked from erp-dev/erp
fix: added new field into purchase and stock cancelled or red flush
This commit is contained in:
@@ -121,7 +121,8 @@ class StockChangeRecordResponseSerializer(serializers.ModelSerializer):
|
|||||||
model = stock_models.StockChangeRecord
|
model = stock_models.StockChangeRecord
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'type', 'warehouse', 'source_type', 'source_id',
|
'id', 'type', 'warehouse', 'source_type', 'source_id',
|
||||||
'is_finished', 'finished_at', 'created_at', 'updated_at'
|
'is_finished', 'finished_at', 'cancelled', 'is_offset', 'is_reversed',
|
||||||
|
'created_at', 'updated_at'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ class StockChangeViewMixin:
|
|||||||
'source_id': record.source_id,
|
'source_id': record.source_id,
|
||||||
'is_finished': record.is_finished,
|
'is_finished': record.is_finished,
|
||||||
'finished_at': record.finished_at,
|
'finished_at': record.finished_at,
|
||||||
|
'cancelled': record.cancelled,
|
||||||
|
'is_offset': record.is_offset,
|
||||||
|
'is_reversed': record.is_reversed,
|
||||||
'created_at': record.created_at,
|
'created_at': record.created_at,
|
||||||
'created_by': record.created_by.username if record.created_by else None,
|
'created_by': record.created_by.username if record.created_by else None,
|
||||||
'remarks': record.remarks,
|
'remarks': record.remarks,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import logging
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.utils import timezone
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.test import APIClient
|
from rest_framework.test import APIClient
|
||||||
@@ -139,6 +140,7 @@ class CreateStockChangeAPITestCase(TestCase):
|
|||||||
|
|
||||||
logging.disable(logging.NOTSET)
|
logging.disable(logging.NOTSET)
|
||||||
self.addCleanup(logging.disable, logging.CRITICAL)
|
self.addCleanup(logging.disable, logging.CRITICAL)
|
||||||
|
|
||||||
with self.assertLogs('api_v1.views.stock_change_views.mixins', level='ERROR') as cm:
|
with self.assertLogs('api_v1.views.stock_change_views.mixins', level='ERROR') as cm:
|
||||||
response = self.client.post('/api/v1/stock-change/', payload, format='json')
|
response = self.client.post('/api/v1/stock-change/', payload, format='json')
|
||||||
|
|
||||||
@@ -146,6 +148,70 @@ class CreateStockChangeAPITestCase(TestCase):
|
|||||||
self.assertEqual(response.data['error'], '无权限访问')
|
self.assertEqual(response.data['error'], '无权限访问')
|
||||||
self.assertTrue(any('无员工信息' in msg for msg in cm.output))
|
self.assertTrue(any('无员工信息' in msg for msg in cm.output))
|
||||||
|
|
||||||
|
def test_get_stock_change_includes_offset_status_fields(self):
|
||||||
|
record = stock_models.StockChangeRecord.objects.create(
|
||||||
|
merchant=self.merchant,
|
||||||
|
type=stock_models.StockChangeTypeEnum.ADD,
|
||||||
|
warehouse=self.warehouse,
|
||||||
|
source_type=stock_models.StockChangeSourceEnum.PURCHASE,
|
||||||
|
created_by=self.user,
|
||||||
|
)
|
||||||
|
detail = stock_models.StockChangeDetail.objects.create(
|
||||||
|
merchant=self.merchant,
|
||||||
|
stock_change_record=record,
|
||||||
|
product=self.product,
|
||||||
|
quantity='10',
|
||||||
|
unit=self.product.unit,
|
||||||
|
)
|
||||||
|
snapshot = stock_models.StockSnapshot.objects.create(
|
||||||
|
merchant=self.merchant,
|
||||||
|
product=self.product,
|
||||||
|
warehouse=self.warehouse,
|
||||||
|
delta='10',
|
||||||
|
quantity_before='0',
|
||||||
|
quantity_after='10',
|
||||||
|
stock_change_record=record,
|
||||||
|
unit=self.product.unit,
|
||||||
|
num_of_rolls=1,
|
||||||
|
cancelled=True,
|
||||||
|
cancelled_at=timezone.now(),
|
||||||
|
offset_id=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
offset_record = stock_models.StockChangeRecord.objects.create(
|
||||||
|
merchant=self.merchant,
|
||||||
|
type=stock_models.StockChangeTypeEnum.ADD,
|
||||||
|
warehouse=self.warehouse,
|
||||||
|
source_type=stock_models.StockChangeSourceEnum.OFFSET,
|
||||||
|
created_by=self.user,
|
||||||
|
)
|
||||||
|
stock_models.StockSnapshot.objects.create(
|
||||||
|
merchant=self.merchant,
|
||||||
|
product=self.product,
|
||||||
|
warehouse=self.warehouse,
|
||||||
|
delta='-10',
|
||||||
|
quantity_before='10',
|
||||||
|
quantity_after='0',
|
||||||
|
stock_change_record=offset_record,
|
||||||
|
unit=self.product.unit,
|
||||||
|
num_of_rolls=1,
|
||||||
|
offset_to=snapshot.id,
|
||||||
|
offset_at=timezone.now(),
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self.client.get(f'/api/v1/stock-change/{record.id}/')
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
record_data = response.data['stock_change_record']
|
||||||
|
self.assertTrue(record_data['cancelled'])
|
||||||
|
self.assertTrue(record_data['is_reversed'])
|
||||||
|
self.assertFalse(record_data['is_offset'])
|
||||||
|
|
||||||
|
offset_response = self.client.get(f'/api/v1/stock-change/{offset_record.id}/')
|
||||||
|
self.assertEqual(offset_response.status_code, status.HTTP_200_OK)
|
||||||
|
offset_data = offset_response.data['stock_change_record']
|
||||||
|
self.assertTrue(offset_data['is_offset'])
|
||||||
|
self.assertFalse(offset_data['is_reversed'])
|
||||||
|
|
||||||
|
|
||||||
class CreateStockChangeRelaxedAPITestCase(TestCase):
|
class CreateStockChangeRelaxedAPITestCase(TestCase):
|
||||||
"""测试宽松模式库存变动创建 API"""
|
"""测试宽松模式库存变动创建 API"""
|
||||||
|
|||||||
@@ -100,3 +100,15 @@
|
|||||||
|
|
||||||
通过以上步骤,审批流程与红冲机制可以衔接:审批负责“正向入库”与任务分发,红冲负责在业务需要时生成配对的反向库存记录,保持库存账实一致,同时具备可回溯、可审计的业务闭环。
|
通过以上步骤,审批流程与红冲机制可以衔接:审批负责“正向入库”与任务分发,红冲负责在业务需要时生成配对的反向库存记录,保持库存账实一致,同时具备可回溯、可审计的业务闭环。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 库存记录红冲标识字段
|
||||||
|
|
||||||
|
库存变动记录的 API 响应新增以下字段,用于前端识别红冲关系:
|
||||||
|
|
||||||
|
- `cancelled`:是否已被红冲(等价于 `is_reversed`)
|
||||||
|
- `is_reversed`:当前记录是否已被红冲
|
||||||
|
- `is_offset`:当前记录是否为红冲记录(用于冲抵其他记录)
|
||||||
|
|
||||||
|
说明:红冲关系来源于库存快照的 `offset_to/offset_id/cancelled` 字段,记录本身不落库状态字段。
|
||||||
|
|
||||||
|
|||||||
@@ -133,6 +133,21 @@ class StockChangeRecord(ModelBase):
|
|||||||
self.details.count()
|
self.details.count()
|
||||||
return self.details.count()
|
return self.details.count()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_offset(self) -> bool:
|
||||||
|
"""是否为红冲记录(用于冲抵其他记录)"""
|
||||||
|
return self.stock_snapshots.filter(offset_to__isnull=False).exists()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_reversed(self) -> bool:
|
||||||
|
"""是否已被红冲"""
|
||||||
|
return self.stock_snapshots.filter(cancelled=True).exists()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cancelled(self) -> bool:
|
||||||
|
"""兼容字段:是否已被红冲"""
|
||||||
|
return self.is_reversed
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def delta_num_of_rolls(self) -> int:
|
def delta_num_of_rolls(self) -> int:
|
||||||
"""计算库存变动的匹数增减"""
|
"""计算库存变动的匹数增减"""
|
||||||
|
|||||||
Reference in New Issue
Block a user