自由职业者最烦的不是写代码,是开票。客户催你交付,你催客户付款,中间还得自己算税。这套流程我跑了三年,直到上个月用Python写了个脚本,现在三分钟干完原来三小时的活。
核心就三件事:自动生成PDF发票、自动发催款邮件、自动追踪支出。下面是我实际在跑的代码,复制粘贴就能用。
![]()
发票生成用的是ReportLab库。这个库的好处是不依赖Office,服务器上也能跑。我的函数接收四个参数:客户名、邮箱、服务列表、发票编号。编号不传就按时间戳自动生成,格式INV-YYYYMMDDHHMM,保证唯一性。
![]()
代码里有个细节:到期日自动算30天后。这个天数你可以改,但建议写死别做成参数——我试过做成配置,结果某次手滑填了300,客户直接当诈骗邮件忽略了。PDF布局分三块:抬头信息、客户信息、明细表格。金额用${:,.2f}格式化,千分位逗号和小数点两位,看起来专业。
实际调用示例是给Acme Corp开的票:40小时Web开发按75美元/小时算,加域名托管费150,总价3150。运行完当前目录下多出invoice_INV-202501141530.pdf,直接邮件附件发给客户。
催款比开票更折磨人。我的方案是SQLite存发票状态,每天跑一遍定时任务。数据库表结构很简单:发票号、客户名、邮箱、金额、到期日、是否已付。查询条件两个:paid=0且due_date小于今天。
邮件内容按逾期天数分级。7天内叫"Gentle Reminder",语气轻松;8到30天标题加粗标OVERDUE,正文开始施压。超过30天的我没写,那种得打电话了,自动化不合适。
有个坑要注意:datetime.strptime的日期格式必须和存库时一致。我一开始用%B %d, %Y存,查询时用%Y-%m-%d读,结果全报ValueError。后来统一改成ISO格式存库,显示时才做本地化转换。
![]()
SMTP配置我用的环境变量,没硬编码在脚本里。这样部署到不同服务器不用改代码,换邮箱密码也不用重新发布。建议开专用邮箱跑这个,万一被标垃圾邮件不影响主业务。
支出追踪是第三部分,原文代码截断了,但从上下文能推断结构:应该也是SQLite表,字段大概包括日期、类别、金额、备注。我的做法是拍照收据→OCR识别→Python写入→月末生成报表。OCR用的开源模型,本地跑不花钱,准确率八九成,错的手动改。
这套系统跑了一个月,省下的时间够我接两个小单。最意外的收获是客户付款变快了——专业格式的PDF发票比Excel截图可信度高,自动催款又刚好卡在对方"还没忘但还没付"的窗口期。
如果你也是一人公司,建议从这个脚本开始。不用追求完美,先跑起来再迭代。我的第一版连PDF都没有,直接打印HTML,照样用了半年。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.