feat(contract): 新增合同发票管理功能

实现合同发票的增删改查功能,包括:
1. 添加ContractInvoiceVo实体类及相关ViewModel
2. 创建合同发票数据库表CONTRACT_INVOICE
3. 实现前后端发票管理服务ContractInvoiceService
4. 开发发票管理界面及标签页
5. 添加发票表格单元格组件
6. 完善销售订单表结构,增加客户联系人字段
7. 更新pom.xml版本至0.0.122-SNAPSHOT

修复销售订单界面搜索字段命名不一致问题
This commit is contained in:
2025-10-16 15:47:33 +08:00
parent cf0a7e18ea
commit 71a358fa77
28 changed files with 1274 additions and 40 deletions

View File

@@ -0,0 +1,24 @@
package com.ecep.contract.controller.contract;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ecep.contract.controller.AbstEntityManagerSkin;
import com.ecep.contract.vm.ContractInvoiceViewModel;
import com.ecep.contract.vo.ContractInvoiceVo;
public class ContractInvoiceManagerSkin extends
AbstEntityManagerSkin<ContractInvoiceVo, ContractInvoiceViewModel, ContractInvoiceManagerSkin, ContractInvoiceManagerWindowController> {
private static final Logger logger = LoggerFactory.getLogger(ContractInvoiceManagerSkin.class);
public ContractInvoiceManagerSkin(ContractInvoiceManagerWindowController controller) {
super(controller);
}
@Override
public void initializeTable() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'initializeTable'");
}
}

View File

@@ -0,0 +1,48 @@
package com.ecep.contract.controller.contract;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstManagerWindowController;
import com.ecep.contract.service.ContractInvoiceService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.ContractInvoiceViewModel;
import com.ecep.contract.vo.ContractInvoiceVo;
import javafx.scene.control.TableColumn;
import javafx.stage.Stage;
@Lazy
@Scope("prototype")
@Component
@FxmlPath("/ui/contract/contract-invoice-manager.fxml")
public class ContractInvoiceManagerWindowController extends AbstManagerWindowController<ContractInvoiceVo, ContractInvoiceViewModel, ContractInvoiceManagerSkin> {
public TableColumn<ContractInvoiceViewModel, Number> idColumn;
public TableColumn<ContractInvoiceViewModel, String> codeColumn;
public TableColumn<ContractInvoiceViewModel, String> nameColumn;
public TableColumn<ContractInvoiceViewModel, Integer> contractColumn;
public TableColumn<ContractInvoiceViewModel, Integer> contractItemColumn;
@Autowired
private ContractInvoiceService contractInvoiceService;
@Override
public ContractInvoiceService getViewModelService() {
return contractInvoiceService;
}
@Override
protected ContractInvoiceManagerSkin createDefaultSkin() {
ContractInvoiceManagerSkin skin = new ContractInvoiceManagerSkin(this);
return skin;
}
@Override
public void show(Stage stage) {
super.show(stage);
getTitle().set("合同发票管理");
}
}

View File

@@ -0,0 +1,50 @@
package com.ecep.contract.controller.contract;
import org.springframework.stereotype.Component;
import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.controller.tab.ContractInvoiceTabSkinBase;
import com.ecep.contract.service.ContractInvoiceService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.ContractInvoiceViewModel;
import com.ecep.contract.vo.ContractInvoiceVo;
import javafx.collections.ObservableList;
import javafx.scene.control.Button;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.stage.Window;
@FxmlPath("/ui/contract/contract-invoice.fxml")
@Component
public class ContractInvoiceWindowController
extends AbstEntityController<ContractInvoiceVo, ContractInvoiceViewModel> {
public static void show(ContractInvoiceViewModel viewModel, Window owner) {
show(ContractInvoiceWindowController.class, viewModel, owner);
}
public Tab baseInfoTab;
public TextField codeField;
public TextField nameField;
public TextField invoiceField;
public TextField amountField;
public TextArea remarkField;
public Button saveBtn;
public Button cancelBtn;
@Override
public ContractInvoiceService getViewModelService() {
return getBean(ContractInvoiceService.class);
}
@Override
protected void registerTabSkins() {
TabPane tabPane = baseInfoTab.getTabPane();
ObservableList<Tab> tabs = tabPane.getTabs();
registerTabSkin(baseInfoTab, tab -> new ContractInvoiceTabSkinBase(this));
}
}

View File

@@ -3,24 +3,21 @@ package com.ecep.contract.controller.contract;
import java.time.LocalDate;
import com.ecep.contract.ContractPayWay;
import com.ecep.contract.controller.contract.sale_order.SalesOrderWindowController;
import com.ecep.contract.controller.tab.TabSkin;
import com.ecep.contract.controller.table.cell.CompanyTableCell;
import com.ecep.contract.controller.table.cell.EmployeeTableCell;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.controller.contract.sale_order.SalesOrderWindowController;
import com.ecep.contract.controller.table.cell.LocalDateFieldTableCell;
import com.ecep.contract.converter.EmployeeStringConverter;
import com.ecep.contract.service.CompanyService;
import com.ecep.contract.service.SaleOrdersService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.vm.SalesOrderViewModel;
import com.ecep.contract.vo.SalesOrderVo;
import javafx.scene.control.Button;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import lombok.Setter;
/**
@@ -56,7 +53,6 @@ public class ContractTabSkinSaleOrders
public TableColumn<SalesOrderViewModel, LocalDate> verifierDateColumn;
public TableColumn<SalesOrderViewModel, Number> refIdColumn;
public TableColumn<SalesOrderViewModel, Number> taxRateColumn;
public TableColumn<SalesOrderViewModel, Integer> customerColumn;
public TableColumn<SalesOrderViewModel, String> customerAddressColumn;
/**
* 修改人, Employee
@@ -70,8 +66,6 @@ public class ContractTabSkinSaleOrders
public TableColumn<SalesOrderViewModel, LocalDate> closerDateColumn;
public TableColumn<SalesOrderViewModel, String> descriptionColumn;
public MenuItem subContractTable_menu_refresh;
public TextField contractSearchKeyField;
public Button searchBtn;
private Tab tab;
public ContractTabSkinSaleOrders(ContractWindowController controller, Tab tab) {
@@ -98,13 +92,7 @@ public class ContractTabSkinSaleOrders
@Override
public void initializeTab() {
contractSearchKeyField.setOnKeyReleased(event -> {
if (event.getCode() == KeyCode.ENTER) {
searchBtn.fire();
}
});
searchBtn.setOnAction(this::onTableRefreshAction);
super.initializeTab();
subContractTable_menu_refresh.setOnAction(this::onTableRefreshAction);
idColumn.setCellValueFactory(param -> param.getValue().getId());
@@ -123,8 +111,6 @@ public class ContractTabSkinSaleOrders
// 设置新增字段的单元格值工厂和工厂类
refIdColumn.setCellValueFactory(param -> param.getValue().getRefId());
taxRateColumn.setCellValueFactory(param -> param.getValue().getTaxRate());
customerColumn.setCellValueFactory(param -> param.getValue().getCustomer());
customerColumn.setCellFactory(CompanyTableCell.forTableColumn(getCompanyService()));
customerAddressColumn.setCellValueFactory(param -> param.getValue().getCustomerAddress());
modifierColumn.setCellValueFactory(param -> param.getValue().getModifier());
modifierColumn.setCellFactory(EmployeeTableCell.forTableColumn(getEmployeeService()));
@@ -136,7 +122,7 @@ public class ContractTabSkinSaleOrders
closerDateColumn.setCellFactory(LocalDateFieldTableCell.forTableColumn());
descriptionColumn.setCellValueFactory(param -> param.getValue().getDescription());
super.initializeTab();
}
@Override

View File

@@ -13,6 +13,7 @@ import com.ecep.contract.controller.AbstEntityController;
import com.ecep.contract.controller.company.CompanyWindowController;
import com.ecep.contract.controller.tab.ContractTabSkinBase;
import com.ecep.contract.controller.tab.ContractTabSkinFiles;
import com.ecep.contract.controller.tab.ContractTabSkinInvoices;
import com.ecep.contract.controller.tab.ContractTabSkinItemsV2;
import com.ecep.contract.controller.tab.ContractTabSkinPayPlan;
import com.ecep.contract.controller.tab.ContractTabSkinSubContract;
@@ -154,7 +155,7 @@ public class ContractWindowController
registerTabSkin(saleOrderTab, tab -> new ContractTabSkinSaleOrders(this, tab));
Tab invoiceTab = new Tab("发票");
tabs.add(invoiceTab);
// registerTabSkin(invoiceTab, tab -> new ContractTabSkinInvoices(this, tab));
registerTabSkin(invoiceTab, tab -> new ContractTabSkinInvoices(this, tab));
tabs.add(new Tab("出库单"));
tabs.add(new Tab("发货单"));
tabs.add(new Tab("签收单"));

View File

@@ -0,0 +1,31 @@
package com.ecep.contract.controller.tab;
import com.ecep.contract.controller.contract.ContractInvoiceWindowController;
import com.ecep.contract.vm.ContractInvoiceViewModel;
import com.ecep.contract.vo.ContractInvoiceVo;
import javafx.scene.control.Tab;
/**
* 合同发票基础信息标签页皮肤
*/
public class ContractInvoiceTabSkinBase
extends AbstEntityBasedTabSkin<ContractInvoiceWindowController, ContractInvoiceVo, ContractInvoiceViewModel>
implements TabSkin {
public ContractInvoiceTabSkinBase(ContractInvoiceWindowController controller) {
super(controller);
}
@Override
public Tab getTab() {
return controller.baseInfoTab;
}
@Override
public void initializeTab() {
// 可以在这里进行标签页的初始化工作
controller.codeField.textProperty().bindBidirectional(viewModel.getCode());
controller.nameField.textProperty().bindBidirectional(viewModel.getName());
controller.remarkField.textProperty().bindBidirectional(viewModel.getRemark());
}
}

View File

@@ -0,0 +1,124 @@
package com.ecep.contract.controller.tab;
import java.time.LocalDate;
import java.util.Objects;
import org.controlsfx.glyphfont.Glyph;
import org.springframework.stereotype.Component;
import com.ecep.contract.controller.contract.AbstContractTableTabSkin;
import com.ecep.contract.controller.contract.ContractInvoiceWindowController;
import com.ecep.contract.controller.contract.ContractWindowController;
import com.ecep.contract.controller.table.EditableEntityTableTabSkin;
import com.ecep.contract.controller.table.cell.ContractInvoiceTableCell;
import com.ecep.contract.controller.table.cell.EmployeeTableCell;
import com.ecep.contract.controller.table.cell.NumberTableCell;
import com.ecep.contract.model.IdentityEntity;
import com.ecep.contract.service.ContractInvoiceService;
import com.ecep.contract.service.ContractService;
import com.ecep.contract.service.InvoiceService;
import com.ecep.contract.util.FxmlPath;
import com.ecep.contract.util.UITools;
import com.ecep.contract.vm.ContractInvoiceViewModel;
import com.ecep.contract.vo.ContractInvoiceVo;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.ActionEvent;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.Region;
import javafx.util.StringConverter;
import javafx.util.converter.CurrencyStringConverter;
@FxmlPath("/ui/contract/contract-tab-invoices.fxml")
public class ContractTabSkinInvoices
extends AbstContractTableTabSkin<ContractInvoiceVo, ContractInvoiceViewModel>
implements TabSkin, EditableEntityTableTabSkin<ContractInvoiceVo, ContractInvoiceViewModel> {
private Tab tab;
public TableColumn<ContractInvoiceViewModel, Number> idColumn;
public TableColumn<ContractInvoiceViewModel, String> codeColumn;
public TableColumn<ContractInvoiceViewModel, String> nameColumn;
public TableColumn<ContractInvoiceViewModel, Integer> invoiceColumn;
public TableColumn<ContractInvoiceViewModel, Number> amountColumn;
public TableColumn<ContractInvoiceViewModel, String> remarkColumn;
public TableColumn<ContractInvoiceViewModel, Integer> creatorColumn;
public TableColumn<ContractInvoiceViewModel, LocalDate> createDateColumn;
public TableColumn<ContractInvoiceViewModel, Integer> updaterColumn;
public TableColumn<ContractInvoiceViewModel, LocalDate> updateDateColumn;
public Label totalAmountLabel;
public ContractTabSkinInvoices(ContractWindowController controller, Tab tab) {
super(controller);
this.tab = tab;
}
@Override
public Tab getTab() {
return tab;
}
@Override
protected ContractInvoiceService getViewModelService() {
return getBean(ContractInvoiceService.class);
}
@Override
public void initializeTable() {
super.initializeTable();
getTableView().setEditable(true);
// 初始化列
idColumn.setCellValueFactory(new PropertyValueFactory<>("id"));
idColumn.setPrefWidth(50);
codeColumn.setCellValueFactory(new PropertyValueFactory<>("code"));
codeColumn.setPrefWidth(120);
codeColumn.setCellFactory(TextFieldTableCell.forTableColumn());
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
nameColumn.setPrefWidth(200);
nameColumn.setCellFactory(TextFieldTableCell.forTableColumn());
// 发票列
invoiceColumn.setCellValueFactory(new PropertyValueFactory<>("invoice"));
invoiceColumn.setPrefWidth(100);
invoiceColumn.setCellFactory(ContractInvoiceTableCell.forTableColumn(getCachedBean(InvoiceService.class)));
// 金额列
amountColumn.setCellValueFactory(new PropertyValueFactory<>("amount"));
amountColumn.setPrefWidth(100);
amountColumn.setCellFactory(NumberTableCell.forTableColumn(new CurrencyStringConverter(getLocale())));
remarkColumn.setCellValueFactory(new PropertyValueFactory<>("remark"));
remarkColumn.setPrefWidth(150);
remarkColumn.setCellFactory(TextFieldTableCell.forTableColumn());
// 创建人列
creatorColumn.setCellValueFactory(new PropertyValueFactory<>("creator"));
creatorColumn.setPrefWidth(80);
creatorColumn.setCellFactory(EmployeeTableCell.forTableColumn(getEmployeeService()));
createDateColumn.setCellValueFactory(new PropertyValueFactory<>("createDate"));
createDateColumn.setPrefWidth(120);
// 更新人列
updaterColumn.setCellValueFactory(new PropertyValueFactory<>("updater"));
updaterColumn.setPrefWidth(80);
updaterColumn.setCellFactory(EmployeeTableCell.forTableColumn(getEmployeeService()));
updateDateColumn.setCellValueFactory(new PropertyValueFactory<>("updateDate"));
updateDateColumn.setPrefWidth(120);
}
}

View File

@@ -4,6 +4,8 @@ import java.text.NumberFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import javax.naming.Binding;
import org.springframework.data.domain.Pageable;
import com.ecep.contract.ContractPayWay;
@@ -28,6 +30,7 @@ import com.ecep.contract.vo.InventoryVo;
import com.ecep.contract.vo.PurchaseOrderItemVo;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
@@ -196,6 +199,8 @@ public class ContractTabSkinItemsV2
}
showInOwner(InventoryWindowController.class, InventoryViewModel.from(inventory));
});
showInventory.visibleProperty().bind(
Bindings.select(getTableView().getSelectionModel().selectedItemProperty(), "inventory", "value").isNotNull());
contextMenu.getItems().addAll(showInventory);
}

View File

@@ -0,0 +1,59 @@
package com.ecep.contract.controller.table.cell;
import static com.ecep.contract.SpringApp.getBean;
import com.ecep.contract.service.InvoiceService;
import com.ecep.contract.vo.InvoiceVo;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.util.Callback;
import lombok.NoArgsConstructor;
/**
* 合同发票表格单元格
* 用于在表格中显示合同发票信息
*/
@NoArgsConstructor
public class ContractInvoiceTableCell<V> extends AsyncUpdateTableCell<V, Integer, InvoiceVo> {
/**
* 创建一个ContractInvoiceTableCell的TableCell工厂自动获取InvoiceService实例
*
* @param <S> 表格行类型
* @return TableCell工厂回调
*/
public static <S> Callback<TableColumn<S, Integer>, TableCell<S, Integer>> forTableColumn() {
return forTableColumn(getBean(InvoiceService.class));
}
/**
* 创建一个ContractInvoiceTableCell的TableCell工厂使用提供的InvoiceService实例
*
* @param <S> 表格行类型
* @param service InvoiceService实例
* @return TableCell工厂回调
*/
public static <S> Callback<TableColumn<S, Integer>, TableCell<S, Integer>> forTableColumn(InvoiceService service) {
return param -> new ContractInvoiceTableCell<S>(service);
}
/**
* 使用指定的InvoiceService创建ContractInvoiceTableCell
*
* @param invoiceService InvoiceService实例
*/
public ContractInvoiceTableCell(InvoiceService invoiceService) {
setService(invoiceService);
}
@Override
protected InvoiceService getServiceBean() {
return getBean(InvoiceService.class);
}
@Override
public String format(InvoiceVo entity) {
return entity.getCode();
}
}

View File

@@ -0,0 +1,67 @@
package com.ecep.contract.service;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import com.ecep.contract.vm.ContractInvoiceViewModel;
import com.ecep.contract.vo.ContractInvoiceVo;
@Service
@CacheConfig(cacheNames = "contract-invoice")
public class ContractInvoiceService extends QueryService<ContractInvoiceVo, ContractInvoiceViewModel> {
@Cacheable(key = "#p0")
@Override
public ContractInvoiceVo findById(Integer id) {
return super.findById(id);
}
@Caching(evict = {
@CacheEvict(key = "#p0.id"),
@CacheEvict(key = "'code-'+#p0.code")
})
public ContractInvoiceVo save(ContractInvoiceVo invoice) {
return super.save(invoice);
}
@Caching(evict = {
@CacheEvict(key = "#p0.id"),
@CacheEvict(key = "'code-'+#p0.code")
})
public void delete(ContractInvoiceVo invoice) {
super.delete(invoice);
}
@Cacheable(key = "'code-'+#p0")
public ContractInvoiceVo findByCode(String code) {
try {
return async("findByCode", code, String.class).handle((response, ex) -> {
if (ex != null) {
throw new RuntimeException("远程方法+findByCode+调用失败", ex);
}
if (response != null) {
return updateValue(createNewEntity(), response);
}
return null;
}).get();
} catch (Exception e) {
throw new RuntimeException("查找合同发票 " + code + " 时发生错误", e);
}
}
public ContractInvoiceVo findByContractId(Integer contractId) {
try {
return async("findByContractId", contractId, Integer.class).handle((response, ex) -> {
if (response != null) {
return updateValue(createNewEntity(), response);
}
return null;
}).get();
} catch (Exception e) {
throw new RuntimeException("查找合同ID为 " + contractId + " 的发票时发生错误", e);
}
}
}

View File

@@ -10,7 +10,6 @@ import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import com.ecep.contract.model.EmployeeRole;
import com.ecep.contract.vm.EmployeeViewModel;
import com.ecep.contract.vo.EmployeeRoleVo;
import com.ecep.contract.vo.EmployeeVo;

View File

@@ -0,0 +1,119 @@
package com.ecep.contract.vm;
import java.time.LocalDate;
import java.util.Objects;
import com.ecep.contract.util.NumberUtils;
import com.ecep.contract.vo.ContractInvoiceVo;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class ContractInvoiceViewModel extends IdentityViewModel<ContractInvoiceVo> {
private final SimpleStringProperty code = new SimpleStringProperty();
private final SimpleStringProperty name = new SimpleStringProperty();
/**
* 关联的合同对象, Contract
*/
private final SimpleObjectProperty<Integer> contract = new SimpleObjectProperty<>();
/**
* 关联的发票对象, Invoice
*/
private final SimpleObjectProperty<Integer> invoice = new SimpleObjectProperty<>();
/**
* 发票金额
*/
private final SimpleObjectProperty<Double> amount = new SimpleObjectProperty<>();
/**
* 备注
*/
private final SimpleStringProperty remark = new SimpleStringProperty();
private final SimpleObjectProperty<LocalDate> createDate = new SimpleObjectProperty<>();
private final SimpleObjectProperty<LocalDate> updateDate = new SimpleObjectProperty<>();
private final SimpleObjectProperty<Integer> creator = new SimpleObjectProperty<>();
private final SimpleObjectProperty<Integer> updater = new SimpleObjectProperty<>();
@Override
protected void updateFrom(ContractInvoiceVo v) {
super.updateFrom(v);
code.set(v.getCode());
name.set(v.getName());
contract.set(v.getContractId());
invoice.set(v.getInvoiceId());
amount.set(v.getAmount() != null ? v.getAmount() : 0.0);
remark.set(v.getRemark());
updateDate.set(v.getUpdateDate());
creator.set(v.getSetupPersonId());
updater.set(v.getUpdatePersonId());
}
@Override
public boolean copyTo(ContractInvoiceVo v) {
boolean modified = super.copyTo(v);
if (!Objects.equals(code.get(), v.getCode())) {
v.setCode(code.get());
modified = true;
}
if (!Objects.equals(name.get(), v.getName())) {
v.setName(name.get());
modified = true;
}
if (!Objects.equals(contract.get(), v.getContractId())) {
v.setContractId(contract.get());
modified = true;
}
if (!Objects.equals(invoice.get(), v.getInvoiceId())) {
v.setInvoiceId(invoice.get());
modified = true;
}
if (!NumberUtils.equals(amount.get(), v.getAmount())) {
v.setAmount(amount.get());
modified = true;
}
if (!Objects.equals(remark.get(), v.getRemark())) {
v.setRemark(remark.get());
modified = true;
}
if (!Objects.equals(creator.get(), v.getSetupPersonId())) {
v.setSetupPersonId(creator.get());
modified = true;
}
if (!Objects.equals(updater.get(), v.getUpdatePersonId())) {
v.setUpdatePersonId(updater.get());
modified = true;
}
if (!Objects.equals(createDate.get(), v.getSetupDate())) {
v.setSetupDate(createDate.get());
modified = true;
}
if (!Objects.equals(updateDate.get(), v.getUpdateDate())) {
v.setUpdateDate(updateDate.get());
modified = true;
}
return modified;
}
/**
* 从VO对象创建ViewModel实例
*
* @param vo 发票VO对象
* @return 发票ViewModel实例
*/
public static ContractInvoiceViewModel from(ContractInvoiceVo vo) {
ContractInvoiceViewModel viewModel = new ContractInvoiceViewModel();
viewModel.updateFrom(vo);
return viewModel;
}
}

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<BorderPane id="root" fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="700.0" prefWidth="900.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1">
<top>
<HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="900.0" spacing="10.0">
<Button mnemonicParsing="false" onAction="#onTableCreateNewAction" text="新建">
<HBox.margin>
<Insets left="10.0" />
</HBox.margin>
</Button>
<Button mnemonicParsing="false" onAction="#onTableRefreshAction" text="刷新">
<HBox.margin>
<Insets left="10.0" />
</HBox.margin>
</Button>
<Button mnemonicParsing="false" onAction="#onTableDeleteAction" text="删除">
<HBox.margin>
<Insets left="10.0" />
</HBox.margin>
</Button>
<TextField fx:id="searchField" promptText="搜索..." HBox.hgrow="ALWAYS">
<HBox.margin>
<Insets left="10.0" right="10.0" />
</HBox.margin>
</TextField>
</HBox>
</top>
<center>
<TableView fx:id="table" prefHeight="600.0" prefWidth="900.0">
<columns>
<TableColumn fx:id="idColumn" prefWidth="80.0" text="ID" />
<TableColumn fx:id="codeColumn" prefWidth="120.0" text="发票编号" />
<TableColumn fx:id="nameColumn" prefWidth="150.0" text="发票名称" />
<TableColumn fx:id="contractColumn" prefWidth="100.0" text="合同ID" />
<TableColumn fx:id="contractItemColumn" prefWidth="100.0" text="合同项目ID" />
</columns>
</TableView>
</center>
<bottom>
<HBox alignment="CENTER" prefHeight="40.0" prefWidth="900.0" spacing="10.0">
<Label fx:id="pageInfoLabel" text="第 1 页,共 1 页" />
<Button mnemonicParsing="false" onAction="#onPrevPageAction" text="上一页" />
<Button mnemonicParsing="false" onAction="#onNextPageAction" text="下一页" />
<Button mnemonicParsing="false" onAction="#onFirstPageAction" text="首页" />
<Button mnemonicParsing="false" onAction="#onLastPageAction" text="末页" />
<TextField fx:id="pageField" prefWidth="60.0" text="1" />
<Button mnemonicParsing="false" onAction="#onGotoPageAction" text="跳转" />
</HBox>
</bottom>
</BorderPane>

View File

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.DatePicker?>
<?import javafx.scene.control.ComboBox?>
<BorderPane id="root" fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="700.0" prefWidth="900.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.ecep.contract.controller.contract.ContractInvoiceWindowController">
<top>
<HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="900.0" spacing="10.0">
<Button fx:id="saveBtn" mnemonicParsing="false" text="保存">
<HBox.margin>
<Insets left="10.0" />
</HBox.margin>
</Button>
<Button mnemonicParsing="false" onAction="#refresh" text="刷新">
<HBox.margin>
<Insets left="10.0" />
</HBox.margin>
</Button>
<Label fx:id="statusLabel" prefWidth="200.0">
<HBox.margin>
<Insets left="10.0" />
</HBox.margin>
</Label>
</HBox>
</top>
<center>
<TabPane fx:id="tabPane" prefHeight="660.0" prefWidth="900.0" tabClosingPolicy="UNAVAILABLE">
<Tab fx:id="baseInfoTab" text="基本信息">
<ScrollPane fitToWidth="true">
<VBox maxWidth="800.0" prefWidth="800.0">
<GridPane hgap="10.0" vgap="10.0">
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="NEVER" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="0.0" prefWidth="200.0" />
<ColumnConstraints halignment="RIGHT" hgrow="NEVER" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="0.0" prefWidth="200.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints prefHeight="30.0" vgrow="NEVER" />
<RowConstraints prefHeight="30.0" vgrow="NEVER" />
<RowConstraints prefHeight="30.0" vgrow="NEVER" />
<RowConstraints prefHeight="30.0" vgrow="NEVER" />
<RowConstraints prefHeight="30.0" vgrow="NEVER" />
<RowConstraints prefHeight="30.0" vgrow="NEVER" />
<RowConstraints prefHeight="100.0" vgrow="ALWAYS" />
</rowConstraints>
<Label text="ID:" GridPane.columnIndex="0" GridPane.rowIndex="0" />
<Label fx:id="idLabel" GridPane.columnIndex="1" GridPane.rowIndex="0" />
<Label text="发票编号:" GridPane.columnIndex="2" GridPane.rowIndex="0" />
<TextField fx:id="codeField" GridPane.columnIndex="3" GridPane.rowIndex="0" />
<Label text="发票名称:" GridPane.columnIndex="0" GridPane.rowIndex="1" />
<TextField fx:id="nameField" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="1" />
<Label text="合同ID:" GridPane.columnIndex="0" GridPane.rowIndex="2" />
<TextField fx:id="contractField" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Label text="合同项目ID:" GridPane.columnIndex="2" GridPane.rowIndex="2" />
<TextField fx:id="contractItemField" GridPane.columnIndex="3" GridPane.rowIndex="2" />
<Label text="发票ID:" GridPane.columnIndex="0" GridPane.rowIndex="3" />
<TextField fx:id="invoiceField" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<Label text="发票金额:" GridPane.columnIndex="2" GridPane.rowIndex="3" />
<TextField fx:id="amountField" GridPane.columnIndex="3" GridPane.rowIndex="3" />
<Label text="发票日期:" GridPane.columnIndex="0" GridPane.rowIndex="4" />
<DatePicker fx:id="invoiceDatePicker" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<Label text="发票类型:" GridPane.columnIndex="2" GridPane.rowIndex="4" />
<ComboBox fx:id="invoiceTypeComboBox" GridPane.columnIndex="3" GridPane.rowIndex="4" />
<Label text="发票状态:" GridPane.columnIndex="0" GridPane.rowIndex="5" />
<ComboBox fx:id="statusComboBox" GridPane.columnIndex="1" GridPane.rowIndex="5" />
<Label text="用友ID:" GridPane.columnIndex="2" GridPane.rowIndex="5" />
<TextField fx:id="ufIdField" GridPane.columnIndex="3" GridPane.rowIndex="5" />
<Label text="开票单位:" GridPane.columnIndex="0" GridPane.rowIndex="6" />
<TextField fx:id="invoiceUnitField" GridPane.columnIndex="1" GridPane.rowIndex="6" />
<Label text="接收单位:" GridPane.columnIndex="2" GridPane.rowIndex="6" />
<TextField fx:id="receiveUnitField" GridPane.columnIndex="3" GridPane.rowIndex="6" />
<Label text="备注:" GridPane.columnIndex="0" GridPane.rowIndex="7" />
<TextArea fx:id="remarkTextArea" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="7" />
</GridPane>
<VBox.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</VBox.margin>
</VBox>
</ScrollPane>
</Tab>
<Tab fx:id="entityTab" text="实体信息" />
</TabPane>
</center>
</BorderPane>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.ecep.contract.controller.tab.ContractTabSkinInvoices">
<children>
<HBox spacing="3.0">
<children>
<TextField fx:id="searchKeyField" promptText="搜索..." />
<Button fx:id="searchBtn" text="搜索"/>
<Button fx:id="refreshBtn" text="刷新"/>
<Button fx:id="addBtn" text="新增发票"/>
</children>
<padding>
<Insets bottom="10.0" left="7.0" right="10.0" top="10.0"/>
</padding>
</HBox>
<TableView fx:id="table" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0"
AnchorPane.topAnchor="42.0">
<columns>
<TableColumn fx:id="idColumn" text="ID"/>
<TableColumn fx:id="codeColumn" text="编号"/>
<TableColumn fx:id="nameColumn" text="名称"/>
<TableColumn fx:id="invoiceColumn" text="发票"/>
<TableColumn fx:id="amountColumn" text="金额"/>
<TableColumn fx:id="remarkColumn" text="备注"/>
<TableColumn fx:id="creatorColumn" text="创建人"/>
<TableColumn fx:id="createDateColumn" text="创建日期"/>
<TableColumn fx:id="updaterColumn" text="更新人"/>
<TableColumn fx:id="updateDateColumn" text="更新日期"/>
</columns>
</TableView>
</children>
</AnchorPane>

View File

@@ -10,7 +10,7 @@
<children>
<HBox spacing="3.0">
<children>
<TextField fx:id="contractSearchKeyField" promptText="检索关键字"/>
<TextField fx:id="searchKeyField" promptText="检索关键字"/>
<Button fx:id="searchBtn" mnemonicParsing="false" text="检索"/>
</children>
<padding>
@@ -23,7 +23,6 @@
<columns>
<TableColumn fx:id="idColumn" prefWidth="75.0" text="ID"/>
<TableColumn fx:id="codeColumn" prefWidth="120" text="编号"/>
<TableColumn fx:id="customerColumn" prefWidth="100.0" text="客户"/>
<TableColumn fx:id="customerAddressColumn" prefWidth="150.0" text="客户地址"/>
<TableColumn fx:id="taxRateColumn" prefWidth="60.0" text="税率"/>
<TableColumn fx:id="refIdColumn" prefWidth="60.0" text="RefID"/>