1

好的,所以我将进入当前项目的阶段,我将在该阶段实施发票,并考虑一下,我想我会看看你们将如何解决这个问题。如果相关,我正在使用 CodeIgniter、jQuery、jQuery UI,并且我可以完全控制服务器,运行 PHP 5.3 和 Apache 2.2.16。生产服务器正在运行 Debian Squeeze。

所以我的查询是这样的。

  • 我正在开发的应用程序将处理发票
  • 发票可以一张一张地生成,也可以批量生成(从一个日期范围开始)
  • 所有发票都应生成 PDF 并保存到服务器。我正在使用 mPDF。
  • 一些发票可以通过电子邮件发送给客户,其他发票必须只是 PDF 格式,如果可能,可以直接从 PHP 发送到打印机(lpr -p?)
  • 发票运行通常每两周进行一次
  • 发票运行通常涉及生成超过 100 个发票
  • 一些发票可能相当大,尽管典型的 PDF 大小可能是每张发票 2-5 页

基本上我想要一些提示。我正在寻求建议的主要领域是:

  • 批量开票 - 如果这是通过一个浏览器请求完成的,可能需要几分钟,并且 PHP 可能会超过最大执行时间。我想也许它通常可以通过 AJAX 完成,其中 jQuery 检索要制作的发票列表,然后遍历列表,请求 PHP 制作 PDF 并处理发票。因此,您有很多较小的请求,而不是一个大请求?这是推荐的吗?有更好的方法吗?
  • 批量打印。用户担心每次运行都必须手动打印数十张发票,这是可以理解的。处理从 PHP 到本地打印机的批量发票打印的最佳方法是什么?我已经阅读了有关使用lpr盒子将输出发送到打印机的信息,但我担心在 100 个 PDF 的批处理过程中,有几个最终可能会迷路。有没有更好的办法?
  • 进度报告。拥有一个典型的纺车可能会变得乏味,我知道用户已经要求更详细的进度更新。对此有何建议?我知道通过上述许多小请求的方法,您可以轻松获得 AJAX 报告:为客户 1 构建 PDF...完成...通过电子邮件将 PDF 发送给客户 1...完成...为客户 2 构建 PDF...等等。
  • 数据库酸度和错误处理。发票是一个很大的问题,而且显然对所涉及的金额很敏感……任何关于交易应用程序逻辑、处理 PDF 生成错误/电子邮件错误以回滚发票等的提示都会很棒。

我会留下这个建议。我们将不胜感激地收到您可以节省的任何提示、建议或意见。

非常感谢。

4

2 回答 2

1

我永远不会建议从浏览器运行这样的工作。这是最适合作为控制台脚本运行的东西。现在,如果需要,您可以从浏览器中启动控制台脚本。

作为控制台作业,您不必担心进程被浏览器或从浏览器到服务器的连接中断。

我可能会首先对发票进行所有数据处理,并确保该过程是原子的。然后我会通过并生成PDF。从技术上讲,您应该能够随时从发票数据中重新生成 pdf。

于 2011-06-14T22:33:05.897 回答
0

现在刚刚完成,并认为我会发布我用来供其他人查看的解决方案。

  1. 根据 datasage 的建议,我首先专注于编写一个可靠的程序来完成数据库处理(使用 MySQL 事务)。

  2. 然后,我编写了处理单个发票的功能(例如,使用 mPDF 构建一个 PDF,通过电子邮件发送一个 PDF)到诸如/invoicing/pdf/123/invoicing/send/123

  3. 对于批处理的客户端程序,首先我编写了一个服务器端侦听器,它将返回需要发送的发票编号的 JSON 对象,以及要发送的相关客户名称和 URI:

     {"invoice_number":1,"customer":"Acme Inc.","uri":"/invoicing/send/1"},
     {"invoice_number":2,"customer":"Another Company","uri":"/invoicing/send/2"},
     {"invoice_number":3,"customer":"Yet Another.","uri":"/invoicing/send/3"},
    
  4. 你可以看到我要去哪里。最后,我编写了客户端 Javascript 来遍历 JSON 并发出请求。然而,我发现的问题是通过使用$.ajax或任何其他本机 jQuery 调用,请求将立即全部触发,并且 Chrome 将服务器连接限制为六个,因此只会发送六张发票。此外,切换$.ajax到使用会async:false导致浏览器冻结,直到所有请求都成功。所以我偶然发现了这个插件:http ://plugins.jquery.com/project/ajaxq它将“排队”AJAX 调用,并提供我需要的效果。

  5. 最后,我的客户端代码看起来有点像这样:

        $(batch).each(function(key,value){
    
            // TODO: make this better
            // For now, uses a plugin which enables us to carry out sequential/synchronous AJAX calls to the server
            $.ajaxq("batch_email", {
                url: value.uri,
                format: 'json',
                success: function(response) { 
                    completed++;
                    $('#progress').val(completed);
    
                    if (response.result == "error") {
                        $('#batch_status').append('<p class="notification error">Failed: '+value.customer_name+'</p>');
                    }
    
                    if (completed != num) {
                        $('#text').html('<img src="'+base_url+'static/img/spinner.gif" style="vertical-align:middle;margin-right:10px;" />'+batch[key+1].customer_name+'...');
                    } else {
                        $('#text').html('Finished');
                        $('#progress').after('<div class="tc"><a href="'+base_url+'customer_invoicing" class="blue button">Return to invoicing</a></a>');
                    }
                }
            });
    
        });
    

在部署之前仍然需要进行一些整理,但它确实有效。如您所见,我使用了 HTML5 进度条来显示程序运行的进度。

希望这可以帮助任何可能在未来几周/几个月内偶然发现这篇文章的人!

最良好的祝愿

于 2011-08-05T00:33:58.167 回答