ShippingTemplateRuleEntity.php 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. <?php
  2. declare(strict_types=1);
  3. namespace SixShop\ShippingTemplate\Entity;
  4. use SixShop\Core\Entity\BaseEntity;
  5. use SixShop\ShippingTemplate\Model\ShippingTemplateRuleModel;
  6. /**
  7. * @mixin ShippingTemplateRuleModel
  8. */
  9. class ShippingTemplateRuleEntity extends BaseEntity
  10. {
  11. /**
  12. * 根据模板ID获取默认规则
  13. */
  14. public function getDefaultRule(int $templateId): ?ShippingTemplateRuleModel
  15. {
  16. return $this->where('template_id', $templateId)
  17. ->where('area_type', 'default')
  18. ->find();
  19. }
  20. /**
  21. * 根据模板ID获取特殊区域规则
  22. */
  23. public function getSpecialRules(int $templateId): iterable
  24. {
  25. return $this->where('template_id', $templateId)
  26. ->where('area_type', 'special')
  27. ->select();
  28. }
  29. /**
  30. * 计算运费
  31. */
  32. public function calculateShippingFee(float $quantity, ?string $regionCode = null): float
  33. {
  34. // 获取模板ID
  35. $templateId = $this->template_id;
  36. // 查找适用的规则
  37. $rule = null;
  38. // 如果提供了地区编码,先检查是否匹配特殊区域规则
  39. if ($regionCode) {
  40. $specialRules = $this->getSpecialRules($templateId);
  41. foreach ($specialRules as $specialRule) {
  42. $regions = json_decode($specialRule->regions, true);
  43. if (is_array($regions) && in_array($regionCode, $regions)) {
  44. $rule = $specialRule;
  45. break;
  46. }
  47. }
  48. }
  49. // 如果没有匹配的特殊区域规则,则使用默认规则
  50. if (!$rule) {
  51. $rule = $this->getDefaultRule($templateId);
  52. }
  53. // 如果没有找到任何规则,返回0
  54. if (!$rule) {
  55. return 0.0;
  56. }
  57. // 计算运费
  58. if ($quantity <= $rule->first) {
  59. // 数量在首件/首重/首体积范围内
  60. return (float)$rule->first_price;
  61. } else {
  62. // 超出部分按续件/续重/续体积计费
  63. $excess = $quantity - $rule->first;
  64. // 简化计算,实际项目中可能需要考虑向上取整等规则
  65. $additionalFee = ceil($excess) * (float)$rule->next_price;
  66. return (float)$rule->first_price + $additionalFee;
  67. }
  68. }
  69. }