仅生成发票号码的代码并不是解决方案。你很快就会遇到问题。
通过查看最后一个发票号码(而不是序列)来动态生成发票号码的一个问题是冲突。用户 1 打开表单,代码检查最后一个发票号码 (INV1/23) 并生成一个新发票号码 - 比如说 INV2/23。现在,用户 2 在另一个会话中打开该表单。该代码将生成相同的 INV2/23,因为最后保存的值是 INV1/23,然后当第二次使用保存时...将出现唯一约束违规。
我的建议是创建一个表,其中包含您想要的格式的生成发票号码(您的要求太模糊,无法为您提供代码),并使用一些代码来决定下一个要提取的号码,因此每个值仅使用一次。这还允许您重复使用孤立值(例如,当使用发票编号但随后交易被取消时)。我建议观看this https://www.youtube.com/watch?v=B5JltFoe5Ho来自 Connor 的视频解释了我刚才描述的解决方案。它适用于序列,但您可以对发票编号使用相同的逻辑。
这是代码。
create table invoice_numbers (
id number generated by default on null as identity
constraint invoice_numbers_id_pk primary key,
seq number,
invoice_year number,
state varchar2(10 char),
invoice_num as ('INV'||seq||'/'||SUBSTR(invoice_year,3,2))
)
;
DECLARE
BEGIN
FOR i IN 1..100 LOOP
INSERT INTO invoice_numbers (seq,invoice_year, state)
values (i,2023,'free');
END LOOP;
END;
/
select * from invoice_numbers;
CREATE OR REPLACE FUNCTION next_invoice_number (year_i NUMBER) RETURN VARCHAR2
IS
l_invoice_num VARCHAR2(100);
l_id NUMBER;
CURSOR next_invoice_num IS
SELECT invoice_num, id
FROM invoice_numbers
WHERE invoice_year = year_i
AND state = 'free'
ORDER BY seq
FOR UPDATE SKIP LOCKED;
BEGIN
OPEN next_invoice_num;
FETCH next_invoice_num INTO l_invoice_num, l_id;
CLOSE next_invoice_num;
UPDATE invoice_numbers SET state = 'used' WHERE id = l_id;
RETURN l_invoice_num;
END;
/
然后在您的 apex 表单中,使用源(pl/sql 表达式)创建发票编号的提交前计算
next_invoice_number(extract (year from sysdate))
请注意,您应该只在提交之前计算发票号码 - 如果在表单上完成,则发票号码将被标记为“已使用”。因此,如果用户随后关闭屏幕而不保存发票,您将丢失该号码。
请注意,您每年都需要一些代码来填充invoice_numbers 表,并需要一些代码来检查您是否没有用完数字。