账单导出

This commit is contained in:
2026-11-01 16:17:12 +08:00
parent f91939f1f0
commit c73910ba74
8 changed files with 69 additions and 9 deletions
+3 -1
View File
@@ -240,7 +240,7 @@ class BillExport implements FromCollection, WithStyles, WithTitle
} }
/** /**
* 标题/列头/合计行加粗,合计行标签左合并 A:G;全表居中 + 全边框;金额列货币格式; * 标题合并 A:H 并居中;标题/列头/合计行加粗,合计行标签左合并 A:G;全表居中 + 全边框;金额列货币格式;
* 数量(浅黄)/金额(浅红)非 0 条件填色(0 不填、列头固定填色),冻结列头 * 数量(浅黄)/金额(浅红)非 0 条件填色(0 不填、列头固定填色),冻结列头
*/ */
public function styles(Worksheet $sheet): array public function styles(Worksheet $sheet): array
@@ -257,6 +257,8 @@ class BillExport implements FromCollection, WithStyles, WithTitle
$sheet->getColumnDimension('G')->setWidth(12); $sheet->getColumnDimension('G')->setWidth(12);
$sheet->getColumnDimension('H')->setWidth(12); $sheet->getColumnDimension('H')->setWidth(12);
$sheet->mergeCells('A1:H1');
foreach ($this->mergeRows as $row) { foreach ($this->mergeRows as $row) {
$sheet->mergeCells('A' . $row . ':G' . $row); $sheet->mergeCells('A' . $row . ':G' . $row);
} }
+3 -1
View File
@@ -144,7 +144,7 @@ class ContainerReturnExport implements FromCollection, WithStyles, WithStrictNul
} }
/** /**
* 标题/列头/合计行加粗;全表居中 + 全边框;金额区货币格式; * 标题按实际列数合并居中;标题/列头/合计行加粗;全表居中 + 全边框;金额区货币格式;
* 门店列(浅蓝)/合计列(浅红)非 0 条件填色(0 不填、列头固定填色),冻结列头行 * 门店列(浅蓝)/合计列(浅红)非 0 条件填色(0 不填、列头固定填色),冻结列头行
*/ */
public function styles(Worksheet $sheet): array public function styles(Worksheet $sheet): array
@@ -161,6 +161,8 @@ class ContainerReturnExport implements FromCollection, WithStyles, WithStrictNul
$storeIds = array_map(intval(...), array_keys($this->storeNames)); $storeIds = array_map(intval(...), array_keys($this->storeNames));
$lastColumn = Coordinate::stringFromColumnIndex($columnCount); $lastColumn = Coordinate::stringFromColumnIndex($columnCount);
$sheet->mergeCells('A1:' . $lastColumn . '1');
// 全部单元格水平/垂直居中 // 全部单元格水平/垂直居中
$sheet->getStyle('A1:' . $lastColumn . $this->lastRow) $sheet->getStyle('A1:' . $lastColumn . $this->lastRow)
->getAlignment() ->getAlignment()
+2 -1
View File
@@ -252,7 +252,7 @@ class PurchaseOrderExport implements FromCollection, WithStrictNullComparison, W
} }
/** /**
* 标题/列头/合计加粗;全表居中 + 全边框;金额类列货币格式; * 标题按实际列数合并居中;标题/列头/合计加粗;全表居中 + 全边框;金额类列货币格式;
* 数量(浅黄)/门店数量(浅蓝)/金额(浅红)按值条件填色(0 不填、列头固定填色),冻结列头 * 数量(浅黄)/门店数量(浅蓝)/金额(浅红)按值条件填色(0 不填、列头固定填色),冻结列头
*/ */
public function styles(Worksheet $sheet): array public function styles(Worksheet $sheet): array
@@ -279,6 +279,7 @@ class PurchaseOrderExport implements FromCollection, WithStrictNullComparison, W
} }
// 全部单元格水平/垂直居中 // 全部单元格水平/垂直居中
$sheet->mergeCells('A1:' . $lastColumn . '1');
$sheet->getStyle('A1:' . $lastColumn . $this->lastRow) $sheet->getStyle('A1:' . $lastColumn . $this->lastRow)
->getAlignment() ->getAlignment()
->setHorizontal(Alignment::HORIZONTAL_CENTER) ->setHorizontal(Alignment::HORIZONTAL_CENTER)
+2 -1
View File
@@ -120,7 +120,7 @@ class PurchaseStoreSheet implements FromCollection, WithStrictNullComparison, Wi
} }
/** /**
* 标题/列头/合计加粗;全表居中 + 全边框;金额类列货币格式; * 标题合并 A:I 并居中;标题/列头/合计加粗;全表居中 + 全边框;金额类列货币格式;
* 数量(浅黄)/金额(浅红)按值条件填色(0 不填、列头固定填色),冻结列头 * 数量(浅黄)/金额(浅红)按值条件填色(0 不填、列头固定填色),冻结列头
*/ */
public function styles(Worksheet $sheet): array public function styles(Worksheet $sheet): array
@@ -135,6 +135,7 @@ class PurchaseStoreSheet implements FromCollection, WithStrictNullComparison, Wi
} }
// 全部单元格水平/垂直居中 // 全部单元格水平/垂直居中
$sheet->mergeCells('A1:I1');
$sheet->getStyle('A1:I' . $this->lastRow) $sheet->getStyle('A1:I' . $this->lastRow)
->getAlignment() ->getAlignment()
->setHorizontal(Alignment::HORIZONTAL_CENTER) ->setHorizontal(Alignment::HORIZONTAL_CENTER)
+6 -5
View File
@@ -122,7 +122,7 @@ class PurchaseSupplierSheet implements FromCollection, WithStrictNullComparison,
} }
/** /**
* 标题合并 A1:C2、备注合并 D1:I2(红色 22 号字);标题/列头加粗;全表居中 + 全边框 + 列头行自动换行; * 标题合并 A1:C2、备注从 D1 合并至实际末列(红色 22 号字);标题/列头加粗;全表居中 + 全边框 + 列头行自动换行;
* 汇总列(浅黄)/门店数量列(浅蓝)按值条件填色(0 不填、列头固定填色),冻结列头 * 汇总列(浅黄)/门店数量列(浅蓝)按值条件填色(0 不填、列头固定填色),冻结列头
*/ */
public function styles(Worksheet $sheet): array public function styles(Worksheet $sheet): array
@@ -131,16 +131,17 @@ class PurchaseSupplierSheet implements FromCollection, WithStrictNullComparison,
$sheet->freezePane('A' . ($this->headerRow + 1)); $sheet->freezePane('A' . ($this->headerRow + 1));
// 标题合并前三列占两行(A1:C2),备注合并六列两行(D1:I2)
$sheet->mergeCells('A1:C2');
$sheet->mergeCells('D1:I2');
$widths = [24, 10, 6]; $widths = [24, 10, 6];
foreach ($widths as $index => $width) { foreach ($widths as $index => $width) {
$sheet->getColumnDimension(Coordinate::stringFromColumnIndex($index + 1))->setWidth($width); $sheet->getColumnDimension(Coordinate::stringFromColumnIndex($index + 1))->setWidth($width);
} }
$storeIds = array_map('intval', array_keys($this->stores)); $storeIds = array_map('intval', array_keys($this->stores));
$lastColumn = Coordinate::stringFromColumnIndex(3 + max(count($storeIds), 1)); $lastColumn = Coordinate::stringFromColumnIndex(3 + max(count($storeIds), 1));
// 标题占前三列,备注占其余实际表格列,均合并两行
$sheet->mergeCells('A1:C2');
$sheet->mergeCells('D1:' . $lastColumn . '2');
foreach ($storeIds as $i => $storeId) { foreach ($storeIds as $i => $storeId) {
$sheet->getColumnDimension(Coordinate::stringFromColumnIndex(4 + $i))->setWidth(6); $sheet->getColumnDimension(Coordinate::stringFromColumnIndex(4 + $i))->setWidth(6);
} }
+12
View File
@@ -11,6 +11,7 @@ use App\Models\PurchaseOrderModel;
use App\Models\StoreModel; use App\Models\StoreModel;
use App\Models\StoreOrderItemModel; use App\Models\StoreOrderItemModel;
use Maatwebsite\Excel\Facades\Excel; use Maatwebsite\Excel\Facades\Excel;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
/** /**
* 门店账单导出:单账单合并明细 / 批量按门店分工作表 / 一级分类过滤 / * 门店账单导出:单账单合并明细 / 批量按门店分工作表 / 一级分类过滤 /
@@ -139,6 +140,17 @@ class BillExportTest extends ProcurementTestCase
); );
} }
/** 账单标题合并全部八列,避免标题受首列宽度限制 */
public function test_export_title_is_merged_across_all_columns(): void
{
$bill = $this->makeBill(StoreModel::factory()->create());
$sheet = (new Spreadsheet())->getActiveSheet();
(new BillExport($bill))->styles($sheet);
$this->assertArrayHasKey('A1:H1', $sheet->getMergeCells());
}
/** 批量导出:同一门店多账单的同商品与费用合并为一张表,不同门店拆分工作表 */ /** 批量导出:同一门店多账单的同商品与费用合并为一张表,不同门店拆分工作表 */
public function test_batch_export_groups_bills_by_store(): void public function test_batch_export_groups_bills_by_store(): void
{ {
+17
View File
@@ -13,6 +13,7 @@ use App\Models\StoreOrderModel;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel; use Maatwebsite\Excel\Facades\Excel;
use Modules\SystemTool\Services\SysSiteConfigService; use Modules\SystemTool\Services\SysSiteConfigService;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
/** /**
* 压回筐记录:周转筐/托盘跟账单走(生成账单时写入完整快照,只读); * 压回筐记录:周转筐/托盘跟账单走(生成账单时写入完整快照,只读);
@@ -243,6 +244,22 @@ class ContainerReturnTest extends ProcurementTestCase
); );
} }
/** 汇总导出标题按日期、门店及合计列的总宽度合并 */
public function test_export_title_is_merged_across_dynamic_columns(): void
{
$export = new ContainerReturnExport(
collect(),
[1 => '门店A', 2 => '门店B'],
'2026-08-01',
'2026-08-03',
);
$sheet = (new Spreadsheet())->getActiveSheet();
$export->styles($sheet);
$this->assertArrayHasKey('A1:D1', $sheet->getMergeCells());
}
/** 指定门店导出:仅所选门店成列,未选门店记录忽略;所选门店无记录整列填 0 */ /** 指定门店导出:仅所选门店成列,未选门店记录忽略;所选门店无记录整列填 0 */
public function test_export_filters_by_selected_stores(): void public function test_export_filters_by_selected_stores(): void
{ {
+24
View File
@@ -216,6 +216,30 @@ class ExportTest extends ProcurementTestCase
$this->assertSame(45.0, (float) $total[11]); $this->assertSame(45.0, (float) $total[11]);
} }
/** 采购导出:标题按实际表格列合并,供应商备注区域随门店列数调整 */
public function test_export_titles_are_merged_across_table_columns(): void
{
[$purchase] = $this->buildPurchaseWithSuppliers();
$purchaseSheet = (new Spreadsheet())->getActiveSheet();
(new PurchaseOrderExport($purchase))->styles($purchaseSheet);
$this->assertArrayHasKey('A1:N1', $purchaseSheet->getMergeCells());
$storeSheet = (new Spreadsheet())->getActiveSheet();
(new PurchaseStoreExport($purchase))->sheets()[0]->styles($storeSheet);
$this->assertArrayHasKey('A1:I1', $storeSheet->getMergeCells());
$supplierSheets = (new PurchaseSupplierExport($purchase))->sheets();
$supplierSheetA = (new Spreadsheet())->getActiveSheet();
$supplierSheets[0]->styles($supplierSheetA);
$this->assertArrayHasKey('A1:C2', $supplierSheetA->getMergeCells());
$this->assertArrayHasKey('D1:E2', $supplierSheetA->getMergeCells());
$supplierSheetB = (new Spreadsheet())->getActiveSheet();
$supplierSheets[1]->styles($supplierSheetB);
$this->assertArrayHasKey('D1:D2', $supplierSheetB->getMergeCells());
}
/** 商品明细导出:范围=全部未删除商品(含下架)∪ 本采购单有订货商品;已删除且无订货的商品不导出 */ /** 商品明细导出:范围=全部未删除商品(含下架)∪ 本采购单有订货商品;已删除且无订货的商品不导出 */
public function test_export_scope_includes_off_shelf_but_not_deleted(): void public function test_export_scope_includes_off_shelf_but_not_deleted(): void
{ {