diff --git a/packages/plugins/@hera/plugin-rental/src/client/hooks/usePdfPath.tsx b/packages/plugins/@hera/plugin-rental/src/client/hooks/usePdfPath.tsx index 9ea0b1e56..734f5f016 100644 --- a/packages/plugins/@hera/plugin-rental/src/client/hooks/usePdfPath.tsx +++ b/packages/plugins/@hera/plugin-rental/src/client/hooks/usePdfPath.tsx @@ -58,12 +58,14 @@ export const PdfIsDoubleProvider = (props) => { export const useRecordPdfPath = () => { const record = useRecord(); - let recordId = record.id; + let recordId = record.id || record.record_id; + let stockId; if (record.__collectionName === 'contracts' && record.__parent) { + // 查看页面,中间表id recordId = record.__parent.id; } - if (typeof record.id === 'string') { - recordId = record.id.split('_')[1] || record.id; + if (record.__collectionName === 'record_stock') { + stockId = record.id; } const { isDouble } = useContext(PdfIsDoubleContext); const { settingType } = useContext(PdfIsLoadContext); @@ -73,8 +75,8 @@ export const useRecordPdfPath = () => { const { annotate } = useContext(AnnotateContext); const path = useMemo( () => - `/records:pdf?recordId=${recordId}&isDouble=${isDouble}&settingType=${settingType}&margingTop=${margingTop}&paper=${paper}&font=${size}&annotate=${annotate}`, - [recordId, isDouble, settingType, margingTop, paper, size, annotate], + `/records:pdf?recordId=${recordId}&stockId=${stockId}&isDouble=${isDouble}&settingType=${settingType}&margingTop=${margingTop}&paper=${paper}&font=${size}&annotate=${annotate}`, + [recordId, isDouble, settingType, margingTop, paper, size, annotate, stockId], ); return path; }; diff --git a/packages/plugins/@hera/plugin-rental/src/server/actions/records-controller.ts b/packages/plugins/@hera/plugin-rental/src/server/actions/records-controller.ts index bc3c928c6..7493da2dd 100644 --- a/packages/plugins/@hera/plugin-rental/src/server/actions/records-controller.ts +++ b/packages/plugins/@hera/plugin-rental/src/server/actions/records-controller.ts @@ -195,108 +195,237 @@ export class RecordPreviewController { @Action('pdf') async printPreview(ctx: Context) { + // 中间表id,盘点单id,单双列展示,人工/全部/带金额,距上边距,纸张,字体,注解 const { - params: { recordId: id, isDouble, settingType, margingTop, paper, font, annotate }, + params: { recordId: id, stockId, isDouble, settingType, margingTop, paper, font, annotate }, } = ctx.action; + + // #region 样式参数 let pdfTop: number; - const isAnnotate = annotate === 'true' ? true : false; - // 查询合同订单中间表,获得订单id,合同id,出入库信息 - const intermediate = await ctx.db.getRepository('record_contract').findOne({ filter: { id } }); - const recordId = intermediate.record_id; - const contractId = intermediate.contract_id; - // 订单基本数据 - const baseRecord = await ctx.db.getRepository('records').findOne({ - filter: { id: recordId }, - appends: [ - 'vehicles', - 'in_stock', - 'in_stock.company', - 'in_stock.contacts', - 'out_stock', - 'out_stock.company', - 'out_stock.contacts', - ], - }); - const userID = baseRecord.createdById || baseRecord.updatedById; - const user = await ctx.db.getRepository('users').findOne({ filter: { id: userID } }); - baseRecord.nickname = user?.nickname || ''; - baseRecord.userPhone = user?.phone || ''; - // 拉侧面文字说明 - const pdfExplain = await ctx.db.getRepository('basic_configuration').find(); - baseRecord.pdfExplain = pdfExplain[0]?.out_of_storage_explain; - const products_view = this.sqlLoader.sqlFiles['products_search_rule_special']; - await ctx.db.sequelize.query(products_view); - // 租金数据 - const leaseData: any = await ctx.db.sequelize.query(this.sqlLoader.sqlFiles['pdf_record_product_item'], { - replacements: { - recordId, - contractId, - }, - type: QueryTypes.SELECT, - }); - // 租金赔偿数据 - const leaseFeeData: any = await ctx.db.sequelize.query(this.sqlLoader.sqlFiles['pdf_record_product_fee_item'], { - replacements: { - intermediateId: intermediate.id, - }, - type: QueryTypes.SELECT, - }); - // 无关联数据 - const noLeaseProductFeeData: any = await ctx.db.sequelize.query( - this.sqlLoader.sqlFiles['pdf_record_no_porduct_fees'], - { - replacements: { - recordId, - contractId, - }, - type: QueryTypes.SELECT, - }, - ); - - // 比如运费按照出入库量,但是录单存在排除的情况,特殊处理 - const noRuleexcluded: any = await ctx.db.sequelize.query( - ` - select - rfin.count , - rfin."comment" , - rfin.new_fee_product_id, - p2.name || '[' || p.name || ']' as fee_name, - p.custom_name, - rfin.is_excluded - from record_contract rc - join record_fee_items_new rfin on rfin.record_contract_id = rc.id and rfin.is_excluded is true and rfin.new_product_id is null - join products p on p.id = rfin.new_fee_product_id - left join products p2 on p."parentId" = p2.id - where rc.id = :intermediateId - `, - { - replacements: { - intermediateId: intermediate.id, - }, - type: QueryTypes.SELECT, - }, - ); - // 合同基本数据 - const contracts = await ctx.db.getRepository('contracts').findOne({ - filter: { - id: intermediate.contract_id, - }, - appends: ['first_party', 'first_party.projects', 'party_b', 'party_b.projects'], - }); - contracts.movement = intermediate.movement; - - const double = isDouble === '0' || isDouble === '1' ? isDouble : pdfExplain[0].record_columns; - const printSetup = - settingType === '0' || settingType === '1' || settingType === '2' - ? settingType - : pdfExplain[0]?.record_print_setup; if (Number(margingTop)) { pdfTop = Number(margingTop); } else { const currentUser = await ctx.db.getRepository('users').findOne({ filter: { id: ctx.state.currentUser.id } }); pdfTop = Number(currentUser?.pdf_top_margin); } + const isAnnotate = annotate === 'true' ? true : false; + const pdfExplain = await ctx.db.getRepository('basic_configuration').find(); + const double = isDouble === '0' || isDouble === '1' ? isDouble : pdfExplain[0].record_columns; + const printSetup = + settingType === '0' || settingType === '1' || settingType === '2' + ? settingType + : pdfExplain[0]?.record_print_setup; + // #endregion 样式参数 + + // #region 查询视图前执行更新视图,用来确定所有产品的相关父级id + const products_view = this.sqlLoader.sqlFiles['products_search_rule_special']; + await ctx.db.sequelize.query(products_view); + // #endregion + + // 1.盘点单 只需要 leaseData + // 2.租赁/购销单 需要 leaseData、leaseFeeData、noLeaseProductFeeData、noRuleexcluded + // 3.暂存单 只需要 leaseData + let leaseData = []; + let leaseFeeData = []; + let noLeaseProductFeeData = []; + let noRuleexcluded = []; + let contracts = {}; + let intermediate: any; + let baseRecord: any; + if (stockId !== 'undefined') { + // 盘点单 + leaseData = await ctx.db.sequelize.query( + ` + select + p.id AS products_id, + p2.id AS "parentId", + ri."comment", + p2.name AS "parentName", + p2.name || '[' || p.name || ']' AS "name", + p2.unit, + p2.convertible, + p2.conversion_unit, + p.weight AS products_weight, + p.ratio AS products_ratio, + ri.count, + 2 as conversion_logic_id + from record_stock rs + join record_items ri on ri.stock_id = rs.id + join products p on p.id = ri.new_product_id + left join products p2 on p2.id = p."parentId" + where rs.id = :stockId`, + { + replacements: { + stockId, + }, + type: QueryTypes.SELECT, + }, + ); + const record_stock = await ctx.db + .getRepository('record_stock') + .findOne({ where: { id: stockId }, appends: ['project'] }); + const userID = record_stock.createdById || record_stock.updatedById || 6; // 记得将盘点用户信息补全 + const user = await ctx.db.getRepository('users').findOne({ filter: { id: userID } }); + baseRecord = { + number: record_stock.id, // 记得生成单号替换 + date: record_stock.date, + pdfExplain: pdfExplain[0]?.out_of_storage_explain, + nickname: user.nickname, + userPhone: user.phone, + systemName: pdfExplain[0]?.name, + plate: record_stock.project.name, + }; + } else { + // 租赁/购销/暂存单 + // 判断是外部视图查看还是表单中间表查看 + let model = 'record_contract'; + let isStock = false; + if (id.split('_').length > 1) { + // 视图的情况 + model = 'view_records_contracts'; + } + intermediate = await ctx.db.getRepository(model).findOne({ filter: { id } }); // 中间表/出入库视图 + const recordId = intermediate.record_id; // 订单id + const contractId = intermediate.contract_id; // 合同id + let intermediateId = intermediate.id; // 中间表id + + if (id.split('_').length > 1) { + // 视图的情况 + intermediateId = parseInt(id.split('_')[1]); + } + baseRecord = await ctx.db.getRepository('records').findOne({ + filter: { id: recordId }, + appends: [ + 'vehicles', + 'in_stock', + 'in_stock.company', + 'in_stock.contacts', + 'out_stock', + 'out_stock.company', + 'out_stock.contacts', + ], + }); + let number; + if (intermediate.number) { + // 视图查看 + number = intermediate.number; + } else if (!intermediate.number && model === 'record_contract') { + const view = await ctx.db + .getRepository('view_records_contracts') + .findOne({ filter: { rc_id: intermediateId } }); + number = view.number; + } + baseRecord.number = number || baseRecord.number; + // 3.拼接订单的pdf基础数据, 用户信息 + const userID = baseRecord.createdById || baseRecord.updatedById; + const user = await ctx.db.getRepository('users').findOne({ filter: { id: userID } }); + baseRecord.nickname = user?.nickname || ''; + baseRecord.userPhone = user?.phone || ''; + // 侧面栏提示信息 + baseRecord.pdfExplain = pdfExplain[0]?.out_of_storage_explain; + baseRecord.systemName = pdfExplain[0]?.name; + + isStock = intermediate.record_category === '3'; // 判断是否为暂存单 + if (isStock) { + contracts['record_category'] = '3'; + const company = await ctx.db.getRepository('company').findOne({ + filter: { + id: intermediate.company_id, + }, + appends: ['projects'], + }); + contracts['first_party'] = company; + const movement = company.projects.find((item) => item.id === baseRecord.in_stock_id) ? '1' : '-1'; + contracts['movement'] = movement; + // 暂存单只需要leaseDate + leaseData = await ctx.db.sequelize.query( + ` + select + p.id AS products_id, + p2.id AS "parentId", + ri."comment", + p2.name AS "parentName", + p2.name || '[' || p.name || ']' AS "name", + p2.unit, + p2.convertible, + p2.conversion_unit, + p.weight AS products_weight, + p.ratio AS products_ratio, + ri.count, + 2 as conversion_logic_id + from records r + join record_items ri on ri.record_id = r.id + join products p on p.id = ri.new_product_id + left join products p2 on p2.id = p."parentId" + where r.id = :recordId`, + { + replacements: { + recordId, + }, + type: QueryTypes.SELECT, + }, + ); + } else { + contracts = await ctx.db.getRepository('contracts').findOne({ + filter: { + id: intermediate.contract_id, + }, + appends: ['first_party', 'first_party.projects', 'party_b', 'party_b.projects'], + }); + contracts['movement'] = intermediate.movement; + // 租赁/购销 + leaseData = await ctx.db.sequelize.query(this.sqlLoader.sqlFiles['pdf_record_product_item'], { + replacements: { + recordId, + contractId, + }, + type: QueryTypes.SELECT, + }); + // 租金产品赔偿 + leaseFeeData = await ctx.db.sequelize.query(this.sqlLoader.sqlFiles['pdf_record_product_fee_item'], { + replacements: { + intermediateId: parseInt(intermediateId), + }, + type: QueryTypes.SELECT, + }); + + // 无关联数据 + noLeaseProductFeeData = await ctx.db.sequelize.query(this.sqlLoader.sqlFiles['pdf_record_no_porduct_fees'], { + replacements: { + recordId, + contractId, + }, + type: QueryTypes.SELECT, + }); + + // 比如运费按照出入库量,但是录单存在排除的情况,特殊处理 + noRuleexcluded = await ctx.db.sequelize.query( + ` + select + rfin.count , + rfin."comment" , + rfin.new_fee_product_id, + p2.name || '[' || p.name || ']' as fee_name, + p.custom_name, + rfin.is_excluded + from record_contract rc + join record_fee_items_new rfin on rfin.record_contract_id = rc.id and rfin.is_excluded is true and rfin.new_product_id is null + join products p on p.id = rfin.new_fee_product_id + left join products p2 on p."parentId" = p2.id + where rc.id = :intermediateId + `, + { + replacements: { + intermediateId: parseInt(intermediateId), + }, + type: QueryTypes.SELECT, + }, + ); + } + } + + // #endregion const cache = ctx.app.cacheManager.getCache('@hera/plugin-rental') as Cache; const key = stringify({ intermediate, diff --git a/packages/plugins/@hera/plugin-rental/src/server/pdf-documents/records-documentV2.tsx b/packages/plugins/@hera/plugin-rental/src/server/pdf-documents/records-documentV2.tsx index bceacf3bc..678561c44 100644 --- a/packages/plugins/@hera/plugin-rental/src/server/pdf-documents/records-documentV2.tsx +++ b/packages/plugins/@hera/plugin-rental/src/server/pdf-documents/records-documentV2.tsx @@ -222,14 +222,13 @@ const PreviewDocument = ({ } const paper = options.paper; const isDouble = Number(options.isDouble); - const explain = - detail.type_new === '1' - ? `盘点单用于清算仓库盈亏盈余。` - : `如供需双方未签正式合同,本${ - detail.record_category - }${detail.movement}单经供需双方代表签字确认后, 将作为合同及发生业务往来的有效凭证,如已签合同,则成为该合同的组成部分。${ - detail.movement === '入库' ? '出库方' : '采购方' - }须核对 以上产品规格、数量确认后可签字认可。`; + const explain = !detail.record_category + ? `盘点单用于清算仓库盈亏盈余。` + : `如供需双方未签正式合同,本${ + detail.record_category + }${detail.movement}单经供需双方代表签字确认后, 将作为合同及发生业务往来的有效凭证,如已签合同,则成为该合同的组成部分。${ + detail.movement === '入库' ? '出库方' : '采购方' + }须核对 以上产品规格、数量确认后可签字认可。`; const getAllPrice = () => { let price = 0; if (detail.record_category === '购销' && priceRule.filter(Boolean).length) { @@ -377,15 +376,18 @@ const PreviewDocument = ({ )); }; - const projectPhone = detail.record_party_b.contacts?.map((item) => (item.name || '') + (item.phone || '')).join(' '); - + const projectPhone = detail.record_party_b?.contacts?.map((item) => (item.name || '') + (item.phone || '')).join(' '); const car = detail.vehicles ? detail.vehicles.map((item) => item?.number).join(' ') : ''; return ( {' '} {/**transform: `scale(${trans})` */} - {detail.contract_first_party?.name || '异常数据,请联系相关负责人!'} + + {!detail.record_category + ? detail.plate + : detail.contract_first_party?.name || detail.systemName || '异常数据,请联系相关负责人!'} + {detail.contract_first_party ? detail.movement : '盘点'}单 @@ -415,11 +417,12 @@ const PreviewDocument = ({ )} - {detail.record_category === '购销' && ( + {(detail.record_category === '购销' || detail.record_category === '暂存') && ( - 销售单位:{detail.record_party_b.company.name || ''} {detail.record_party_b.name || ''} + {detail.record_category === '暂存' ? '出库方:' : '销售单位:'} + {detail.record_party_b?.company?.name || ''} {detail.record_party_b.name || ''} 日期:{detail.record_date && dayjs(detail.record_date).format('YYYY-MM-DD')} @@ -427,7 +430,10 @@ const PreviewDocument = ({ 流水号:{detail.record_number} - 采购单位:{detail.record_party_a.name || ''} + + {detail.record_category === '暂存' ? '入库方:' : '采购单位:'} + {detail.record_party_a.name || ''} + 车号:{car} 原始单号:{detail.record_origin} @@ -436,7 +442,7 @@ const PreviewDocument = ({ {!detail.record_category && ( - 盘点单位:{detail.record_party_a.name || ''} + 盘点单位:{detail.plate || ''} 日期:{detail.record_date && dayjs(detail.record_date).format('YYYY-MM-DD')} diff --git a/packages/plugins/@hera/plugin-rental/src/server/services/record-pdf-service.ts b/packages/plugins/@hera/plugin-rental/src/server/services/record-pdf-service.ts index e8b7e4999..7ec68e6f2 100644 --- a/packages/plugins/@hera/plugin-rental/src/server/services/record-pdf-service.ts +++ b/packages/plugins/@hera/plugin-rental/src/server/services/record-pdf-service.ts @@ -36,28 +36,30 @@ export class RecordPdfService { }; return data[movement]; }; - const record_category = (category) => { const data = { '1': '购销', '2': '租赁', + '3': '暂存', + // 非盘点单的情况就是暂存单 }; return data[category]; }; const needRecord = { - record_type: baseRecord.type_new, record_number: baseRecord.number, record_date: baseRecord.date, - record_origin: baseRecord.origin, - record_party_b: movement(contracts.movement) === '出库' ? baseRecord.in_stock : baseRecord.out_stock, // 还需要判断第三个合同的情况,确定一下出库入是否合同公司有关 - record_party_a: movement(contracts.movement) === '入库' ? baseRecord.in_stock : baseRecord.out_stock, - vehicles: baseRecord.vehicles, + record_origin: baseRecord?.origin, + record_party_b: movement(contracts.movement) === '出库' ? baseRecord?.in_stock : baseRecord?.out_stock, // 还需要判断第三个合同的情况,确定一下出库入是否合同公司有关 + record_party_a: movement(contracts.movement) === '入库' ? baseRecord?.in_stock : baseRecord?.out_stock, + vehicles: baseRecord?.vehicles, record_category: record_category(contracts.record_category), contract_first_party: contracts.first_party, //公司信息,甲方,我们 movement: movement(contracts.movement), pdfExplain: baseRecord.pdfExplain, nickname: baseRecord.nickname, userPhone: baseRecord.userPhone, + systemName: baseRecord.systemName, + plate: baseRecord.plate, }; // !租金数据 const leasePorducts = leaseData.map((leas) => { @@ -126,7 +128,7 @@ export class RecordPdfService { total = count * fee.fee_weight; conversion_unit = 'KG'; } else if (fee.conversion_logic_id > 4) { - const ProductWeightRule = leaseData.findOne((leas) => leas.products_id === fee.products_id); + const ProductWeightRule = leaseData.find((leas) => leas.products_id === fee.products_id); if (ProductWeightRule.wr_logic_id === ConversionLogics.Keep) { total = count * ProductWeightRule.wr_weight; } else if (ProductWeightRule.wr_logic_id === ConversionLogics.Product) { diff --git a/packages/plugins/@hera/plugin-rental/src/server/sqls/pdf_record_product_item.sql b/packages/plugins/@hera/plugin-rental/src/server/sqls/pdf_record_product_item.sql index b173939f3..398a5267a 100644 --- a/packages/plugins/@hera/plugin-rental/src/server/sqls/pdf_record_product_item.sql +++ b/packages/plugins/@hera/plugin-rental/src/server/sqls/pdf_record_product_item.sql @@ -19,8 +19,7 @@ FROM records r JOIN contracts c ON c.id = :contractId LEFT JOIN contract_items ci ON c.id = ci.contract_id - AND ci.start_date <= r."date" - AND ci.end_date >= r."date" + AND ci.date_range @> r."date" LEFT JOIN contract_plans cp ON cp.id = ci.contract_plan_id JOIN contract_plan_lease_items cpli ON ( cpli.contract_plan_id = cp.id diff --git a/packages/plugins/@hera/plugin-rental/src/server/sqls/view_records_contracts.sql b/packages/plugins/@hera/plugin-rental/src/server/sqls/view_records_contracts.sql index baa7e400b..dc6f03ae2 100644 --- a/packages/plugins/@hera/plugin-rental/src/server/sqls/view_records_contracts.sql +++ b/packages/plugins/@hera/plugin-rental/src/server/sqls/view_records_contracts.sql @@ -12,7 +12,16 @@ SELECT p.id AS project_id, rc.has_receipt, rc.has_stub, - c.record_category + c.record_category, + ( + CASE + WHEN c1.abbreviation IS NOT NULL THEN c1.abbreviation::TEXT + ELSE c1.id::TEXT + END || '-' || CASE + WHEN c2.abbreviation IS NOT NULL THEN c2.abbreviation::TEXT + ELSE c2.id::TEXT + END || '-' || r.number + )::CHARACTER VARYING AS number FROM records r JOIN record_contract rc ON rc.record_id = r.id @@ -24,6 +33,7 @@ FROM ELSE r.in_stock_id END ) + JOIN company c2 ON c2.id = c.party_b_id WHERE r.direct_record_id IS NULL UNION ALL @@ -44,7 +54,8 @@ SELECT p3.id AS project_id, rc.has_receipt, rc.has_stub, - '3' AS record_category + '3' AS record_category, + r.number::VARCHAR AS number FROM records r LEFT JOIN record_contract rc ON rc.record_id = r.id