Forráskód Böngészése

Merge branch 'feature/EK-3320' of guanli/ngds into master

ryan001 1 hónapja
szülő
commit
1b91ecb848

+ 8 - 4
backendApi/config/params.php

@@ -24,6 +24,10 @@ return [
         'v1/calc/record-list',
         'v1/calc/auto-calc',
         'v1/shop/order-period-adjust-batch',
+        'v1/shop/order-invoice-remark',
+        'v1/shop/order-invoice-method',
+        'v1/shop/order-invoice-export',
+        'v1/shop/order-invoice-export-file',
 //        'v1/site/countries'
     ],
     'noCheckPermissionActions' => [
@@ -83,10 +87,6 @@ return [
         'demo/ipayments',
         'article/detail',
         'admin/change-language',
-//        'currency/currencies-conversions',
-//        'currency/set-currencies-conversions',
-//        'transportation/transportation',
-//        'transportation/set-transportation',
         'bonus/auto-calc',
         'bonus/calc-period',
         'bonus/close-period',
@@ -95,5 +95,9 @@ return [
         'calc/record-list',
         'calc/auto-calc',
         'shop/order-period-adjust-batch',
+        'shop/order-invoice-remark',
+        'shop/order-invoice-method',
+        'shop/order-invoice-export',
+        'shop/order-invoice-export-file',
     ],
 ];

+ 4 - 0
backendApi/config/urlManagerRules.php

@@ -56,6 +56,10 @@ return [
             'GET dec-order-list-export' => 'dec-order-list-export',
             'POST delete-order' => 'delete-order',
             'GET order-list' => 'order-list',
+            'GET order-invoice-method' => 'order-invoice-method',
+            'POST order-invoice-remark' => 'order-invoice-remark',
+            'GET order-invoice-export/<orderSn>' => 'order-invoice-export',
+            'GET order-invoice-export-file/<orderSn>' => 'order-invoice-export-file',
             'GET order-list-export' => 'order-list-export',
             'POST order-delivery' => 'order-delivery',
             'POST order-refund' => 'order-refund',

+ 102 - 0
backendApi/modules/v1/controllers/ShopController.php

@@ -32,6 +32,7 @@ use common\models\Currency;
 use common\models\CurrencyConversions;
 use common\models\DeclarationPackage;
 use common\models\DecOrder;
+use common\models\Export;
 use common\models\FlowWallet;
 use common\models\forms\DecPackageForm;
 use common\models\forms\ExcelOrderDecForm;
@@ -39,6 +40,7 @@ use common\models\forms\ExcelOrderShopForm;
 use common\models\forms\ExcelOrderStandardForm;
 use common\models\forms\OrderDeleteForm;
 use common\models\forms\OrderForm;
+use common\models\forms\OrderInvoiceRemarkForm;
 use common\models\forms\OrderPeriodAdjustForm;
 use common\models\forms\ShopGoodsForm;
 use common\models\forms\UploadForm;
@@ -49,6 +51,7 @@ use common\models\ShopGoods;
 use common\models\ShopGoodsNature;
 use common\models\User;
 use common\models\UserInfo;
+use common\helpers\Tool;
 use Yii;
 use yii\web\HttpException;
 use yii\web\UploadedFile;
@@ -451,6 +454,32 @@ class ShopController extends BaseController {
         }
     }
 
+    /**
+     * @throws Exception
+     * @throws HttpException
+     */
+    public function actionOrderInvoiceRemark() {
+        if (\Yii::$app->request->isPost) {
+            $formModel = new OrderInvoiceRemarkForm();
+            if ($formModel->load(\Yii::$app->request->post(), '') && $result = $formModel->remarkOrderInvoice()) {
+
+                return static::notice(\Yii::t('ctx', 'successfully'));
+            } else {
+                return static::notice(Form::formatErrorsForApi($formModel->getErrors()), 400);
+            }
+        }
+    }
+
+    /**
+     * 订单发票支付方式
+     * @return mixed
+     * @throws Exception
+     * @throws HttpException
+     */
+    public function actionOrderInvoiceMethod() {
+        return static::notice(['method'=>['Cash', 'Credit Card', 'Direct Banking', 'Cheque']]);
+    }
+
     /**
      * 订单表
      * @return mixed
@@ -805,6 +834,55 @@ class ShopController extends BaseController {
         return static::notice(\Yii::t('ctx', 'startExporting')); // 导出开始,请到文件管理-导出文件查看
     }
 
+    public function actionOrderInvoiceExport()
+    {
+        $orderSn = \Yii::$app->request->get('orderSn');
+
+        $filter = $this->filterCondition([
+            'SN'=> 'O.SN',
+        ]);
+
+        $filter['condition'] = ' O.IS_DELETE=0 AND O.SN=:SN';
+        $filter['params'] = [':SN' => $orderSn];
+
+        // 生成发票编号
+        $order = Order::find()
+            ->alias('O')
+            ->select('O.*,CS.CODE AS COUNTRY_CODE')
+            ->where(['SN' => $orderSn])
+            ->join('LEFT JOIN', Countries::tableName() . ' AS CS', 'CS.ID=O.COUNTRY_ID')
+            ->asArray()->one();
+        if (!$order) {
+            return static::notice('订单不存在', 400);
+        }
+        if (!$order['INVOICE_NO']) {
+            $invoiceNo = $this->generateInvoiceNo($order['COUNTRY_CODE']);
+            Order::updateAll(['INVOICE_NO' => $invoiceNo], 'SN = :SN', [':SN' => $orderSn]);
+        }
+
+        $form = new ShopExportForm();
+        $result = $form->run($filter, \Yii::t('ctx', 'actionOrderInvoiceExport'),null,$orderSn);
+        if (!$result) {
+            return static::notice(Form::formatErrorsForApi($form->getErrors()), 400);
+        }
+        return static::notice(\Yii::t('ctx', 'startExporting')); // 导出开始,请到文件管理-导出文件查看
+    }
+
+    public function actionOrderInvoiceExportFile()
+    {
+        $orderSn = \Yii::$app->request->get('orderSn');
+
+        //查找最新的导出文件
+        $data = Export::find()
+            ->where(['REMARK' => $orderSn])
+            ->orderBy(['CREATED_AT' => SORT_DESC])
+            ->one();
+        if (!$data || $data['IS_EXPORTING']) {
+            return static::notice('导出进行中', 400);
+        }
+        return static::notice($data);
+    }
+
     /**
      * 报单表导出
      * @return mixed
@@ -1103,4 +1181,28 @@ class ShopController extends BaseController {
 
         return static::notice('成功. ' . json_encode($orderErr));
     }
+
+    public function generateInvoiceNo($country_code = '')
+    {
+        $prefix = 'Inv'.$country_code;
+        $currentDate = date('dmY');
+        
+        // 查询今天生成的最新发票号(包含当天日期格式的)
+        $order = Order::find()
+            ->where(['STATUS' => 1, 'IS_DELETE' => 0])
+            ->andWhere(['like', 'INVOICE_NO', $prefix . $currentDate])
+            ->orderBy(['INVOICE_NO' => SORT_DESC])
+            ->one();
+
+        if (!$order || !$order->INVOICE_NO) {
+            // 如果今天没有生成过发票号或没有符合条件的订单,从00001开始
+            $no = '00001';
+        } else {
+            $invoiceNo = $order->INVOICE_NO;
+            // 截取最后5位数字部分并+1
+            $no = sprintf('%05d', intval(substr($invoiceNo, -5)) + 1);
+        }
+
+        return $prefix . $currentDate . $no;
+    }
 }

+ 3 - 2
backendApi/modules/v1/models/exportForms/BaseExportForm.php

@@ -18,14 +18,15 @@ class BaseExportForm extends Model
      * @param $filter
      * @param $listName
      * @param null $consoleRouter
+     * @param null $remark
      * 不传值默认导出controller、action和console里面的controller、action一致
      * @return bool
      * @throws \yii\db\Exception
      */
-    public function export($filter, $listName, $consoleRouter = null){
+    public function export($filter, $listName, $consoleRouter = null,$remark = null){
         $transaction = \Yii::$app->db->beginTransaction();
         try {
-            $this->exportObj->exportHandle($filter, $listName, $consoleRouter);
+            $this->exportObj->exportHandle($filter, $listName, $consoleRouter,$remark);
             $transaction->commit();
             return true;
         } catch (Exception $e) {

+ 3 - 2
backendApi/modules/v1/models/exportForms/ShopExportForm.php

@@ -11,12 +11,13 @@ class ShopExportForm extends BaseExportForm
      * @param $filter
      * @param $listName
      * @param null $consoleRouter
+     * @param null $remark
      * @return bool
      * @throws \yii\db\Exception
      */
-    public function run($filter, $listName, $consoleRouter = null){
+    public function run($filter, $listName, $consoleRouter = null,$remark = null){
         $this->exportObj = ShopExport::instance();
-        return $this->export($filter, $listName, $consoleRouter);
+        return $this->export($filter, $listName, $consoleRouter,$remark);
     }
 
 

+ 2 - 0
backendApi/modules/v1/models/lists/shop/OrderList.php

@@ -384,6 +384,8 @@ class OrderList extends \common\libs\dataList\DataList implements DataListInterf
                         return $row['AUTO_MAINTENANCE'] == 1 ? \Yii::t('ctx', 'yes') : \Yii::t('ctx', 'no');
                     },
                 ],
+                'INVOICE_REMARK' => null,
+                'METHOD' => null,
             ];
         }
         return $this->columns;

+ 31 - 0
common/helpers/Tool.php

@@ -11,6 +11,8 @@ namespace common\helpers;
 
 use common\models\AlarmCall;
 use common\models\ApproachOrderCall;
+use common\models\Countries;
+use common\models\Order;
 use Faker\Provider\Uuid;
 use Yii;
 use yii\helpers\Url;
@@ -627,4 +629,33 @@ class Tool {
 
         return ($amount / $beforeRate) * $afterRate;
     }
+
+    /**
+     * 生成发票号
+     * @param $countryId
+     * @return string
+     */
+    public static function generateInvoiceNo()
+    {
+        $prefix = 'Inv';
+        $currentDate = date('dmY');
+        
+        // 查询今天生成的最新发票号(包含当天日期格式的)
+        $order = Order::find()
+            ->where(['STATUS' => 1, 'IS_DELETE' => 0])
+            ->andWhere(['like', 'INVOICE_NO', $prefix . $currentDate])
+            ->orderBy(['INVOICE_NO' => SORT_DESC])
+            ->one();
+
+        if ($order && !empty($order->INVOICE_NO)) {
+            $invoiceNo = $order->INVOICE_NO;
+            // 截取最后5位数字部分并+1
+            $no = sprintf('%05d', intval(substr($invoiceNo, -5)) + 1);
+        } else {
+            // 如果今天没有生成过发票号或没有符合条件的订单,从00001开始
+            $no = '00001';
+        }
+
+        return $prefix . $currentDate . $no;
+    }
 }

+ 1 - 1
common/libs/dataList/DataList.php

@@ -464,4 +464,4 @@ class DataList extends Model
             $this->columns = [];
         }
     }
-}
+}

+ 477 - 11
common/libs/export/BaseExport.php

@@ -18,12 +18,14 @@ use common\models\BaApproachOrderGoods;
 use common\models\BaOrder;
 use common\models\BaOrderGoods;
 use common\models\BaUser;
+use common\models\Currency;
 use common\models\Export;
 use common\models\Order;
 use common\models\OrderGoods;
 use common\models\Region;
 use common\models\ShopGoods;
 use common\models\User;
+use console\helpers\Logger;
 use Yii;
 use yii\base\Exception;
 use yii\base\InvalidConfigException;
@@ -157,15 +159,15 @@ class BaseExport extends Component {
      */
     public function getSavePath() {
         $this->savePath = $this->pathCreator(date('Ymd', Date::nowTime()));
-        return trim($this->savePath, __DS__);
+        return trim((string)$this->savePath, __DS__);
     }
 
     /**
      * @return bool|string|null
      */
     public function getSaveBasePath() {
-        $this->saveBasePath = Yii::getAlias('@backendApi') . __DS__ . 'web' . __DS__ . 'upload' . __DS__ . \Yii::$app->params['excelLocalDir'];
-        return trim($this->saveBasePath, __DS__);
+        $this->saveBasePath = Yii::getAlias('@backendApi') . __DS__ . 'web' . __DS__ . 'upload' . __DS__ . (isset(\Yii::$app->params['excelLocalDir']) ? \Yii::$app->params['excelLocalDir'] : '');
+        return trim((string)$this->saveBasePath, __DS__);
     }
 
     /**
@@ -190,7 +192,7 @@ class BaseExport extends Component {
      */
     public function getParams() {
         $this->params = CacheHelper::getAsyncParams($this->taskId);
-        
+
         // 设置语言
         Yii::$app->language = $this->params['language'] ?? 'en-US';
         Yii::$app->sourceLanguage = Yii::$app->language == 'zh-CN' ? 'en-US' : 'zh-CN';
@@ -466,14 +468,16 @@ class BaseExport extends Component {
      * @param $filter
      * @param $listName
      * @param null $consoleRouter
+     * @param null remark
      * @throws Exception
      */
-    public function exportHandle($filter, $listName, $consoleRouter = null){
+    public function exportHandle($filter, $listName, $consoleRouter = null,$remark = null){
         $params = [
             'moduleId' => $this->moduleId,
             'listName' => $listName,
             'action' => $consoleRouter ? $consoleRouter : Yii::$app->controller->id.'/'.Yii::$app->controller->action->id, // 这里这么写,是因为调用的异步路由和同步的控制器和方法是一样的,所以,只要不传默认调和同步一样的异步方法
             'userId' => Yii::$app->user->id,
+            'remark' => $remark,
         ];
         $this->webToAsync($params,$filter);
     }
@@ -817,7 +821,7 @@ ORDER;
             // 设置行高
             $pdf->setCellHeightRatio(1);
             // 设置左、上、右的间距
-            $pdf->SetMargins('10', '0', '10');
+            $pdf->SetMargins('30', '70', '30');
             // 设置是否自动分页  距离底部多少距离时分页
             $pdf->SetAutoPageBreak(TRUE, '15');
             // 设置图像比例因子
@@ -829,14 +833,15 @@ ORDER;
             $pdf->setFontSubsetting(true);
             $pdf->AddPage();
             // 设置字体
-            $pdf->SetFont('stsongstdlight', '', 10, '', true);
+            $pdf->SetFont('dejavusans', '', 10, '', true);
             //        $image_file = \Yii::$app->basePath . '/../frontendEle/src/static/img/ngds-logo.jpg';
 //        if (!file_exists($image_file)) {
 //            $image_file = \Yii::$app->runtimePath . '/../common/uploads/ngds-logo.jpg';
 //        }
-            $image_file = \Yii::$app->basePath . '/../ngds-logo.jpg';
-            $image = file_get_contents($image_file);
-            $pdf->Image('@' . $image, 15, 12, 20, 7, 'JPG');
+            // $image_file = \Yii::$app->basePath . '/../ngds-logo.jpg';
+            // $image = file_get_contents($image_file);
+            // 将图像放在右上角,根据页面宽度和边距计算位置
+            // $pdf->Image('@' . $image, $pdf->getPageWidth() - 45, 25, 30, 10, 'JPG');
             $pdf->writeHTML($context);
 
             $result = $pdf->Output($realFile, 'F');
@@ -1258,7 +1263,7 @@ ORDER;
                     'FRONT_REMARK' => $columnData['FRONT_REMARK'],
                     'DELIVERY_STATUS_NAME' => Tool::paramConvert(\Yii::$app->params['deliveryStatus'])[$columnData['DELIVERY_STATUS']]['label'] ?? '',
                 ];
-                
+
                 fputcsv($this->_fp, Tool::arrTextConvert($columnAccept));
                 unset($percent, $columnData, $columnAccept);
             }
@@ -1528,4 +1533,465 @@ ORDER;
         $this->complete();
         return true;
     }
+
+    /**
+     * 生成
+     * @return bool
+     * @throws Exception
+     * @throws InvalidConfigException
+     * @throws \yii\httpclient\Exception
+     */
+    public function actionOrderInvoiceExport() {
+        $this->getParams();
+        if (!$this->params) {
+            throw new Exception('无法获取需要的参数');
+        }
+        $path = __DS__ . $this->getSaveBasePath() . __DS__ . $this->getSavePath();
+        $realFile = $this->mkdir($path) . __DS__ . $this->getFileName('.pdf');
+
+        $this->completed = false;
+        $this->getExportId();
+        $this->getUserId();
+        $fileNameUpdated = false;
+
+        // 获取列表数据及表头
+        $this->_listModel = new $this->listModelClass();
+        $this->_listModel->isExport = true;
+
+        // 查询订单数据
+        // 使用新的查询对象,禁用查询缓存,确保获取最新数据
+        $query = OrderGoods::find()
+            ->alias('OG')
+            ->where($this->params['condition'], $this->params['params'])
+            ->select('OG.ID AS AID,O.*,U.REAL_NAME,U.DEC_ID,SG.CATEGORY_TYPE,OG.REAL_PRICE,OG.TAX_RATE,OG.BUY_NUMS,OG.SKU_CODE,OG.GOODS_TITLE,OG.REAL_PV')
+            ->join('LEFT JOIN', ORDER::tableName() . ' AS O', 'OG.ORDER_SN=O.SN')
+            ->join('LEFT JOIN', User::tableName() . ' AS U', 'U.ID=O.USER_ID')
+            ->join('LEFT JOIN', ShopGoods::tableName() . ' AS SG', 'SG.ID=OG.GOODS_ID')
+            ->asArray()
+            ->noCache(); // 禁用查询缓存
+
+        // 添加详细的调试信息
+        $rawSql = $query->createCommand()->getRawSql();
+        $oderList = $query->all();
+
+        $sn = $oderList[0]['SN'];
+        // 同时使用原生SQL查询进行对比测试
+        $nativeConnection = Yii::$app->db;
+        $nativeQuery = "
+            SELECT 
+             `OG`.`ID` AS `AID`, 
+             `O`.*, 
+             `U`.`REAL_NAME`, 
+             `U`.`DEC_ID`, 
+             `SG`.`CATEGORY_TYPE`, 
+             `OG`.`REAL_PRICE`, 
+             `OG`.`TAX_RATE`, 
+             `OG`.`BUY_NUMS`, 
+             `OG`.`SKU_CODE`, 
+             `OG`.`GOODS_TITLE`, 
+             `OG`.`REAL_PV` 
+        FROM 
+             `AR_ORDER_GOODS` `OG` 
+             LEFT JOIN `AR_ORDER` `O` ON OG.ORDER_SN = O.SN 
+             LEFT JOIN `AR_USER` `U` ON U.ID = O.USER_ID 
+             LEFT JOIN `AR_SHOP_GOODS` `SG` ON SG.ID = OG.GOODS_ID 
+        WHERE 
+             O.IS_DELETE = 0 
+             AND O.SN = '{$sn}' 
+        ORDER BY 
+             `O`.`CREATED_AT` DESC";
+        $nativeResults = $nativeConnection->createCommand($nativeQuery)->queryAll();
+
+        // 如果原生查询有结果但Yii查询没有,使用原生查询结果
+        if(count($nativeResults) > 0 && count($oderList) < count($nativeResults)) {
+            $oderList = $nativeResults;
+        }
+
+        if ($oderList) {
+            $userId = '';
+            $userName = '';
+            $address = '';
+            $mobile = $oderList[0]['MOBILE'];
+            $orderAt = Date::convert($oderList[0]['CREATED_AT'],'d/m/Y');
+            $orderDetails = '';
+            $orderDetails_bv = '';
+            $orderSn = $oderList[0]['SN'];;
+            $orderAmount = 0;  // 合计总额
+            $orderNums = 0; // 合计总数
+            $totalTaxAmount = 0; // 合计税额
+            $totalAmount = 0;
+            $paymentStatus = 'Paid'; // 支付状态
+            $invoiceRemark = $oderList[0]['INVOICE_REMARK'];
+            $paymentMethod = $oderList[0]['METHOD']??'Cash'; // 支付方式
+            $currency = Currency::findOne($oderList[0]['CURRENCY_ID'])['CODE'] ?? '';;
+            $invoiceNo = $oderList[0]['INVOICE_NO'];
+
+            $provinceName = $oderList[0]['PROVINCE'] ? Region::getCnName($oderList[0]['PROVINCE']) : '';
+            $cityName = $oderList[0]['CITY'] ? Region::getCnName($oderList[0]['CITY']) : '';
+            $countyName = $oderList[0]['COUNTY'] ? Region::getCnName($oderList[0]['COUNTY']) : '';
+            $address = $provinceName . $cityName . $countyName . $oderList[0]['ADDRESS'];
+
+            $paymentStatus = \Yii::$app->params['orderStatus'][$oderList[0]['STATUS']]['label'] ?? 'Paid';
+
+            $orderTotalBv = 0;
+            $orderTotalTaxAmount = 0;
+            $orderTotalAmount = 0;
+            $orderTotal = 0;
+            $orderTotalQuantity = count($oderList);
+
+            $no = 0;
+            foreach ($oderList as $key => $value) {
+                $no += 1;
+
+                $userId = $value['USER_NAME'];
+                $userName = $value['REAL_NAME'];
+
+                // 总价
+                $totalAmount = $value['BUY_NUMS'] * $value['REAL_PRICE'];
+                $orderAmount += $totalAmount;
+                $orderNums += $value['BUY_NUMS'];
+                // 税额
+                $taxAmount = Tool::calculateTax($value['REAL_PRICE'], $value['TAX_RATE'], $value['BUY_NUMS']);
+                $totalTaxAmount += $taxAmount;
+                $totalBv = $value['BUY_NUMS'] * $value['REAL_PV'];
+                $orderTotalBv += $totalBv;
+
+                $orderTotalTaxAmount += $taxAmount;
+                $orderTotalAmount += $totalAmount - $taxAmount;
+                $orderTotal += $totalAmount;
+
+                $totalBvFormat = Tool::formatAmount($totalBv);
+                $taxableAmountFormat =Tool::formatAmount($taxAmount);
+                $vatAmountFormat = Tool::formatAmount($totalAmount - $taxAmount);
+                $totalFormat = Tool::formatAmount($totalAmount);
+                $vatRateFormat = Tool::formatAmount($value['TAX_RATE']) . '%';
+                $unitPriceFormat = Tool::formatAmount($value['REAL_PRICE']);
+                $unitBvFormat = Tool::formatAmount($value['REAL_PV']);
+
+                // 订单详情
+                //ek-3391 Taxable Amount和VAT Amount字段取值错误(两个取值取反了),需要修改 (2025/11/25 13:35 Ryan)
+                $orderDetails .= <<<EOT
+                <tr style="text-align: left; font-weight: normal; font-size: 12px; width: 100%; padding: 5px 5px;">
+                    <td style="white-space: nowrap;">{$no}</td>
+                    <td>{$value['SKU_CODE']}</td>
+                    <td>{$value['GOODS_TITLE']}</td>
+                    <td>{$value['BUY_NUMS']}</td>
+                    <td>{$unitPriceFormat}</td>
+<!--                    <td>{$unitBvFormat}</td>-->
+<!--                    <td>{$totalBvFormat}</td>-->
+                    <td colspan="2">{$vatAmountFormat}</td> 
+                    <td>{$vatRateFormat}</td>
+                    <td colspan="2">{$taxableAmountFormat}</td>
+                    <td>{$totalFormat}</td> 
+                </tr>
+EOT;
+                $orderDetails_bv .= <<<EOT
+                    <td>{$value['SKU_CODE']}</td>
+                    <td>{$value['BUY_NUMS']}</td>
+                    <td>{$unitBvFormat}</td>
+                    <td>{$totalBvFormat}</td>
+EOT;
+            }
+
+            $memberCode = Yii::t('app', 'memberCode');
+            $memberName = Yii::t('app', 'memberName');
+            $memberAddress = Yii::t('app', 'memberAddress');
+            $memberPhone = Yii::t('app', 'memberPhone');
+            $orderCode = Yii::t('app', 'orderCode');
+            $taxInvoice = Yii::t('app', 'taxInvoice');
+            $productCode = Yii::t('app', 'productCode');
+            $productName = Yii::t('app', 'productName');
+            $productPrice = Yii::t('app', 'productPrice');
+            $quantity = Yii::t('app', 'qty');
+            $taxRate = Yii::t('app', 'taxRate');
+            $totalTax = Yii::t('app', 'totalTax');
+            $totalAmount = Yii::t('app', 'totalAmount');
+            $total = Yii::t('app', 'total');
+            $signature = Yii::t('app', 'signature');
+            $date = Yii::t('app', 'date');
+            $createAt = Yii::t('app', 'createAt');
+
+            $l['a_meta_charset'] = 'UTF-8';
+            $l['a_meta_dir'] = 'ltr';
+            $l['a_meta_language'] = 'zh';
+            $l['w_page'] = '页面';
+
+            $orderAmount = Tool::formatAmount($orderAmount);
+            $totalTaxAmount = Tool::formatAmount($totalTaxAmount);
+
+            $orderTotalBv = Tool::formatAmount($orderTotalBv);
+            $orderTotalTaxAmount = Tool::formatAmount($orderTotalTaxAmount);
+            $orderTotalAmount = Tool::formatAmount($orderTotalAmount);
+            $orderTotal = Tool::formatAmount($orderTotal);
+
+            $context = <<<ORDER
+        <!doctype html>
+        <html lang="en">
+            <head>
+                <meta charset="UTF-8" />
+                <title>{$taxInvoice}</title>
+                <style>
+                    table {
+                        border-collapse: collapse;
+                    }
+                    table td, table th {
+                        border: 1px solid #ccc;
+                        border-collapse: collapse;
+                    }
+                    .bg {
+                        background-color: #ccc;
+                    }
+                    
+                    /* 无边框表格样式类 */
+                    .table-noborder {
+                      border-collapse: collapse; /* 合并边框(避免残留间隙) */
+                      border-spacing: 0; /* 清除单元格之间的默认间隙 */
+                      empty-cells: show; /* 不影响空单元格(可选,避免意外显示) */
+                    }
+                    /* 清除 table、th、td 的所有边框 */
+                    .table-noborder,
+                    .table-noborder th,
+                    .table-noborder td {
+                      border: none !important; /* !important 可选,用于覆盖冲突样式 */
+                      outline: none; /* 清除可能的默认轮廓(可选) */
+                    }
+                </style>
+            </head>
+            <body style="font-weight: normal; margin: 0; padding: 0; line-height: 1.3;">
+                <div class="content" style="line-height: 1.3; font-weight: normal;">
+                    <div style="display: flex; justify-content: space-between; align-items: flex-start; width: 100%;">
+                        <div style="width: 70%;">
+                            <p style="text-align: left; font-weight: bold; font-size: 16px; margin: 0 !important; padding: 0 !important; line-height: 1.3 !important;"><b>TAX INVOICE</b></p>
+                            <p style="text-align: left; font-size: 14px; margin: 0 !important; padding: 0 !important; line-height: 1.3 !important;">ELKEN ARABIYA GENERAL TRADING CO. LLC</p>
+                            <p style="text-align: left; font-size: 13px; margin: 0 !important; padding: 0 !important; line-height: 1.3 !important;">Shop No.2, Plot 356-1142, Juneirah Street, Umm Suqeim 1, Dubai, UAE</p>
+                            <p style="text-align: left; font-size: 13px; margin: 0 !important; padding: 0 !important; line-height: 1.3 !important;">Phone: +971042296118</p>
+                            <p style="text-align: left; font-size: 13px; margin: 0 !important; padding: 0 !important; line-height: 1.3 !important;">License No: 1314319</p>
+                            <p style="text-align: left; font-size: 13px; margin: 0 !important; padding: 0 !important; line-height: 1.3 !important;">VAT No: 105034822400003</p>
+                        </div>
+                        <div style="width: 25%; text-align: right;">
+                            <!-- 图像将通过TCPDF直接插入 -->
+                        </div>
+                    </div>
+                    
+                    <hr />
+                    <br>
+                    <br>
+                    <div style="width: 100%; line-height: 15px; margin-left: 0; margin-right: 0; margin-top: 0; margin-bottom: 0; padding: 0;">
+                        <table class="table-noborder" width="100%">
+                            <tr style="text-align: left; font-size: 12px; font-weight: normal; height: 50px; vertical-align: middle;">
+                                <td>
+                                    Bill to
+                                </td>
+                                <td>
+                                    Invoice No.: {$invoiceNo}
+                                </td>
+                            </tr>
+                            <tr style="text-align: left; font-size: 12px; font-weight: normal; height: 50px; vertical-align: middle;">
+                                <td>
+                                    Name of Distributor: {$userName}
+                                </td>
+                                <td>
+                                    Date: {$orderAt}
+                                </td>
+                            </tr>
+                            <tr style="text-align: left; font-size: 12px; font-weight: normal; height: 50px; vertical-align: middle;">
+                                <td>
+                                    Member ID: {$userId}
+                                </td>
+                                <td>
+                                    Payment status: {$paymentStatus}
+                                </td>
+                            </tr>
+                            <tr style="text-align: left; font-size: 12px; font-weight: normal; height: 50px; vertical-align: middle;">
+                                <td colspan="2">
+                                    Address: {$address}
+                                </td>
+                            </tr>
+                            <tr style="text-align: left; font-size: 12px; font-weight: normal; height: 50px; vertical-align: middle;">
+                                <td colspan="2">
+                                    Contact: {$mobile}
+                                </td>
+                            </tr>
+                        </table>
+                        
+                        <br />
+                        <br />
+                        <br />
+                        
+                        <table style="table-layout: fixed;" width="100%">
+                            <tr style="text-align: left; font-weight: normal; font-size: 12px;">
+                                <th style="width: 5%; white-space: nowrap;">No.</th>
+                                <th style="width: 10%; white-space: normal; word-break: break-word;">Product Code</th>
+                                <th style="width: 19%; white-space: normal; word-break: break-word;">Product Name</th>
+                                <th style="width: 8%; white-space: nowrap;">Quantity</th>
+                                <th style="width: 10%; white-space: normal; word-break: break-word;">Unit Price ({$currency})</th>
+                                <th style="width: 14%; white-space: normal; word-break: break-word;" colspan="2">Taxable Amount ({$currency})</th>
+                                <th style="width: 8%; white-space: normal; word-break: break-word;">VAT Rate</th>
+                                <th style="width: 16%; white-space: normal; word-break: break-word;" colspan="2">VAT Amount ({$currency})</th>
+                                <th style="width: 10%; white-space: normal; word-break: break-word;">Total ({$currency})</th>
+                            </tr>
+                            {$orderDetails}
+                        </table>
+                            
+                        <table style="table-layout: fixed;" class="table-noborder">
+                            <tr><td colspan="11"></td></tr>
+                            <tr><td colspan="11"></td></tr>
+                        </table>
+                        
+                        <table style="table-layout: fixed;">  
+                            <tr style="text-align: left; font-weight: normal; font-size: 12px;">
+                                <td class="table-noborder" style="width: 5%; white-space: nowrap;"></td>
+                                <td style="width: 29%; text-align: left; background-color: lightslategray;" colspan="2">Grand Total</td>
+                                <td style="width: 8%; text-align: left; background-color: lightslategray;">{$orderTotalQuantity}</td>
+                                <td style="width: 10%; text-align: left; background-color: lightslategray;"></td>
+                                <td style="width: 14%; text-align: left; background-color: lightslategray;" colspan="2">{$orderTotalAmount}</td>
+                                <td style="width: 8%; text-align: left; background-color: lightslategray;"></td>
+                                <td style="width: 16%; text-align: left; background-color: lightslategray;" colspan="2">{$orderTotalTaxAmount}</td>
+                                <td style="width: 10%; text-align: left; background-color: lightslategray;">{$orderTotal}</td>
+                            </tr>
+                        </table>
+                        
+                        <table style="table-layout: fixed;" class="table-noborder">    
+                            <tr>
+                                <td colspan="11"></td>
+                            </tr>
+                        </table>    
+                        
+                        <table style="table-layout: fixed;" width="100%">
+                            <tr style="text-align: left; font-weight: normal; font-size: 12px;">
+                                <td colspan="7" class="table-noborder"></td>
+                                <td style="text-align: left; background-color: lightgoldenrodyellow;" colspan="2" >Total Amount</td>
+                                <td style="text-align: left; background-color: lightgoldenrodyellow;" colspan="2">{$currency}{$orderAmount}</td>
+                            </tr>
+                        </table>
+                        
+                        <table style="table-layout: fixed;" class="table-noborder">    
+                            <tr>
+                                <td colspan="11"></td>
+                            </tr>
+                        </table> 
+                        
+                        <table style="table-layout: fixed;" class="table-noborder">
+                            <tr style="text-align: left; font-weight: normal; font-size: 12px;">
+                                <td colspan="7"></td>
+                                <td colspan="2">Method:</td>
+                                <td colspan="2">{$paymentMethod}</td>
+                            </tr>
+                            <tr style="text-align: left; font-weight: normal; font-size: 12px;">
+                                <td colspan="7"></td>
+                                <td colspan="2" >Paid amount:</td>
+                                <td colspan="2">{$currency}{$orderAmount}</td>
+                            </tr>
+                        </table>
+                        
+                        <table style="table-layout: fixed;" class="table-noborder">    
+                            <tr>
+                                <td colspan="11"></td>
+                            </tr>
+                        </table>
+                        
+                        <table style="table-layout: fixed;">
+                            <tr style="text-align: left; font-weight: normal; font-size: 12px; margin-top: 15px;">
+                                <td colspan="7" class="table-noborder"></td>
+                                <td>Product Code</td>
+                                <td>Quantity</td>
+                                <td>Unit BV</td>
+                                <td>Total BV</td>
+                            </tr>
+                            <tr style="text-align: left; font-weight: normal; font-size: 12px;">
+                                <td colspan="7" class="table-noborder"></td>
+                                $orderDetails_bv
+                            </tr>
+                        </table>
+                        
+                        <table style="table-layout: fixed;">
+                            <tr style="text-align: left; font-weight: normal; font-size: 12px; margin-top: 15px;">
+                                <td colspan="2" class="table-noborder">Remark:</td>
+                                <td colspan="9" class="table-noborder"></td>
+                            </tr>
+                            <tr style="text-align: left; font-weight: normal; font-size: 12px;">
+                                <td colspan="6" class="table-noborder">{$invoiceRemark}</td>
+                            </tr>
+                        </table>
+
+                        
+                        <table style="table-layout: fixed;" class="table-noborder">    
+                            <tr>
+                                <td colspan="11"></td>
+                            </tr>
+                            <tr>
+                                <td colspan="11"></td>
+                            </tr>
+                            <tr>
+                                <td colspan="11"></td>
+                            </tr>
+                            <tr>
+                                <td colspan="11"></td>
+                            </tr>
+                        </table>
+                        
+                        <table style="table-layout: fixed;" class="table-noborder">    
+                            <tr style="text-align: left; font-weight: normal; font-size: 12px; margin-top: 15px;">
+                                <td colspan="4">Issued By:</td>
+                                <td colspan="4">Picked By:</td>
+                                <td colspan="3">Received By:</td>
+                            </tr>
+                            <tr>
+                                <td colspan="11"></td>
+                            </tr>
+                        </table>
+                    </div>
+                </div>
+            </body>
+        </html>
+ORDER;
+
+            require_once (\Yii::$app->vendorPath . '/tecnickcom/tcpdf/tcpdf.php');
+
+            $pdf = new \TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
+            // 设置打印模式
+            $pdf->SetCreator(PDF_CREATOR);
+            $pdf->SetAuthor('DaZe');
+            $pdf->SetTitle($orderSn);
+            $pdf->SetSubject('TCPDF Tutorial');
+            $pdf->SetKeywords('TCPDF, PDF, example, test, guide');
+            // 是否显示页眉
+            $pdf->setPrintHeader(false);
+            // 设置页眉字体
+            $pdf->setHeaderFont(Array('Helvetica', '', '12'));
+            // 页眉距离顶部的距离
+            $pdf->SetHeaderMargin('5');
+            // 是否显示页脚
+            $pdf->setPrintFooter(false);
+            // 设置默认等宽字体
+            $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
+            // 设置行高
+//            $pdf->setCellHeightRatio(1);
+            // 设置左、上、右的间距
+            $pdf->SetMargins('10', '0', '10');
+            // 设置是否自动分页  距离底部多少距离时分页
+            $pdf->SetAutoPageBreak(TRUE, '15');
+            // 设置图像比例因子
+            $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
+            if (@file_exists(\Yii::$app->vendorPath . 'tecnickcom/tcpdf/examples/lang/eng.php')) {
+                require_once(\Yii::$app->vendorPath . '/tecnickcom/tcpdf/examples/lang/eng.php');
+                $pdf->setLanguageArray($l);
+            }
+            $pdf->setFontSubsetting(true);
+            $pdf->AddPage();
+            // 设置字体
+            $pdf->SetFont('Helvetica', '', 10, '', true);
+//            $image_file = \Yii::$app->basePath . '/../ngds-logo.jpg';
+//            $image = file_get_contents($image_file);
+//            $pdf->Image('@' . $image, 15, 12, 20, 7, 'JPG');
+            $pdf->writeHTML($context);
+
+            $result = $pdf->Output($realFile, 'F');
+
+            $this->_updateFirst($realFile, 1);
+        }
+
+        $this->complete();
+        return true;
+    }
 }

+ 1 - 0
common/messages/en-US/app.php

@@ -5,6 +5,7 @@ return [
     'reconsume' => 'Reconsume',
     'orderCode' => 'Order Code',
     'orderDetail' => 'Order Detail',
+    'taxInvoice' => 'Tax Invoice',
     'productCode' => 'Product Code',
     'productName' => 'Product Name',
     'productPrice' => 'Product Price',

+ 1 - 0
common/messages/zh-CN/app.php

@@ -4,6 +4,7 @@ return [
     'addressId' => '收货地址',
     'orderCode' => '订单号',
     'orderDetail' => '订单详情',
+    'taxInvoice' => '发票',
     'productCode' => '商品编号',
     'productName' => '商品名字',
     'productPrice' => '商品价格',

+ 2 - 0
common/models/ApproachOrder.php

@@ -56,6 +56,8 @@ use Yii;
  * @property string $EXCHANGE_RATE 汇率
  * @property string COUNTRY_ID 国家ID
  * @property int CURRENCY_ID 币种ID
+ * @property int AUTO_MAINTENANCE AMP订单
+ * @property string INVOICE_REMARK 发票备注
  */
 class ApproachOrder extends \common\components\ActiveRecord
 {

+ 4 - 0
common/models/Order.php

@@ -57,6 +57,9 @@ use Yii;
  * @property string COUNTRY_ID 国家ID
  * @property int CURRENCY_ID 币种ID
  * @property int AUTO_MAINTENANCE AMP订单
+ * @property string INVOICE_REMARK 发票备注
+ * @property string INVOICE_NO 发票号
+ * @property string METHOD 支付方式
  */
 class Order extends \common\components\ActiveRecord
 {
@@ -140,6 +143,7 @@ class Order extends \common\components\ActiveRecord
             'COUNTRY_ID' => '国家ID',
             'CURRENCY_ID' => '币种ID',
             'AUTO_MAINTENANCE' => 'AMP订单',
+            'INVOICE_REMARK' => '发票备注',
         ];
     }
     /*

+ 84 - 0
common/models/forms/OrderInvoiceRemarkForm.php

@@ -0,0 +1,84 @@
+<?php
+namespace common\models\forms;
+
+use common\components\Model;
+use common\models\Order;
+use yii\base\Exception;
+
+class OrderInvoiceRemarkForm extends Model
+{
+    public $orderSn;
+    public $invoiceRemark;
+    public $orderMethod;
+
+    /**
+     * @inheritdoc
+     */
+    public function rules()
+    {
+        return [
+            [['orderSn'], 'trim'],
+            [['orderSn'], 'required'],
+            ['invoiceRemark', 'string', 'max' => 50000],
+            ['orderMethod', 'string'],
+            ['orderMethod', 'in', 'range' => ['Cash', 'Credit Card', 'Direct Banking', 'Cheque']],
+        ];
+    }
+
+    public function attributeLabels()
+    {
+        return [
+            'orderSn' => '订单号',
+            'invoiceRemark' => '发票备注',
+            'orderMethod' => '支付方式',
+        ];
+    }
+
+    /**
+     * 指定校验场景
+     * @return array
+     */
+    public function scenarios()
+    {
+        $parentScenarios =  parent::scenarios();
+        $customScenarios = [];
+
+        return array_merge($parentScenarios, $customScenarios);
+    }
+
+    /**
+     * @throws Exception
+     */
+    public function remarkOrderInvoice()
+    {
+        if (!$this->validate()) {
+            return null;
+        }
+
+        $sn = $this->orderSn;
+        // 订单详情
+        $orderInfo = Order::findOneAsArray(['SN' => $sn]);
+
+        if (!$orderInfo) {
+            throw new Exception('订单不存在');
+        }
+
+        $db = \Yii::$app->db;
+        $transaction = $db->beginTransaction();
+        try {
+            Order::updateAll(
+                ['INVOICE_REMARK' => $this->invoiceRemark,'METHOD'=>$this->orderMethod],
+                'SN=:SN',
+                ['SN' => $sn]
+            );
+
+            $transaction->commit();
+        } catch(Exception $e) {
+            $transaction->rollBack();
+            $this->addError('add', $e->getMessage());
+            return null;
+        }
+
+        return true;
+    }
+}

+ 24 - 0
console/controllers/ShopController.php

@@ -109,6 +109,30 @@ class ShopController extends BaseController
         return false;
     }
 
+    /**
+     * 订单列表导出PDF
+     * @param $taskId
+     * @return bool
+     */
+    public function actionOrderInvoiceExport($taskId)
+    {
+        $factory = ShopExport::factory($taskId);
+        $factory->listModelClass = OrderList::class;
+        try {
+            if ($factory->actionOrderInvoiceExport()) {
+                Yii::$app->swooleAsyncTimer->pushAsyncResultToAdmin($factory->getUserId(), '导出成功');
+            }
+            unset($factory);
+            return true;
+        } catch (\Exception $e) {
+            echo '导出失败。详情:' . $e->getMessage() . ' ' . $e->getLine() . ' ' . $e->getFile();
+            Yii::$app->swooleAsyncTimer->pushAsyncResultToAdmin($factory->getUserId(), '导出失败。详情:' . $e->getMessage() . ' ' . $e->getLine() . ' ' . $e->getFile(), false);
+        }
+
+        unset($factory);
+        return false;
+    }
+
     /**
      * 订单列表导出PDF
      * @param $taskId

+ 21 - 0
console/controllers/ToolController.php

@@ -208,6 +208,27 @@ class ToolController extends BaseController
         Email::sendRegistrationEmail('18511880790@163.com', 'zhangl', 'test123');
     }
 
+    public function actionOrderInvoiceRemark()
+    {
+        try {
+            $formModel = new \common\models\forms\OrderInvoiceRemarkForm();
+            // 设置测试用的订单号
+            $formModel->orderSn = 'OS202402015553509710';
+            $formModel->invoiceRemark = "这是一个测试发票备注。<span style='color:red;'>这是一个测试发票备注。</span>";
+
+            // 调用remarkOrderInvoice方法
+            $result = $formModel->remarkOrderInvoice();
+
+            if ($result) {
+                echo "成功:订单发票备注已更新\n";
+            } else {
+                echo "失败:" . json_encode($formModel->getErrors()) . "\n";
+            }
+        } catch (Exception $e) {
+            echo "异常:" . $e->getMessage() . "\n";
+        }
+    }
+
     public function actionUpdatePercent() {
         $percent = 100;
         $periodNum = 134;