forked from yoone/API
1
0
Fork 0

Compare commits

...

2 Commits

Author SHA1 Message Date
黄珑 21d699486b 订单页增加判断,非管理员只显示最近10天数据 2025-08-25 18:16:38 +08:00
黄珑 f331e1b86e Fix: 获取运费增加正确提示 2025-08-23 17:42:02 +08:00
7 changed files with 102 additions and 27 deletions

View File

@ -22,7 +22,7 @@ import { errorResponse, successResponse } from '../utils/response.util';
import { LogisticsService } from '../service/logistics.service'; import { LogisticsService } from '../service/logistics.service';
import { ShippingDetailsDTO } from '../dto/freightcom.dto'; import { ShippingDetailsDTO } from '../dto/freightcom.dto';
import { ShippingAddress } from '../entity/shipping_address.entity'; import { ShippingAddress } from '../entity/shipping_address.entity';
import { QueryServiceDTO, ShipmentBookDTO } from '../dto/logistics.dto'; import { QueryServiceDTO, ShipmentBookDTO, ShipmentFeeBookDTO } from '../dto/logistics.dto';
import { User } from '../decorator/user.decorator'; import { User } from '../decorator/user.decorator';
@Controller('/logistics') @Controller('/logistics')
@ -180,7 +180,7 @@ export class LogisticsController {
) )
@Post('/getShipmentFee') @Post('/getShipmentFee')
async getShipmentFee( async getShipmentFee(
@Body() data: ShipmentBookDTO @Body() data: ShipmentFeeBookDTO
) { ) {
try { try {
const fee = await this.logisticsService.getShipmentFee(data); const fee = await this.logisticsService.getShipmentFee(data);

View File

@ -68,11 +68,12 @@ export class OrderController {
@Get('/getOrders') @Get('/getOrders')
async getOrders( async getOrders(
@Query() @Query()
param: QueryOrderDTO param: QueryOrderDTO,
@User() user
) { ) {
try { try {
const count = await this.orderService.getOrderStatus(param); const count = await this.orderService.getOrderStatus(param);
const data = await this.orderService.getOrders(param); const data = await this.orderService.getOrders(param, user);
return successResponse({ return successResponse({
...data, ...data,
count, count,

View File

@ -21,6 +21,50 @@ export class ShipmentBookDTO {
orderIds?: number[]; orderIds?: number[];
} }
export class ShipmentFeeBookDTO {
@ApiProperty()
stockPointId: number;
@ApiProperty()
sender: string;
@ApiProperty()
startPhone: string;
@ApiProperty()
startPostalCode: string;
@ApiProperty()
pickupAddress: string;
// pickupWarehouse: number; // 此处用 stockPointId 到后端解析
@ApiProperty()
shipperCountryCode: string;
@ApiProperty()
receiver: string;
@ApiProperty()
city: string;
@ApiProperty()
province: string;
@ApiProperty()
country: string;
@ApiProperty()
postalCode: string;
@ApiProperty()
deliveryAddress: string;
@ApiProperty()
receiverPhone: string;
@ApiProperty()
receiverEmail: string;
@ApiProperty()
length: number;
@ApiProperty()
width: number;
@ApiProperty()
height: number;
@ApiProperty()
dimensionUom: string;
@ApiProperty()
weight: number;
@ApiProperty()
weightUom: string;
}
export class PaymentMethodDTO { export class PaymentMethodDTO {
@ApiProperty() @ApiProperty()
id: string; id: string;

View File

@ -8,7 +8,7 @@ import { Order } from '../entity/order.entity';
import { Shipment } from '../entity/shipment.entity'; import { Shipment } from '../entity/shipment.entity';
import { ShipmentItem } from '../entity/shipment_item.entity'; import { ShipmentItem } from '../entity/shipment_item.entity';
import { OrderShipment } from '../entity/order_shipment.entity'; import { OrderShipment } from '../entity/order_shipment.entity';
import { QueryServiceDTO, ShipmentBookDTO } from '../dto/logistics.dto'; import { QueryServiceDTO, ShipmentBookDTO, ShipmentFeeBookDTO } from '../dto/logistics.dto';
import { import {
ErpOrderStatus, ErpOrderStatus,
OrderStatus, OrderStatus,
@ -30,6 +30,7 @@ import { OrderSale } from '../entity/order_sale.entity';
import { UniExpressService } from './uni_express.service'; import { UniExpressService } from './uni_express.service';
import { StockPoint } from '../entity/stock_point.entity'; import { StockPoint } from '../entity/stock_point.entity';
import { OrderService } from './order.service'; import { OrderService } from './order.service';
import { convertKeysFromCamelToSnake } from '../utils/object-transform.util';
@Provide() @Provide()
export class LogisticsService { export class LogisticsService {
@ -283,34 +284,19 @@ export class LogisticsService {
} }
} }
async getShipmentFee(data: ShipmentBookDTO) { async getShipmentFee(data: ShipmentFeeBookDTO) {
try { try {
const stock_point = await this.stockPointModel.findOneBy({ id: data.stockPointId}); const stock_point = await this.stockPointModel.findOneBy({ id: data.stockPointId});
const reqBody = { const reqBody = {
sender: data.details.origin.contact_name, ...convertKeysFromCamelToSnake(data),
start_phone: data.details.origin.phone_number,
start_postal_code: data.details.origin.address.postal_code.replace(/\s/g, ''),
pickup_address: data.details.origin.address.address_line_1,
pickup_warehouse: stock_point.upStreamStockPointId, pickup_warehouse: stock_point.upStreamStockPointId,
shipper_country_code: data.details.origin.address.country,
receiver: data.details.destination.contact_name,
city: data.details.destination.address.city,
province: data.details.destination.address.region,
country: data.details.destination.address.country,
postal_code: data.details.destination.address.postal_code.replace(/\s/g, ''),
delivery_address: data.details.destination.address.address_line_1,
receiver_phone: data.details.destination.phone_number.number,
receiver_email: data.details.destination.email_addresses,
// item_description: data.sales, // todo: 货品信息
length: data.details.packaging_properties.packages[0].measurements.cuboid.l,
width: data.details.packaging_properties.packages[0].measurements.cuboid.w,
height: data.details.packaging_properties.packages[0].measurements.cuboid.h,
dimension_uom: data.details.packaging_properties.packages[0].measurements.cuboid.unit,
weight: data.details.packaging_properties.packages[0].measurements.weight.value,
weight_uom: data.details.packaging_properties.packages[0].measurements.weight.unit,
currency: 'CAD', currency: 'CAD',
// item_description: data.sales, // todo: 货品信息
} }
const resShipmentFee = await this.uniExpressService.getRates(reqBody); const resShipmentFee = await this.uniExpressService.getRates(reqBody);
if (resShipmentFee.status !== 'SUCCESS') {
throw new Error(resShipmentFee.ret_msg);
}
return resShipmentFee.data.totalAfterTax * 100; return resShipmentFee.data.totalAfterTax * 100;
} catch (e) { } catch (e) {
throw e; throw e;

View File

@ -546,7 +546,7 @@ export class OrderService {
current, current,
pageSize, pageSize,
customer_email, customer_email,
}) { }, user = undefined) {
const parameters: any[] = []; const parameters: any[] = [];
// 基础查询 // 基础查询
@ -629,6 +629,13 @@ export class OrderService {
totalQuery += ` AND o.date_created <= ?`; totalQuery += ` AND o.date_created <= ?`;
parameters.push(endDate); parameters.push(endDate);
} }
if (!user.isSuper) {
sqlQuery += ` AND o.date_created >= ?`;
totalQuery += ` AND o.date_created >= ?`;
const tenDaysAgo = new Date();
tenDaysAgo.setDate(tenDaysAgo.getDate() - 10);
parameters.push(new Date(tenDaysAgo).toISOString().substring(0, 10));
}
// 处理 status 参数 // 处理 status 参数
if (status) { if (status) {

View File

@ -70,6 +70,7 @@ export class UserService {
id: user.id, id: user.id,
deviceId, deviceId,
username: user.username, username: user.username,
isSuper: user.isSuper,
}); });
return { return {

View File

@ -0,0 +1,36 @@
function camelToSnake(str: string): string {
return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
}
function snakeToCamel(str: string): string {
return str.replace(/(_[\w])/g, (match) =>
match[1].toUpperCase()
);
}
export function convertKeysFromSnakeToCamel<T>(obj: T): T {
if (Array.isArray(obj)) {
return obj.map(convertKeysFromSnakeToCamel) as unknown as T;
} else if (obj !== null && typeof obj === 'object') {
return Object.keys(obj).reduce((acc, key) => {
const newKey = snakeToCamel(key);
acc[newKey] = convertKeysFromSnakeToCamel((obj as any)[key]);
return acc;
}, {} as any);
}
return obj;
}
export function convertKeysFromCamelToSnake<T>(obj: T): T {
if (Array.isArray(obj)) {
return obj.map(convertKeysFromCamelToSnake) as unknown as T;
} else if (obj !== null && typeof obj === 'object') {
return Object.keys(obj).reduce((acc, key) => {
const newKey = camelToSnake(key);
acc[newKey] = convertKeysFromCamelToSnake((obj as any)[key]);
return acc;
}, {} as any);
}
return obj;
}