Deep dive: Account, Stock, Sale, Purchase — +800 LOC business logic

Account:
- Multi-currency: company_currency_id, amount_total_signed
- Lock dates on res.company (period, fiscal year, tax) + enforcement in action_post
- Recurring entries: account.move.recurring with action_generate (copy+advance)
- Tax groups: amount_type='group' computes child taxes with include_base_amount
- ComputeTaxes batch function, findTaxAccount helper

Stock:
- Lot/Serial tracking: enhanced stock.lot with expiration dates + qty compute
- Routes: stock.route model with product/category/warehouse selectable flags
- Rules: stock.rule model with pull/push/buy/manufacture actions + procure methods
- Returns: action_return on picking (swap locations, copy moves)
- Product tracking extension (none/lot/serial) + route_ids M2M

Sale:
- Pricelist: get_product_price with fixed/percentage/formula computation
- Margin: purchase_price, margin, margin_percent on line + order totals
- Down payments: action_create_down_payment (deposit invoice at X%)

Purchase:
- 3-way matching: action_create_bill now updates qty_invoiced on PO lines
- Purchase agreements: purchase.requisition + line with state machine

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc
2026-04-03 19:05:39 +02:00
parent d9171191af
commit b8fa4719ad
14 changed files with 802 additions and 17 deletions

View File

@@ -199,7 +199,7 @@ func initPurchaseOrder() {
// Read PO lines to generate invoice lines
rows, err := env.Tx().Query(env.Ctx(),
`SELECT COALESCE(name,''), COALESCE(product_qty,1), COALESCE(price_unit,0), COALESCE(discount,0)
`SELECT id, COALESCE(name,''), COALESCE(product_qty,1), COALESCE(price_unit,0), COALESCE(discount,0)
FROM purchase_order_line
WHERE order_id = $1 ORDER BY sequence, id`, poID)
if err != nil {
@@ -207,6 +207,7 @@ func initPurchaseOrder() {
}
type poLine struct {
id int64
name string
qty float64
price float64
@@ -215,7 +216,7 @@ func initPurchaseOrder() {
var lines []poLine
for rows.Next() {
var l poLine
if err := rows.Scan(&l.name, &l.qty, &l.price, &l.discount); err != nil {
if err := rows.Scan(&l.id, &l.name, &l.qty, &l.price, &l.discount); err != nil {
rows.Close()
return nil, err
}
@@ -258,6 +259,13 @@ func initPurchaseOrder() {
companyID, journalID)
}
// Update qty_invoiced on PO lines
for _, l := range lines {
env.Tx().Exec(env.Ctx(),
`UPDATE purchase_order_line SET qty_invoiced = COALESCE(qty_invoiced, 0) + $1 WHERE id = $2`,
l.qty, l.id)
}
billIDs = append(billIDs, billID)
// Update PO invoice_status