U8ThirtyPartyDatabaseServerService.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <?php
  2. namespace App\Service;
  3. use Illuminate\Support\Facades\Config;
  4. use Illuminate\Support\Facades\DB;
  5. use Illuminate\Support\Facades\Log;
  6. class U8ThirtyPartyDatabaseServerService extends Service
  7. {
  8. protected $connectionName = '';
  9. public function __construct($data)
  10. {
  11. $this->createConnection($data);
  12. }
  13. private function createConnection($data)
  14. {
  15. $mainConnName = $data['connect_name'];
  16. $this->connectionName = $mainConnName;
  17. // 创建连接
  18. $mainConfig = [
  19. 'driver' => 'sqlsrv',
  20. 'host' => $data['api_host'],
  21. 'port' => $data['database_port'],
  22. 'database' => $data['database'],
  23. 'username' => $data['username'],
  24. 'password' => $data['password'],
  25. 'options' => [
  26. \PDO::SQLSRV_ATTR_QUERY_TIMEOUT => 15, // 减少超时
  27. \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
  28. ],
  29. ];
  30. // 配置注入
  31. Config::set("database.connections.{$mainConnName}", $mainConfig);
  32. }
  33. public function getStockCountByCategory()
  34. {
  35. try {
  36. $result = DB::connection($this->connectionName)
  37. ->table('Inventory as i')
  38. ->lock('WITH(NOLOCK)')
  39. ->join('InventoryClass as ic', 'i.cInvCCode', '=', 'ic.cInvCCode')
  40. ->join('CurrentStock as s', 'i.cInvCode', '=', 's.cInvCode')
  41. ->select([
  42. 'ic.cInvCCode as category_code',
  43. 'ic.cInvCName as category_name',
  44. DB::raw('SUM(s.iQuantity) as total_quantity')
  45. ])
  46. ->groupBy('ic.cInvCCode', 'ic.cInvCName')
  47. ->orderBy('ic.cInvCCode', 'ASC')
  48. ->get()
  49. ->map(function($item) {
  50. return [
  51. 'category_code' => trim($item->category_code),
  52. 'category_name' => trim($item->category_name),
  53. 'total_quantity' => (float)$item->total_quantity,
  54. ];
  55. })
  56. ->toArray();
  57. return [true, $result];
  58. } catch (\Throwable $e) {
  59. return [false, $e->getMessage()];
  60. }
  61. }
  62. public function getStockCountWithPercentage()
  63. {
  64. try {
  65. // 1. 获取基础数据:明细分类库存
  66. $details = DB::connection($this->connectionName)
  67. ->table('Inventory as i')
  68. ->lock('WITH(NOLOCK)')
  69. ->join('InventoryClass as ic', 'i.cInvCCode', '=', 'ic.cInvCCode')
  70. ->join('CurrentStock as s', 'i.cInvCode', '=', 's.cInvCode')
  71. ->select([
  72. 'ic.cInvCCode as sub_code', // 明细编码 (如 0102)
  73. 'ic.cInvCName as sub_name', // 明细名称
  74. DB::raw('SUM(s.iQuantity) as sub_quantity')
  75. ])
  76. ->groupBy('ic.cInvCCode', 'ic.cInvCName')
  77. ->get();
  78. // 2. 转换数据结构,按大类进行逻辑汇总
  79. $collection = $details->map(function ($item) {
  80. return [
  81. 'parent_code' => substr(trim($item->sub_code), 0, 2), // 截取前两位作为大类编码
  82. 'sub_code' => trim($item->sub_code),
  83. 'sub_name' => trim($item->sub_name),
  84. 'sub_quantity' => (float)$item->sub_quantity,
  85. ];
  86. });
  87. // 3. 计算每个大类的总数 (以 parent_code 分组求和)
  88. $parentTotals = $collection->groupBy('parent_code')->map(function ($group) {
  89. return $group->sum('sub_quantity');
  90. });
  91. // 4. 组装最终结果,合并大类总数并计算百分比
  92. $result = $collection->map(function ($item) use ($parentTotals) {
  93. $parentSum = $parentTotals[$item['parent_code']] ?? 0;
  94. // 计算占比:(子类数量 / 父类总数) * 100
  95. $percentage = $parentSum > 0
  96. ? round(($item['sub_quantity'] / $parentSum) * 100, 2)
  97. : 0;
  98. return [
  99. 'parent_category_code' => $item['parent_code'],
  100. 'category_code' => $item['sub_code'],
  101. 'category_name' => $item['sub_name'],
  102. 'total_quantity' => $item['sub_quantity'],
  103. 'parent_total' => $parentSum,
  104. 'percentage' => $percentage, // 格式化为百分比字符串
  105. ];
  106. })->values()->toArray();
  107. return [true, $result];
  108. } catch (\Throwable $e) {
  109. return [false, $e->getMessage()];
  110. }
  111. }
  112. /**
  113. * 更新销售订单明细表 (SO_SODetails) 的 FPurQuan 字段
  114. * * @param array $data 包含 sale_order_details 的数组
  115. */
  116. public function updateSaleOrderDetails($data)
  117. {
  118. // 2. 开启事务执行更新
  119. $db = DB::connection($this->connectionName);
  120. $db->beginTransaction();
  121. try {
  122. foreach ($data['sale_order_details'] as $item) {
  123. $autoId = $item['erp_sale_dt_id'];
  124. $quantity = floatval($item['quantity']);
  125. // 3. 执行更新
  126. // U8 销售订单子表表名为 SO_SODetails,主键通常是 iSOsID (在某些版本也叫 AutoID)
  127. // 根据你的描述,FPurQuan 是我们要更新的目标字段
  128. $db->table('SO_SODetails')
  129. ->where('AutoID', $autoId) // 请根据你数据库实际字段名确认是 AutoID 还是 iSOsID
  130. ->update([
  131. 'fPurQuan' => $quantity,
  132. ]);
  133. }
  134. $db->commit();
  135. return [true, ''];
  136. } catch (\Throwable $e) {
  137. $db->rollBack();
  138. return [false, '操作失败:' . $e->getMessage()];
  139. }
  140. }
  141. }