using System.Globalization; namespace Admin.NET.Plugin.AiDOP.Supply; /// /// 采购单号生成:类型前缀 + yyyyMMdd + 固定宽度流水(事务内 FOR UPDATE 取号)。 /// public static class PurOrdNumberGenerator { public static async Task NextAsync(ISqlSugarClient db, string typePrefix, DateTime sequenceDate, int serialWidth) { var batch = await NextBatchAsync(db, typePrefix, sequenceDate, serialWidth, 1); return batch[0]; } public static async Task> NextBatchAsync( ISqlSugarClient db, string typePrefix, DateTime sequenceDate, int serialWidth, int count) { if (count <= 0) throw Oops.Oh("编号数量必须大于 0。"); if (serialWidth <= 0 || serialWidth > 9) throw Oops.Oh("流水号宽度无效。"); var prefix = typePrefix.Trim() + sequenceDate.ToString("yyyyMMdd", CultureInfo.InvariantCulture); var maxSeq = await db.Ado.GetIntAsync( """ SELECT IFNULL(MAX(CAST(RIGHT(TRIM(PurOrd), @SerialWidth) AS UNSIGNED)), 0) FROM PurOrdMaster WHERE TRIM(PurOrd) LIKE CONCAT(@Prefix, '%') AND CHAR_LENGTH(TRIM(PurOrd)) = CHAR_LENGTH(@Prefix) + @SerialWidth FOR UPDATE """, new SugarParameter("@Prefix", prefix), new SugarParameter("@SerialWidth", serialWidth)); var maxSerial = (int)Math.Pow(10, serialWidth) - 1; var result = new List(count); for (var i = 1; i <= count; i++) { var next = maxSeq + i; if (next > maxSerial) throw Oops.Oh($"当日{typePrefix.Trim()}单号流水已超过 {maxSerial}(前缀 {prefix})"); result.Add(prefix + next.ToString($"D{serialWidth}", CultureInfo.InvariantCulture)); } return result; } /// /// PurOrdRctMaster.Receiver:类型前缀 + yyyyMMdd + 固定宽度流水(如 PT202605190001)。 /// public static async Task NextRctReceiverAsync( ISqlSugarClient db, string typePrefix, string rctType, DateTime sequenceDate, int serialWidth) { if (string.IsNullOrWhiteSpace(typePrefix)) throw Oops.Oh("单号前缀无效。"); if (string.IsNullOrWhiteSpace(rctType)) throw Oops.Oh("收货类型无效。"); if (serialWidth <= 0 || serialWidth > 9) throw Oops.Oh("流水号宽度无效。"); var prefix = typePrefix.Trim() + sequenceDate.ToString("yyyyMMdd", CultureInfo.InvariantCulture); var maxSeq = await db.Ado.GetIntAsync( """ SELECT IFNULL(MAX(CAST(RIGHT(TRIM(Receiver), @SerialWidth) AS UNSIGNED)), 0) FROM PurOrdRctMaster WHERE RctType = @RctType AND TRIM(Receiver) LIKE CONCAT(@Prefix, '%') AND CHAR_LENGTH(TRIM(Receiver)) = CHAR_LENGTH(@Prefix) + @SerialWidth FOR UPDATE """, new SugarParameter("@Prefix", prefix), new SugarParameter("@RctType", rctType.Trim()), new SugarParameter("@SerialWidth", serialWidth)); var maxSerial = (int)Math.Pow(10, serialWidth) - 1; var next = maxSeq + 1; if (next > maxSerial) throw Oops.Oh($"当日{typePrefix.Trim()}单号流水已超过 {maxSerial}(前缀 {prefix})"); return prefix + next.ToString($"D{serialWidth}", CultureInfo.InvariantCulture); } }