40、电商订单管理与税费运费处理

电商订单管理与税费运费处理

1. 订单管理系统现状与问题

当前,订单管理页面无法正常工作,需要对其进行修改以适配新功能。在将客户订单添加到系统的过程中,新增代码较为简单,数据和业务层的订单处理函数现在将客户 ID 作为参数,并分配给订单。不过,在实现更多新的订单代码后,才能为客户提供更多信息,如发送确认电子邮件。

2. 客户订单管理的更新

由于数据库已将订单与客户关联,接下来需要更新订单管理页面,因为旧页面已无法正常工作。这涉及对数据层和业务层进行各种修改,以在管理系统中提供新的数据结构和访问代码。由于更改范围广泛,将分别对数据层、业务层和表示层进行处理。

3. 数据层的修改

需要对数据库中的存储过程进行更新和创建新的存储过程,具体如下:
- 更新的存储过程
- orders_get_most_recent_orders
- orders_get_orders_between_dates
- orders_get_orders_by_status
- orders_get_order_info
- orders_update_order
- 新创建的存储过程
- orders_get_by_customer_id
- orders_get_order_short_details
- customer_get_customers_list

更新数据层的具体步骤
1. 使用 phpMyAdmin 创建以下存储过程,执行每个步骤的代码前不要忘记设置 $$ 分隔符。
2. 删除旧的 orders_get_most_recent_orders 存储过程,并创建新的:

-- Drop orders_get_most_recent_orders stored procedure
DROP PROCEDURE orders_get_most_recent_orders$$
-- Create orders_get_most_recent_orders stored procedure
CREATE PROCEDURE orders_get_most_recent_orders(IN inHowMany INT)
BEGIN
PREPARE statement FROM
"SELECT     o.order_id, o.total_amount, o.created_on,
o.shipped_on, o.status, c.name
FROM       orders o
INNER JOIN customer c
ON o.customer_id = c.customer_id
ORDER BY   o.created_on DESC
LIMIT      ?";
SET @p1 = inHowMany;
EXECUTE statement USING @p1;
END$$
  1. 删除旧的 orders_get_orders_between_dates 存储过程,并创建新的:
-- Drop orders_get_orders_between_dates stored procedure
DROP PROCEDURE orders_get_orders_between_dates$$
-- Create orders_get_orders_between_dates stored procedure
CREATE PROCEDURE orders_get_orders_between_dates(
IN inStartDate DATETIME, IN inEndDate DATETIME)
BEGIN
SELECT     o.order_id, o.total_amount, o.created_on,
o.shipped_on, o.status, c.name
FROM       orders o
INNER JOIN customer c
ON o.customer_id = c.customer_id
WHERE      o.created_on >= inStartDate AND o.created_on <= inEndDate
ORDER BY   o.created_on DESC;
END$$
  1. 删除旧的 orders_get_orders_by_status 存储过程,并创建新的:
-- Drop orders_get_orders_by_status stored procedure
DROP PROCEDURE orders_get_orders_by_status$$
-- Create orders_get_orders_by_status stored procedure
CREATE PROCEDURE orders_get_orders_by_status(IN inStatus INT)
BEGIN
SELECT     o.order_id, o.total_amount, o.created_on,
o.shipped_on, o.status, c.name
FROM       orders o
INNER JOIN customer c
ON o.customer_id = c.customer_id
WHERE      o.status = inStatus
ORDER BY   o.created_on DESC;
END$$
  1. 删除旧的 orders_get_order_info 存储过程,并创建新的:
-- Drop orders_get_order_info stored procedure
DROP PROCEDURE orders_get_order_info$$
-- Create orders_get_order_info stored procedure
CREATE PROCEDURE orders_get_order_info(IN inOrderId INT)
BEGIN
SELECT order_id, total_amount, created_on, shipped_on, status,
comments, customer_id, auth_code, reference
FROM   orders
WHERE  order_id = inOrderId;
END$$
  1. 删除旧的 orders_update_order 存储过程,并创建新的:
-- Drop orders_update_order stored procedure
DROP PROCEDURE orders_update_order$$
-- Create orders_update_order stored procedure
CREATE PROCEDURE orders_update_order(IN inOrderId INT, IN inStatus INT,
IN inComments VARCHAR(255), IN inAuthCode VARCHAR(50),
IN inReference VARCHAR(50))
BEGIN
DECLARE currentStatus INT;
SELECT status
FROM   orders
WHERE  order_id = inOrderId
INTO   currentStatus;
IF  inStatus != currentStatus AND (inStatus = 0 OR inStatus = 1) THEN
UPDATE orders SET shipped_on = NULL WHERE order_id = inOrderId;
ELSEIF inStatus != currentStatus AND inStatus = 2 THEN
UPDATE orders SET shipped_on = NOW() WHERE order_id = inOrderId;
END IF;
UPDATE orders
SET    status = inStatus, comments = inComments,
auth_code = inAuthCode, reference = inReference
WHERE  order_id = inOrderId;
END$$
  1. 执行以下代码创建 orders_get_orders_by_customer_id 存储过程:
-- Create orders_get_by_customer_id stored procedure
CREATE PROCEDURE orders_get_by_customer_id(IN inCustomerId INT)
BEGIN
SELECT     o.order_id, o.total_amount, o.created_on,
o.shipped_on, o.status, c.name
FROM       orders o
INNER JOIN customer c
ON o.customer_id = c.customer_id
WHERE      o.customer_id = inCustomerId
ORDER BY   o.created_on DESC;
END$$
  1. 执行以下代码创建 orders_get_order_short_details 存储过程:
-- Create orders_get_order_short_details stored procedure
CREATE PROCEDURE orders_get_order_short_details(IN inOrderId INT)
BEGIN
SELECT      o.order_id, o.total_amount, o.created_on,
o.shipped_on, o.status, c.name
FROM        orders o
INNER JOIN  customer c
ON o.customer_id = c.customer_id
WHERE       o.order_id = inOrderId;
END$$
  1. 执行以下代码创建 customer_get_customers_list 存储过程:
-- Create customer_get_customers_list stored procedure
CREATE PROCEDURE customer_get_customers_list()
BEGIN
SELECT customer_id, name FROM customer ORDER BY name ASC;
END$$
4. 业务层的修改

需要对业务层进行一些更改,包括修改 Orders 类的 UpdateOrder() 方法,并向 Orders Customers 类添加三个新方法:
- GetByCustomerId()
- GetOrderShortDetails()
- GetCustomersList()

更新业务层的具体步骤
1. 在 business/orders.php Orders 类中添加 GetByCustomerId() 方法:

// Gets all orders placed by a specified customer
public static function GetByCustomerId($customerId)
{
// Build the SQL query
$sql = 'CALL orders_get_by_customer_id(:customer_id)';
// Build the parameters array
$params = array (':customer_id' => $customerId);
// Execute the query and return the results
return DatabaseHandler::GetAll($sql, $params);
}
  1. business/orders.php Orders 类中添加 GetOrderShortDetails() 方法:
// Get short details for an order
public static function GetOrderShortDetails($orderId)
{
// Build the SQL query
$sql = 'CALL orders_get_order_short_details(:order_id)';
// Build the parameters array
$params = array (':order_id' => $orderId);
// Execute the query and return the results
return DatabaseHandler::GetAll($sql, $params);
}
  1. 修改 Orders 类的 UpdateOrder() 方法:
// Updates order details
public static function UpdateOrder($orderId, $status, $comments,
$authCode, $reference)
{
// Build the SQL query
$sql = 'CALL orders_update_order(:order_id, :status, :comments,
:auth_code, :reference)';
// Build the parameters array
$params = array (':order_id' => $orderId,
':status' => $status,
':comments' => $comments,
':auth_code' => $authCode,
':reference' => $reference);
// Execute the query
DatabaseHandler::Execute($sql, $params);
}
  1. business/customer.php Customer 类中添加 GetCustomersList() 方法:
// Gets all customers names with their associated id
public static function GetCustomersList()
{
// Build the SQL query
$sql = 'CALL customer_get_customers_list()';
// Execute the query and return the results
return DatabaseHandler::GetAll($sql);
}
5. 表示层的修改

需要更新表示层以利用新的数据层和业务层功能。目前不会对订单管理代码进行大规模更改,因为在完成新的订单处理系统后还会进行修改。

更新表示层的具体步骤
1. 在 presentation/templates/admin_orders.tpl 中添加以下代码:

{* admin_orders.tpl *}
{load_presentation_object filename="admin_orders" assign="obj"}
{if $obj->mErrorMessage}<p class="error">{$obj->mErrorMessage}</p>{/if}
<form method="get" action="{$obj->mLinkToAdmin}">
<input name="Page" type="hidden" value="Orders" />
<p>
<font class="bold-text">Show orders by customer</font>
<select name="customer_id">
{section name=i loop=$obj->mCustomers}
<option value="{$obj->mCustomers[i].customer_id}"
{if $obj->mCustomers[i].customer_id == $obj->mCustomerId}
selected="selected"
{/if}>
{$obj->mCustomers[i].name}
</option>
{/section}
</select>
<input type="submit" name="submitByCustomer" value="Go!" />
</p>
<p>
<font class="bold-text">Get by order ID</font>
<input name="orderId" type="text" value="{$obj->mOrderId}" />
<input type="submit" name="submitByOrderId" value="Go!" />
</p>
<p>
<font class="bold-text">Show the most recent</font>
<input name="recordCount" type="text" value="{$obj->mRecordCount}" />
...
{section name=i loop=$obj->mOrders}
{assign var=status value=$obj->mOrders[i].status}
<tr>
<td>{$obj->mOrders[i].order_id}</td>
<td>{$obj->mOrders[i].created_on|date_format:"%Y-%m-%d %T"}</td>
<td>{$obj->mOrders[i].shipped_on|date_format:"%Y-%m-%d %T"}</td>
<td>{$obj->mOrderStatusOptions[$status]}</td>
<td>{$obj->mOrders[i].name}</td>
<td align="right">
<a href="{$obj->mOrders[i].link_to_order_details_admin}">View Details</a>
</td>
</tr>
{/section}
</table>
{/if}
  1. presentation/admin_orders.php AdminOrders 类中添加以下成员:
public $mLinkToAdmin;
public $mCustomers;
public $mCustomerId;
public $mOrderId;
  1. presentation/admin_orders.php AdminOrders 类的 init() 方法中添加以下代码:
// If "Show orders by status" filter is in action ...
if (isset ($_GET['submitOrdersByStatus']))
{
$this->mSelectedStatus = $_GET['status'];
$this->mOrders = Orders::GetOrdersByStatus($this->mSelectedStatus);
}
// If the "Show orders by customer ID" filter is in action ...
if (isset ($_GET['submitByCustomer']))
{
if (empty ($_GET['customer_id']))
$this->mErrorMessage = 'No customer has been selected';
else
{
$this->mCustomerId = $_GET['customer_id'];
$this->mOrders = Orders::GetByCustomerId($this->mCustomerId);
}
}
// If the "Get order by ID" filter is in action ...
if (isset ($_GET['submitByOrderId']))
{
if (empty ($_GET['orderId']))
$this->mErrorMessage = 'You must enter an order ID.';
else
{
$this->mOrderId = $_GET['orderId'];
$this->mOrders = Orders::GetOrderShortDetails($this->mOrderId);
}
}
$this->mCustomers = Customer::GetCustomersList();
if (is_array($this->mOrders) && count($this->mOrders) == 0)
$this->mErrorMessage =
'No orders found matching your searching criteria!';
  1. presentation/admin_order_details.php AdminOrderDetails 类中添加新成员:
public $mLinkToAdmin;
public $mLinkToOrdersAdmin;
public $mCustomerInfo;
  1. AdminOrderDetails 类的 init() 方法中修改更新订单的代码:
// Initializes class members
public function init()
{
if (isset ($_GET['submitUpdate']))
{
Orders::UpdateOrder($this->mOrderId, $_GET['status'],
$_GET['comments'], $_GET['authCode'], $_GET['reference']);
}
  1. AdminOrderDetails 类的 init() 方法中添加读取客户数据的代码:
$this->mOrderInfo = Orders::GetOrderInfo($this->mOrderId);
$this->mOrderDetails = Orders::GetOrderDetails($this->mOrderId);
$this->mCustomerInfo = Customer::Get($this->mOrderInfo['customer_id']);
// Value which specifies whether to enable or disable edit mode
if (isset ($_GET['submitEdit']))
  1. 修改 presentation/templates/admin_order_details.tpl
<tr>
<td class="bold-text">Status: </td>
<td>
<select name="status"
{if ! $obj->mEditEnabled} disabled="disabled" {/if} >
{html_options options=$obj->mOrderStatusOptions
selected=$obj->mOrderInfo.status}
</select>
</td>
</tr>
<tr>
<td class="bold-text">Authorization Code: </td>
<td>
<input name="authCode" type="text" size="50"
value="{$obj->mOrderInfo.auth_code}"
{if ! $obj->mEditEnabled} disabled="disabled" {/if} />
<td>
</tr>
<tr>
<td class="bold-text">Reference Number: </td>
<td>
<input name="reference" type="text" size="50"
value="{$obj->mOrderInfo.reference}"
{if ! $obj->mEditEnabled} disabled="disabled" {/if} />
<td>
</tr>
<tr>
<td class="bold-text">Comments: </td>
<td>
<input name="comments" type="text" size="50"
value="{$obj->mOrderInfo.comments}"
{if ! $obj->mEditEnabled} disabled="disabled" {/if} />
<td>
</tr>
<tr>
<td class="bold-text">Customer Name: </td>
<td>{$obj->mCustomerInfo.name}</td>
</tr>
<tr>
<td class="bold-text" valign="top">Shipping Address: </td>
<td>
{$obj->mCustomerInfo.address_1}<br />
{if $obj->mCustomerInfo.address_2}
{$obj->mCustomerInfo.address_2}<br />
{/if}
{$obj->mCustomerInfo.city}<br />
{$obj->mCustomerInfo.region}<br />
{$obj->mCustomerInfo.postal_code}<br />
{$obj->mCustomerInfo.country}<br />
</td>
</tr>
<tr>
<td class="bold-text">Customer Email: </td>
<td>{$obj->mCustomerInfo.email}</td>
</tr>
</table>
  1. 更新 admin.php ,添加对对称加密、安全卡和客户业务层类的引用:
require_once BUSINESS_DIR . 'shopping_cart.php';
require_once BUSINESS_DIR . 'orders.php';
require_once BUSINESS_DIR . 'symmetric_crypt.php';
require_once BUSINESS_DIR . 'secure_card.php';
require_once BUSINESS_DIR . 'customer.php';
  1. 加载网站,确保新添加的代码正常工作。
6. 税费和运费处理

许多电子商务网站都需要添加税费和运费。这一功能的实现复杂度取决于具体需求,这里将提供基本且可扩展的功能来评估税费和运费。

7. 税费问题
  • 历史背景 :早期电子商务网站的税收执行不力,许多网站完全忽略税收,尤其是国际订单。随着人们对电子商务的认识增加,税务机构开始重视这一问题,提出并实施了一系列解决方案。
  • 关键概念 :“关联”(nexus)是税收的关键概念,即企业在征税管辖区有足够的业务存在才需要征税。国际运输时,除非公司在目的地国家有重要业务,否则通常无需负责税收;国内运输则可能需要负责。
  • 其他关键问题
    • 税收取决于发货地和收货地。
    • 适用国家规则。
    • 销售的产品类型很重要。
  • 简单的税收方案 :数据库表将包含各种适用的税率信息,目前税率选择取决于客户的运输区域,所有产品按相同税率征税。
8. 运费问题
  • 处理方式 :运费处理相对税费较简单,但也可根据需求复杂化。如果有与邮政服务的既有关系,可尽量保持原有方式;如果是新开始或调整业务,有多种选择。
  • 选择方案
    • 不考虑运费,如数字下载业务。
    • 将运费包含在产品成本中。
    • 收取固定费用。
    • 考虑产品的重量和尺寸计算精确费用,部分运输公司提供 API 简化计算。
  • 简单的运费方案 :为数据库中的每个运输区域提供多种运输选项,每个选项有相应费用,该费用直接添加到订单成本中。
9. 实施税费和运费处理

需要对系统进行多项修改,包括添加新的数据库表( tax shipping )、修改 orders 表、添加新的数据库函数、修改业务层类以及在表示层提供用户选择运输方式的方法。理想情况下,应清除 orders order_detail 表的内容,或考虑旧订单不包含税费和运费的情况。

以下是数据层修改的流程图:

graph TD;
    A[开始] --> B[更新存储过程];
    B --> C[创建新存储过程];
    C --> D[完成数据层修改];

以下是业务层修改的表格:
| 类 | 方法 | 说明 |
| ---- | ---- | ---- |
| Orders | GetByCustomerId() | 获取指定客户的所有订单 |
| Orders | GetOrderShortDetails() | 获取订单的简短详情 |
| Orders | UpdateOrder() | 更新订单详情 |
| Customers | GetCustomersList() | 获取所有客户列表 |

电商订单管理与税费运费处理

10. 具体实施步骤

为了实现税费和运费的处理,下面将详细介绍具体的操作步骤。

10.1 数据库表的添加与修改
  • 添加新表 :在数据库中添加 tax shipping 表,用于存储税费和运费的相关信息。
  • 修改 orders :根据新的需求,对 orders 表进行相应的修改,可能需要添加新的字段来记录税费和运费信息。
10.2 数据库函数的添加与修改
  • 添加新函数 :编写新的数据库函数,用于计算税费和运费。例如,可以创建一个函数根据客户的运输区域和订单信息计算税费,另一个函数根据运输区域和产品重量计算运费。
  • 修改现有函数 :对现有的订单处理函数进行修改,使其能够调用新的税费和运费计算函数,并将计算结果更新到订单信息中。
10.3 业务层类的修改
  • 修改 Orders :在 Orders 类中添加新的方法,用于调用数据库函数计算税费和运费,并将计算结果保存到订单对象中。例如:
// 计算并更新订单的税费和运费
public static function CalculateTaxAndShipping($orderId)
{
    // 调用数据库函数计算税费
    $tax = DatabaseHandler::CallFunction('calculate_tax', $orderId);
    // 调用数据库函数计算运费
    $shipping = DatabaseHandler::CallFunction('calculate_shipping', $orderId);

    // 更新订单信息
    Orders::UpdateOrder($orderId, null, null, null, null, $tax, $shipping);
}
  • 修改其他相关类 :根据具体需求,对其他相关的业务层类进行修改,确保整个业务流程能够正确处理税费和运费。
10.4 表示层的修改
  • 添加用户选择运输方式的界面 :在订单确认页面或结算页面添加一个下拉框或单选框,让用户选择运输方式。根据用户的选择,调用业务层的方法计算相应的运费。
<select name="shipping_method">
    {section name=i loop=$obj->mShippingMethods}
    <option value="{$obj->mShippingMethods[i].id}">{$obj->mShippingMethods[i].name} - {$obj->mShippingMethods[i].price}</option>
    {/section}
</select>
  • 显示税费和运费信息 :在订单详情页面和结算页面显示计算好的税费和运费信息,让用户清楚了解订单的总成本。
<tr>
    <td class="bold-text">税费: </td>
    <td>{$obj->mOrderInfo.tax}</td>
</tr>
<tr>
    <td class="bold-text">运费: </td>
    <td>{$obj->mOrderInfo.shipping}</td>
</tr>
11. 测试与验证

在完成所有修改后,需要对系统进行全面的测试,确保税费和运费的计算和处理功能正常工作。

11.1 测试用例设计
  • 正常情况测试 :创建不同类型的订单,选择不同的运输区域和运输方式,验证税费和运费的计算结果是否正确。
  • 边界情况测试 :测试极端情况,如订单金额为零、运输区域为空等,确保系统能够正确处理这些情况。
  • 异常情况测试 :模拟网络故障、数据库错误等异常情况,验证系统的容错能力和错误处理机制。
11.2 测试流程
graph TD;
    A[开始测试] --> B[创建测试订单];
    B --> C[选择运输区域和方式];
    C --> D[计算税费和运费];
    D --> E[验证计算结果];
    E --> F{结果是否正确};
    F -- 是 --> G[测试通过];
    F -- 否 --> H[记录错误信息];
    H --> I[修复问题];
    I --> B;
12. 总结与展望

通过以上步骤,我们实现了电商订单管理系统中税费和运费的处理功能。采用简单而可扩展的方案,为系统的后续发展奠定了基础。

在未来,可以根据实际业务需求,进一步完善税费和运费的计算逻辑。例如,考虑不同产品类型的税率差异,根据订单重量和体积动态调整运费计算方式等。同时,还可以集成更多的运输公司 API,提供更多的运输选项和实时的运费报价,提升用户体验。

以下是表示层修改的操作列表:
1. 在订单确认页面添加运输方式选择界面。
2. 在订单详情页面显示税费和运费信息。
3. 验证用户选择的运输方式是否正确更新到订单信息中。

以下是测试用例的表格:
| 测试类型 | 测试用例描述 | 预期结果 |
| ---- | ---- | ---- |
| 正常情况测试 | 创建订单,选择不同运输区域和方式 | 税费和运费计算正确 |
| 边界情况测试 | 订单金额为零,选择运输方式 | 系统正常处理,计算结果合理 |
| 异常情况测试 | 模拟网络故障,提交订单 | 系统提示错误信息,不影响数据完整性 |

MATLAB代码实现了一个基于多种智能优化算法优化RBF神经网络的回归预测模型,其核心是通过智能优化算法自动寻找最优的RBF扩展参数(spread),以提升预测精度。 1.主要功能 多算法优化RBF网络:使用多种智能优化算法优化RBF神经网络的核心参数spread。 回归预测:对输入特征进行回归预测,适用于连续值输出问题。 性能对比:对比不同优化算法在训练集和测试集上的预测性能,绘制适应度曲线、预测对比图、误差指标柱状图等。 2.算法步骤 数据准备:导入数据,随机打乱,划分训练集和测试集(默认7:3)。 数据归一化:使用mapminmax将输入和输出归一化到[0,1]区间。 标准RBF建模:使用固定spread=100建立基准RBF模型。 智能优化循环: 调用优化算法(从指定文件夹中读取算法文件)优化spread参数。 使用优化后的spread重新训练RBF网络。 评估预测结果,保存性能指标。 结果可视化: 绘制适应度曲线、训练集/测试集预测对比图。 绘制误差指标(MAE、RMSE、MAPE、MBE)柱状图。 十种智能优化算法分别是: GWO:灰狼算法 HBA:蜜獾算法 IAO:改进天鹰优化算法,改进①:Tent混沌映射种群初始化,改进②:自适应权重 MFO:飞蛾扑火算法 MPA:海洋捕食者算法 NGO:北方苍鹰算法 OOA:鱼鹰优化算法 RTH:红尾鹰算法 WOA:鲸鱼算法 ZOA:斑马算法
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值