Deepen all business modules: methods, validations, workflows

Account:
- action_post: partner validation, line count check, sequence number
  assignment (JOURNAL/YYYY/NNNN format)
- action_register_payment: opens payment wizard from invoice
- remove_move_reconcile: undo reconciliation, reset residuals
- Register Payment button in invoice form (visible when posted+unpaid)

Sale:
- action_cancel: cancels linked draft invoices + SO state
- action_draft: reset cancelled SO to draft
- action_view_invoice: navigate to linked invoices
- Cancel/Reset buttons in form view header

Purchase:
- button_draft: reset cancelled PO to draft
- action_create_bill already existed

Stock:
- action_cancel on picking: cancels moves + picking state

CRM:
- action_set_won_rainbowman: sets Won stage + rainbow effect
- convert_opportunity: lead→opportunity type switch

HR:
- hr.contract model (name, employee, wage, dates, state)

Project:
- action_blocked on task (kanban_state)
- Task stage seed data (New, In Progress, Done, Cancelled)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc
2026-04-03 00:58:01 +02:00
parent 0143ddd655
commit cc1f150732
9 changed files with 258 additions and 0 deletions

View File

@@ -105,6 +105,38 @@ func initCRMLead() {
}
return true, nil
})
// convert_opportunity: alias for convert_to_opportunity
m.RegisterMethod("convert_opportunity", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) {
env := rs.Env()
for _, id := range rs.IDs() {
env.Tx().Exec(env.Ctx(),
`UPDATE crm_lead SET type = 'opportunity' WHERE id = $1`, id)
}
return true, nil
})
// action_set_won_rainbowman: set won stage + rainbow effect
m.RegisterMethod("action_set_won_rainbowman", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) {
env := rs.Env()
// Find Won stage
var wonStageID int64
env.Tx().QueryRow(env.Ctx(),
`SELECT id FROM crm_stage WHERE is_won = true LIMIT 1`).Scan(&wonStageID)
if wonStageID == 0 {
wonStageID = 4 // fallback
}
for _, id := range rs.IDs() {
env.Tx().Exec(env.Ctx(),
`UPDATE crm_lead SET stage_id = $1, probability = 100 WHERE id = $2`, wonStageID, id)
}
return map[string]interface{}{
"effect": map[string]interface{}{
"type": "rainbow_man",
"message": "Congrats, you won this opportunity!",
},
}, nil
})
}
// initCRMStage registers the crm.stage model.