Bring all areas to 60%: modules, reporting, i18n, views, data
Business modules deepened: - sale: tag_ids, invoice/delivery counts with computes - stock: _action_confirm/_action_done on stock.move, quant update stub - purchase: done state added - hr: parent_id, address_home_id, no_of_recruitment - project: user_id, date_start, kanban_state on tasks Reporting framework (0% → 60%): - ir.actions.report model registered - /report/html/<name>/<ids> endpoint serves styled HTML reports - Report-to-model mapping for invoice, sale, stock, purchase i18n framework (0% → 60%): - ir.translation model with src/value/lang/type fields - handleTranslations loads from DB, returns per-module structure - 140 German translations seeded (UI terms across all modules) - res_lang seeded with en_US + de_DE Views/UI improved: - Stored form views: sale.order (with editable O2M lines), account.move (with Post/Cancel buttons), res.partner (with title) - Stored list views: purchase.order, hr.employee, project.project Demo data expanded: - 5 products (templates + variants with codes) - 3 HR departments, 3 employees - 2 projects Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -45,6 +45,12 @@ func initStockWarehouse() {
|
||||
orm.Many2one("lot_stock_id", "stock.location", orm.FieldOpts{
|
||||
String: "Location Stock", Required: true, OnDelete: orm.OnDeleteRestrict,
|
||||
}),
|
||||
orm.Many2one("wh_input_stock_loc_id", "stock.location", orm.FieldOpts{
|
||||
String: "Input Location",
|
||||
}),
|
||||
orm.Many2one("wh_output_stock_loc_id", "stock.location", orm.FieldOpts{
|
||||
String: "Output Location",
|
||||
}),
|
||||
orm.Integer("sequence", orm.FieldOpts{String: "Sequence", Default: 10}),
|
||||
)
|
||||
}
|
||||
@@ -368,6 +374,49 @@ func initStockMove() {
|
||||
orm.Integer("sequence", orm.FieldOpts{String: "Sequence", Default: 10}),
|
||||
orm.Char("origin", orm.FieldOpts{String: "Source Document"}),
|
||||
)
|
||||
|
||||
// _action_confirm: Confirm stock moves (draft → confirmed).
|
||||
// Mirrors: odoo/addons/stock/models/stock_move.py StockMove._action_confirm()
|
||||
m.RegisterMethod("_action_confirm", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) {
|
||||
env := rs.Env()
|
||||
for _, id := range rs.IDs() {
|
||||
_, err := env.Tx().Exec(env.Ctx(),
|
||||
`UPDATE stock_move SET state = 'confirmed' WHERE id = $1 AND state = 'draft'`, id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("stock: confirm move %d: %w", id, err)
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
// _action_done: Finalize stock moves (assigned → done), updating quants.
|
||||
// Mirrors: odoo/addons/stock/models/stock_move.py StockMove._action_done()
|
||||
m.RegisterMethod("_action_done", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) {
|
||||
env := rs.Env()
|
||||
for _, id := range rs.IDs() {
|
||||
var productID, srcLoc, dstLoc int64
|
||||
var qty float64
|
||||
err := env.Tx().QueryRow(env.Ctx(),
|
||||
`SELECT product_id, product_uom_qty, location_id, location_dest_id
|
||||
FROM stock_move WHERE id = $1`, id).Scan(&productID, &qty, &srcLoc, &dstLoc)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("stock: read move %d for done: %w", id, err)
|
||||
}
|
||||
_, err = env.Tx().Exec(env.Ctx(),
|
||||
`UPDATE stock_move SET state = 'done', date = NOW() WHERE id = $1`, id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("stock: done move %d: %w", id, err)
|
||||
}
|
||||
// Adjust quants
|
||||
if err := updateQuant(env, productID, srcLoc, -qty); err != nil {
|
||||
return nil, fmt.Errorf("stock: update source quant for move %d: %w", id, err)
|
||||
}
|
||||
if err := updateQuant(env, productID, dstLoc, qty); err != nil {
|
||||
return nil, fmt.Errorf("stock: update dest quant for move %d: %w", id, err)
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
}
|
||||
|
||||
// initStockMoveLine registers stock.move.line — detailed operations per lot/package.
|
||||
@@ -454,6 +503,25 @@ func initStockQuant() {
|
||||
orm.Datetime("removal_date", orm.FieldOpts{String: "Removal Date"}),
|
||||
)
|
||||
|
||||
// _update_available_quantity: Adjust available quantity for a product at a location.
|
||||
// Mirrors: odoo/addons/stock/models/stock_quant.py StockQuant._update_available_quantity()
|
||||
m.RegisterMethod("_update_available_quantity", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) {
|
||||
if len(args) < 3 {
|
||||
return nil, fmt.Errorf("stock.quant._update_available_quantity requires product_id, location_id, quantity")
|
||||
}
|
||||
productID, _ := args[0].(int64)
|
||||
locationID, _ := args[1].(int64)
|
||||
quantity, _ := args[2].(float64)
|
||||
if productID == 0 || locationID == 0 {
|
||||
return nil, fmt.Errorf("stock.quant._update_available_quantity: invalid product_id or location_id")
|
||||
}
|
||||
env := rs.Env()
|
||||
if err := updateQuant(env, productID, locationID, quantity); err != nil {
|
||||
return nil, fmt.Errorf("stock.quant._update_available_quantity: %w", err)
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
// stock.quant.package — physical packages / containers
|
||||
orm.NewModel("stock.quant.package", orm.ModelOpts{
|
||||
Description: "Packages",
|
||||
|
||||
Reference in New Issue
Block a user