1
0
forked from erp-dev/erp

feat: big

This commit is contained in:
2026-07-01 11:51:13 +08:00
parent 7c9b77afb0
commit 5170700234
28 changed files with 933 additions and 37 deletions

40
business/notifications.py Normal file
View File

@@ -0,0 +1,40 @@
import logging
from django.conf import settings
from django.db import transaction
logger = logging.getLogger(__name__)
def enqueue_business_order_speech(*, order, order_label: str, action_label: str) -> None:
if not getattr(settings, 'BUSINESS_ORDER_SPEECH_NOTIFY_ENABLED', True):
return
if _is_external_order(order):
return
order_id = _get_order_identifier(order)
text = f'{order_label} {order_id}{action_label}'
def _enqueue():
try:
from business.tasks import notify_business_order_speech
notify_business_order_speech.delay(text=text)
except Exception:
logger.exception('[business.notifications] 投递业务单据语音播报任务失败(已忽略)')
transaction.on_commit(_enqueue)
def _is_external_order(order) -> bool:
return bool(
getattr(order, 'is_external_source', False)
or getattr(order, 'external_source_id', None)
)
def _get_order_identifier(order) -> str:
human_id = getattr(order, 'human_id', None)
if human_id:
return str(human_id)
return str(getattr(order, 'id', ''))

View File

@@ -13,6 +13,7 @@ from stock import models as stock_models
from . import models
from . import services as business_services
from .notifications import enqueue_business_order_speech
def render_pre_sales_order_created_markdown(
@@ -304,6 +305,7 @@ def create_pre_sales_order(
transaction.on_commit(_send_created_signal)
pre_sales_order.refresh_from_db()
enqueue_business_order_speech(order=pre_sales_order, order_label='预销售单', action_label='创建')
return pre_sales_order
@@ -580,6 +582,7 @@ def create_pre_purchase_order(
)
pre_purchase_order.refresh_from_db()
enqueue_business_order_speech(order=pre_purchase_order, order_label='预采购单', action_label='创建')
return pre_purchase_order

View File

@@ -23,6 +23,9 @@ from .tasks import (
create_purchase_return_order_stock_entries,
create_sales_return_order_stock_entries,
)
from .notifications import enqueue_business_order_speech
class BalanceService:
@staticmethod
def adjust_supplier_balance(
@@ -317,6 +320,7 @@ def create_purchase_order(
models.PurchaseOrderItem.objects.bulk_create(bulk_objects)
purchase_order.refresh_from_db()
enqueue_business_order_speech(order=purchase_order, order_label='采购单', action_label='创建')
return purchase_order
@@ -462,6 +466,7 @@ def create_sales_order(
models.SalesOrderItem.objects.bulk_create(bulk_objects)
sales_order.refresh_from_db()
enqueue_business_order_speech(order=sales_order, order_label='销售单', action_label='创建')
return sales_order
@@ -613,6 +618,7 @@ def create_purchase_return_order(
models.PurchaseReturnOrderItem.objects.bulk_create(bulk_objects)
return_order.refresh_from_db()
enqueue_business_order_speech(order=return_order, order_label='采购退货单', action_label='创建')
return return_order
@@ -766,6 +772,7 @@ def create_sales_return_order(
models.SalesReturnOrderItem.objects.bulk_create(bulk_objects)
return_order.refresh_from_db()
enqueue_business_order_speech(order=return_order, order_label='销售退货单', action_label='创建')
return return_order
@@ -883,6 +890,7 @@ def create_payment_order(
discount_amount=normalized_discount,
)
payment_order.refresh_from_db()
enqueue_business_order_speech(order=payment_order, order_label='付款单', action_label='创建')
return payment_order
@@ -921,6 +929,7 @@ def create_receipt_order(
discount_amount=normalized_discount,
)
receipt_order.refresh_from_db()
enqueue_business_order_speech(order=receipt_order, order_label='收款单', action_label='创建')
return receipt_order
@@ -1687,6 +1696,7 @@ def _cancel_order_impl(
locked.status = cancelled_status
locked.save(update_fields=['status', 'updated_at'])
locked.refresh_from_db(fields=['status', 'updated_at'])
enqueue_business_order_speech(order=locked, order_label=error_label, action_label='作废')
return locked

View File

@@ -157,3 +157,24 @@ def create_sales_return_order_stock_entries(
payload['task_id'] = self.request.id
return payload
@shared_task(bind=True)
def notify_business_order_speech(self, *, text: str) -> Dict[str, Any]:
try:
from flower.utils import play_speech
response = play_speech(text=text, timeout_seconds=3.0)
return {
'status': 'sent',
'task_id': self.request.id,
'status_code': response.status_code,
'raw': response.raw,
}
except Exception as exc:
logger.exception('[business.tasks] 业务单据语音播报失败(已忽略)')
return {
'status': 'error',
'task_id': self.request.id,
'error': str(exc),
}