创建/修改 Sales Order 时的约束 - 单项最大数量和总条目数

本文介绍如何在SAP系统中实现销售订单的行项目数量和金额限制,通过自定义表结构、创建维护屏幕及修改特定User Exit来完成。重点讲述了获取限制值的方法和检查流程。

需求:
Restrict line item quantity and amount of a SO in spectial sales area, sales district and data&time period.

解决过程备案
1. 自定义表结构和创建Maintain Screen


2. 修改 USEREXIT_SAVE_DOCUMENT_PREPARE
 DATA: LV_UNIT_LIMIT LIKE ZSDLIMIT-UNIT_LIMIT,
      LV_LINE_LIMIT LIKE ZSDLIMIT-LINE_LIMIT,
      LV_LINE_AMT TYPE I VALUE 0.

* Get line item unit limit and line limit.
  SELECT SINGLE UNIT_LIMIT LINE_LIMIT
    INTO (LV_UNIT_LIMIT, LV_LINE_LIMIT)
    FROM ZSDLIMIT
    WHERE VKORG  = XVBAK-VKORG
      AND VTWEG  = XVBAK-VTWEG
      AND SPART  = XVBAK-SPART
      AND BZIRK  = XVBKD-BZIRK
      AND ( DATAB <= SY-DATUM )
      AND ( TIMAB <= SY-UZEIT )
      AND ( DATBI >= SY-DATUM OR DATBI = 0 )
      AND ( TIMBI >= SY-UZEIT OR TIMBI <= 0 ).

* Unit limit check
  IF LV_UNIT_LIMIT NE SPACE.
    LOOP AT XVBAP  
       WHERE UPDKZ NE 'D'
              AND ABGRU = SPACE.
              AND KWMENG > LV_UNIT_LIMIT.
      FCODE = FCODE_GLEICHE_SEITE. "=ENT1: continue
*      PERFORM FCODE_BEARBEITEN.
      MESSAGE E013(ZEDI) WITH LV_UNIT_LIMIT.
    ENDLOOP.
  ENDIF.

* Line limit check
  IF LV_LINE_LIMIT NE SPACE.
    LOOP AT XVBAP TRANSPORTING NO FIELDS
         WHERE UPDKZ NE 'D'
                AND ABGRU = SPACE.
       ADD 1 TO LV_LINE_AMT.
    ENDLOOP.

    IF LV_LINE_AMT > LV_LINE_LIMIT.
      FCODE = FCODE_GLEICHE_SEITE. "=ENT1: continue
      MESSAGE E014(ZEDI) WITH LV_LINE_LIMIT.
    ENDIF.
  ENDIF.

这里要感谢下SAP砍刀的帮忙, 没想到要用 TIMBI <= 0 的形式来判断一个时间类型的字段是否为initial。我试了TIMBI = SPACE / '' / '000000' / IS NULL / 0 均未得到正确结果,原因是Open SQL => Native SQL时参数值解析出的值 ( ' ' 会被解析成'00000', 0 / SPACE=>'000000') 和数据库中的值不一致,ABAP Dictionary TIMS类型的字段在DB (Oracle / SQL Server)中默认值为空字符串。

3. 在 USEREXIT_SAVE_DOCUMENT_PREPARED 中如果用MESSAGE EXXX报错时,需要加这样写:
    FCODE = FCODE_GLEICHE_SEITE. "=ENT1: continue
    MESSAGE E013(ZEDI) WITH LV_UNIT_LIMIT.
要不然在出现Error Message后,回车,SO line item中值不可修改,具体原因我也没深究,只是在Debug的时候发现FCODE_GLEICHE_SEITE的值为ENT1, 通过 t-code VFBS 可以知道它是Continue的意思,在报完Message后,系统会根据这个FCODE做一些操作。

4. 修改 USEREXIT_CHECK_XVBAP
在VA01 / VA02中系统每接受一个ITEM, 都会调用这个User Exit来check其中的数据,这里要注意的是要用这样的语句来获得当前的有效行数:
  LOOP AT XVBAP TRANSPORTING NO FIELDS
       WHERE UPDKZ NE 'D'
              AND ABGRU = SPACE.
    ADD 1 TO LV_LINE_AMT.
  ENDLOOP.
这里报Message时Message Type要用 "I", 要不对于Bundle/BOM物料就会因得不到后续处理而产生问题 另这里不需要修改FCODE.

参考
http://help.sap.com/saphelp_46c/helpdata/en/1c/f62c7dd435d1118b3f0060b03ca329/content.htm

-- 创建据库 CREATE DATABASE IF NOT EXISTS restaurant_system CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE restaurant_system; -- 用户表(集成顾客/服务员/管理员) CREATE TABLE users ( user_id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL COMMENT 'SHA-256加密存储', phone VARCHAR(20) UNIQUE, email VARCHAR(100) UNIQUE, role ENUM('customer','waiter','admin') DEFAULT 'customer', avatar VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, last_login DATETIME ) ENGINE=InnoDB; CREATE TABLE dish_categories ( category_id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, description VARCHAR(255), sort_order INT DEFAULT 0 ); CREATE TABLE dining_tables ( table_id INT PRIMARY KEY AUTO_INCREMENT, table_no VARCHAR(20) UNIQUE NOT NULL, capacity INT NOT NULL COMMENT '最大容纳人', location VARCHAR(100), status ENUM('vacant','occupied','cleaning','reserved') DEFAULT 'vacant', qr_code VARCHAR(255) COMMENT '绑定二维码' ); -- 菜品表 CREATE TABLE dishes ( dish_id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL, category_id INT, price DECIMAL(10,2) NOT NULL, cost DECIMAL(10,2) COMMENT '成本价', discount_rate DECIMAL(3,2) DEFAULT 1.00, image_url VARCHAR(255), description TEXT, is_featured BOOLEAN DEFAULT FALSE, is_active BOOLEAN DEFAULT TRUE, sales_count INT DEFAULT 0, FOREIGN KEY (category_id) REFERENCES dish_categories(category_id) ); CREATE TABLE orders ( order_id VARCHAR(32) PRIMARY KEY COMMENT '雪花算法生成', user_id INT NOT NULL, table_id INT, waiter_id INT COMMENT '服务员ID', total_amount DECIMAL(12,2) NOT NULL, actual_amount DECIMAL(12,2) COMMENT '实收金额', status ENUM('pending','confirmed','cooking','served','completed','canceled') DEFAULT 'pending', special_notes TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, completed_at DATETIME, FOREIGN KEY (user_id) REFERENCES users(user_id), FOREIGN KEY (table_id) REFERENCES dining_tables(table_id), FOREIGN KEY (waiter_id) REFERENCES users(user_id) ) PARTITION BY RANGE (YEAR(created_at)) ( PARTITION p2025 VALUES LESS THAN (2026), PARTITION p2026 VALUES LESS THAN (2027) ); CREATE TABLE order_details ( detail_id INT PRIMARY KEY AUTO_INCREMENT, order_id VARCHAR(32) NOT NULL, dish_id INT NOT NULL, quantity INT NOT NULL DEFAULT 1, unit_price DECIMAL(10,2) NOT NULL, discount_price DECIMAL(10,2), remark VARCHAR(255), FOREIGN KEY (order_id) REFERENCES orders(order_id), FOREIGN KEY (dish_id) REFERENCES dishes(dish_id) ); CREATE TABLE payments ( payment_id VARCHAR(32) PRIMARY KEY, order_id VARCHAR(32) NOT NULL, amount DECIMAL(12,2) NOT NULL, method ENUM('wechat','alipay','cash','card','voucher'), transaction_no VARCHAR(64), status ENUM('pending','completed','refunded') DEFAULT 'pending', payer_info VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (order_id) REFERENCES orders(order_id) ); CREATE TABLE feedbacks ( feedback_id INT PRIMARY KEY AUTO_INCREMENT, order_id VARCHAR(32) NOT NULL, user_id INT NOT NULL, rating TINYINT CHECK (rating BETWEEN 1 AND 5), content TEXT, reply_content TEXT, reply_time DATETIME, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (order_id) REFERENCES orders(order_id), FOREIGN KEY (user_id) REFERENCES users(user_id) ); CREATE INDEX idx_dish_search ON dishes(name, category_id, price); CREATE INDEX idx_order_user ON orders(user_id); CREATE INDEX idx_order_status ON orders(status); CREATE INDEX idx_order_time ON orders(created_at);基于您对于餐厅点餐管理系统的需求分析,设计系统的实体关系图(ER图)。 要求: 准确识别系统中的主要实体; 合理定义实体的属性; 正确表示实体间的联系及联系的类型(1:1, 1:N, M:N); 适当添加联系的属性; 确保ER图能够支撑需求分析中提到的所有核心功能。
06-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值