Merge branch 'test' of https://git.lionquexpress.com/wuweihua/BMS into test
This commit is contained in:
@@ -36,6 +36,10 @@ public interface ArBillMapper {
|
||||
|
||||
int insertArBill(ArBill bill);
|
||||
|
||||
int updateProfitSnapshot(@Param("arBillId") Long arBillId,
|
||||
@Param("shenzhenArea") String shenzhenArea,
|
||||
@Param("guangzhouArea") String guangzhouArea);
|
||||
|
||||
int updateArBillStatus(@Param("arBillId") Long arBillId, @Param("status") String status,
|
||||
@Param("remark") String remark, @Param("operator") String operator,
|
||||
@Param("fromStatus") String fromStatus);
|
||||
|
||||
+6
@@ -935,6 +935,12 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
throw new ServiceException("账单生成结果为空或订单数量发生变化,请重新生成");
|
||||
}
|
||||
ArBill finalBill = billMapper.selectArBillById(task.getArBillId());
|
||||
// 明细与费用已全部落库;快照和 READY 状态必须在同一事务中提交。
|
||||
if (billMapper.updateProfitSnapshot(task.getArBillId(),
|
||||
com.bms.price.enums.ProfitAreaRule.SHENZHEN.getCustomerArea(),
|
||||
com.bms.price.enums.ProfitAreaRule.GUANGZHOU.getCustomerArea()) != 1) {
|
||||
throw new ServiceException("账单毛利快照更新失败,请重新生成");
|
||||
}
|
||||
billMapper.updateArBillGenerationStatus(task.getArBillId(),
|
||||
ArBillGenerationStatus.READY, task.getCreateBy(), null);
|
||||
if (generateTaskMapper.markSuccess(taskId, new Date()) != 1) {
|
||||
|
||||
@@ -193,6 +193,49 @@
|
||||
#{confirmedBy}, #{confirmedTime}, #{createBy}, #{createUserId}, sysdate(), #{updateBy}, sysdate())
|
||||
</insert>
|
||||
|
||||
<!-- 只在生成完成时汇总当前账单;历史回填使用相同的校验口径。 -->
|
||||
<update id="updateProfitSnapshot">
|
||||
update ar_bill b
|
||||
left join (
|
||||
select d.ar_bill_id, count(*) as detail_count, sum(d.total_amount) as detail_total,
|
||||
count(distinct d.currency) as detail_currency_count, min(d.currency) as detail_currency,
|
||||
sum(case when d.currency is not null and f.currency_count = 1 and f.fee_currency = d.currency
|
||||
then 0 else 1 end) as currency_errors,
|
||||
sum(case when d.total_amount is not null and f.sales_amount is not null
|
||||
and f.sales_amount = d.total_amount then 0 else 1 end) as amount_errors,
|
||||
case when count(f.product_amount) = count(*) then sum(f.product_amount) else null end as product_total,
|
||||
case when count(f.redline_amount) = count(*) then sum(f.redline_amount) else null end as redline_total
|
||||
from ar_bill_detail d
|
||||
left join (
|
||||
select fee.detail_id,
|
||||
case when count(fee.amount) = count(*) then sum(fee.amount) else null end as sales_amount,
|
||||
case when count(fee.currency) = count(*) then count(distinct fee.currency) else 0 end as currency_count,
|
||||
min(fee.currency) as fee_currency,
|
||||
case when count(fee.product_amount) = count(*) then sum(fee.product_amount) else null end as product_amount,
|
||||
case when count(fee.redline_amount) = count(*) then sum(fee.redline_amount) else null end as redline_amount
|
||||
from ar_bill_detail_fee fee
|
||||
join ar_bill_detail fd on fd.detail_id = fee.detail_id
|
||||
where fd.ar_bill_id = #{arBillId}
|
||||
group by fee.detail_id
|
||||
) f on f.detail_id = d.detail_id
|
||||
where d.ar_bill_id = #{arBillId}
|
||||
group by d.ar_bill_id
|
||||
) a on a.ar_bill_id = b.ar_bill_id
|
||||
set b.product_amount = case when abs(a.product_total) <= 99999999999999.9999 then a.product_total else null end,
|
||||
b.redline_amount = case when abs(a.redline_total) <= 99999999999999.9999 then a.redline_total else null end,
|
||||
b.profit_calc_status = case
|
||||
when a.detail_count is null or a.detail_count = 0 then 'NO_DETAIL'
|
||||
when b.profit_customer_area is null or b.profit_customer_area not in (#{shenzhenArea}, #{guangzhouArea}) then 'MISSING_AREA'
|
||||
when b.currency is null or a.currency_errors > 0 or a.detail_currency_count != 1 or a.detail_currency != b.currency then 'CURRENCY_MISMATCH'
|
||||
when b.total_amount is null or a.amount_errors > 0 or a.detail_total != b.total_amount then 'AMOUNT_MISMATCH'
|
||||
when (b.profit_customer_area = #{shenzhenArea} and a.product_total is null)
|
||||
or (b.profit_customer_area = #{guangzhouArea} and a.redline_total is null) then 'MISSING_PRICE'
|
||||
when (b.profit_customer_area = #{shenzhenArea} and abs(a.product_total) > 99999999999999.9999)
|
||||
or (b.profit_customer_area = #{guangzhouArea} and abs(a.redline_total) > 99999999999999.9999) then 'PRICE_OVERFLOW'
|
||||
else 'READY' end
|
||||
where b.ar_bill_id = #{arBillId} and b.generation_status = 'GENERATING'
|
||||
</update>
|
||||
|
||||
<update id="updateArBillStatus">
|
||||
update ar_bill
|
||||
set status = #{status},
|
||||
|
||||
@@ -60,7 +60,16 @@
|
||||
<if test="query.endBillDate != null">and b.bill_date <= #{query.endBillDate}</if>
|
||||
</sql>
|
||||
|
||||
<!-- 按费用快照先聚合到订单,再聚合到完整账单,避免账单金额及费用重复。 -->
|
||||
<!-- 报表直接读取账单快照。 -->
|
||||
<sql id="validProfitSnapshot">
|
||||
b.profit_calc_status = 'READY' and b.total_amount is not null
|
||||
and ((b.profit_customer_area = #{shenzhenArea} and b.product_amount is not null)
|
||||
or (b.profit_customer_area = #{guangzhouArea} and b.redline_amount is not null))
|
||||
</sql>
|
||||
<sql id="areaProductAmount">
|
||||
case when b.profit_customer_area = #{shenzhenArea} then b.product_amount
|
||||
when b.profit_customer_area = #{guangzhouArea} then b.redline_amount else null end
|
||||
</sql>
|
||||
<sql id="billRows">
|
||||
<bind name="shenzhenArea" value="@com.bms.price.enums.ProfitAreaRule@SHENZHEN.getCustomerArea()"/>
|
||||
<bind name="guangzhouArea" value="@com.bms.price.enums.ProfitAreaRule@GUANGZHOU.getCustomerArea()"/>
|
||||
@@ -68,45 +77,12 @@
|
||||
b.profit_customer_area as customer_area,
|
||||
b.profit_sales_user_name as sales_user_name, b.currency, b.status,
|
||||
b.total_amount as sales_amount, b.written_off_amount, b.unwritten_amount,
|
||||
case when a.detail_count > 0 and a.invalid_count = 0 and b.total_amount is not null
|
||||
and a.detail_total = b.total_amount then a.product_total else null end as product_amount,
|
||||
case when a.detail_count > 0 and a.invalid_count = 0 and b.total_amount is not null
|
||||
and a.detail_total = b.total_amount then b.total_amount - a.product_total else null end as sales_gross_profit,
|
||||
case when a.detail_count > 0 and a.invalid_count = 0 and b.total_amount is not null
|
||||
and a.detail_total = b.total_amount and b.total_amount != 0
|
||||
then round((b.total_amount - a.product_total) * 100 / b.total_amount, 4) else null end as sales_gross_margin_rate,
|
||||
case when a.detail_count > 0 and a.invalid_count = 0 and b.total_amount is not null
|
||||
and a.detail_total = b.total_amount then 0 else 1 end as profit_incomplete
|
||||
case when <include refid="validProfitSnapshot"/> then <include refid="areaProductAmount"/> else null end as product_amount,
|
||||
case when <include refid="validProfitSnapshot"/> then b.total_amount - (<include refid="areaProductAmount"/>) else null end as sales_gross_profit,
|
||||
case when <include refid="validProfitSnapshot"/> and b.total_amount != 0
|
||||
then round((b.total_amount - (<include refid="areaProductAmount"/>)) * 100 / b.total_amount, 4) else null end as sales_gross_margin_rate,
|
||||
case when <include refid="validProfitSnapshot"/> then 0 else 1 end as profit_incomplete
|
||||
from ar_bill b
|
||||
left join (
|
||||
select d.ar_bill_id, count(*) as detail_count, sum(d.total_amount) as detail_total,
|
||||
sum(case when d.total_amount is not null and d.currency is not null and b.currency is not null
|
||||
and d.currency = b.currency and f.currency_count = 1 and f.fee_currency = d.currency
|
||||
and f.sales_amount is not null and f.sales_amount = d.total_amount
|
||||
and ((b.profit_customer_area = #{shenzhenArea} and f.product_complete = 1)
|
||||
or (b.profit_customer_area = #{guangzhouArea} and f.redline_complete = 1))
|
||||
then 0 else 1 end) as invalid_count,
|
||||
sum(case when b.profit_customer_area = #{shenzhenArea} then f.product_amount
|
||||
when b.profit_customer_area = #{guangzhouArea} then f.redline_amount else null end) as product_total
|
||||
from ar_bill_detail d join ar_bill b on b.ar_bill_id = d.ar_bill_id
|
||||
left join (
|
||||
select fee.detail_id,
|
||||
case when count(fee.amount) = count(*) then sum(fee.amount) else null end as sales_amount,
|
||||
case when count(fee.currency) = count(*) then count(distinct fee.currency) else 0 end as currency_count,
|
||||
min(fee.currency) as fee_currency,
|
||||
case when count(fee.product_amount) = count(*) then sum(fee.product_amount) else null end as product_amount,
|
||||
case when count(fee.redline_amount) = count(*) then sum(fee.redline_amount) else null end as redline_amount,
|
||||
case when count(fee.product_amount) = count(*) then 1 else 0 end as product_complete,
|
||||
case when count(fee.redline_amount) = count(*) then 1 else 0 end as redline_complete
|
||||
from ar_bill_detail_fee fee
|
||||
join ar_bill_detail d on d.detail_id = fee.detail_id
|
||||
join ar_bill b on b.ar_bill_id = d.ar_bill_id
|
||||
<include refid="billConditions"/>
|
||||
group by fee.detail_id
|
||||
) f on f.detail_id = d.detail_id
|
||||
<include refid="billConditions"/>
|
||||
group by d.ar_bill_id
|
||||
) a on a.ar_bill_id = b.ar_bill_id
|
||||
<include refid="billConditions"/>
|
||||
</sql>
|
||||
<select id="selectBills" resultMap="row">
|
||||
|
||||
Reference in New Issue
Block a user