1
+ <?xml version =" 1.0" encoding =" utf-8" ?>
2
+ <odoo >
3
+ <record id =" paperformat_product_bom_report" model =" report.paperformat" >
4
+ <field name =" name" >Custom Paperformat Product BoM</field >
5
+ <field name =" default" eval =" False" />
6
+ <field name =" disable_shrinking" eval =" True" />
7
+ <field name =" format" >A4</field >
8
+ <field name =" page_height" >0</field >
9
+ <field name =" page_width" >0</field >
10
+ <field name =" orientation" >Portrait</field >
11
+ <field name =" margin_top" >10</field >
12
+ <field name =" header_spacing" >20</field >
13
+ <field name =" margin_bottom" >5</field >
14
+ <field name =" margin_left" >0</field >
15
+ <field name =" margin_right" >0</field >
16
+ <field name =" dpi" >96</field >
17
+ </record >
18
+
19
+ <!-- Main template -->
20
+ <template id =" report_product_product_bom_activity" >
21
+ <t t-set =" data_report_landscape" t-value =" True" />
22
+ <t t-call =" web.basic_layout" >
23
+ <t t-foreach =" docs" t-as =" product_product" >
24
+ <div class =" page" >
25
+ <t t-call =" activity_validation.report_product_product_bom" />
26
+ </div >
27
+ <p style =" page-break-before:always;" > </p >
28
+ </t >
29
+ </t >
30
+ </template >
31
+
32
+ <template id =" report_product_product_bom" >
33
+ <div class =" o_mrp_bom_report_page container py-lg-5 px-0 bg-view" >
34
+ <div class =" px-3 mb-5" >
35
+ <h1 >BoM Overview</h1 >
36
+ <h2 t-if =" product_product['display_name']" >Reference: <t t-esc =" product_product['display_name']" /></h2 >
37
+ </div >
38
+ <t t-set =" currency" t-value =" product_product.currency_id" />
39
+ <div t-if =" product_product.bom_ids" >
40
+ <table class =" table table-borderless" style =" table-layout: fixed; width: 100%;" >
41
+ <thead >
42
+ <tr >
43
+ <th name =" th_mrp_bom_h" style =" width: 27%;" >Product</th >
44
+ <th class =" text-end" style =" width: 7.5%;" >Quantity</th >
45
+ <th class =" text-end" style =" width: 9%;" >Ready to Produce</th >
46
+ <th class =" text-end" style =" width: 10%;" >Free to Use / On Hand</th >
47
+ <th style =" width: 9.5%;" >Availability</th >
48
+ <th class =" text-end" style =" width: 5%;" >Lead Time</th >
49
+ <th style =" width: 16%;" >Route</th >
50
+ <th class =" text-end" style =" width: 7%;" >BoM Cost</th >
51
+ <th class =" text-end" style =" width: 9%;" >Product Cost</th >
52
+ </tr >
53
+ </thead >
54
+ <tbody >
55
+ <t t-foreach =" product_product.bom_ids" t-as =" data" >
56
+ <tr >
57
+ <td name =" td_mrp_bom" t-out =" data.display_name" />
58
+ <td class =" text-end" t-out =" data.product_qty" t-options =' {"widget": "float", "decimal_precision": "Product Unit of Measure"}' />
59
+ <td ></td >
60
+ <td class =" text-end" >
61
+ <t t-out =" product_product.product_variant_id.free_qty" t-options =' {"widget": "float", "decimal_precision": "Product Unit of Measure"}' /> /
62
+ <t t-out =" product_product.product_variant_id.qty_available" t-options =' {"widget": "float", "decimal_precision": "Product Unit of Measure"}' />
63
+ </td >
64
+ <t t-set =" now" t-value =" datetime.datetime.now()" />
65
+ <t t-set =" future_date" t-value =" now + datetime.timedelta(days=data.produce_delay)" />
66
+ <td ><t t-out =" future_date.strftime('%m/%d/%Y')" /></td >
67
+ <td class =" text-end" >
68
+ <span >
69
+ <t t-out =" data.produce_delay" t-options =" {'widget': 'float', 'precision': 0}" /> Days
70
+ </span >
71
+ </td >
72
+ <td >
73
+ <span >Manufacture: <t t-out =" data.display_name" /></span >
74
+ </td >
75
+ <td class =" text-end" t-out =" product_product.standard_price" t-options =' {"widget": "monetary", "display_currency": currency}' ></td >
76
+ <td class =" text-end" t-out =" product_product.standard_price" t-options =' {"widget": "monetary", "display_currency": currency}' ></td >
77
+ </tr >
78
+ <t t-foreach =" data.bom_line_ids" t-as =" line" >
79
+ <tr >
80
+ <td style =" padding-left: 2rem;" name =" td_mrp_bom" t-out =" line.product_id.display_name" />
81
+ <td class =" text-end" t-out =" line.product_qty" t-options =' {"widget": "float", "decimal_precision": "Product Unit of Measure"}' />
82
+ <td ></td >
83
+ <td class =" text-end" >
84
+ <t t-out =" line.product_id.free_qty" t-options =' {"widget": "float", "decimal_precision": "Product Unit of Measure"}' />
85
+ /
86
+ <t t-out =" line.product_id.qty_available" t-options =' {"widget": "float", "decimal_precision": "Product Unit of Measure"}' />
87
+ </td >
88
+ <t t-if =" line.product_id.seller_ids" >
89
+ <t t-set =" today_now" t-value =" datetime.datetime.now()" />
90
+ <t t-set =" next_date" t-value =" today_now + datetime.timedelta(days=line.product_id.seller_ids[0].delay)" />
91
+ <td ><t t-out =" next_date.strftime('%m/%d/%Y')" /></td >
92
+ <td class =" text-end" >
93
+ <span >
94
+ <t t-out =" line.product_id.seller_ids[0].delay" t-options =" {'widget': 'float', 'precision': 0}" /> Days
95
+ </span >
96
+ </td >
97
+ <td >
98
+ <span >Buy: <t t-out =" line.product_id.seller_ids[0].partner_id.name" /></span >
99
+ </td >
100
+ </t >
101
+ <t t-else =" " >
102
+ <td ></td >
103
+ <td ></td >
104
+ <td ></td >
105
+ </t >
106
+ <td class =" text-end" t-out =" line.product_id.standard_price" t-options =' {"widget": "monetary", "display_currency": currency}' ></td >
107
+ <td class =" text-end" t-out =" line.product_id.standard_price" t-options =' {"widget": "monetary", "display_currency": currency}' ></td >
108
+ </tr >
109
+ <t t-foreach =" line.product_id.activity_ids" t-as =" activity" >
110
+ <t t-set =" change_request_id" t-value =" activity.env.ref('activity_validation.mail_activity_change_request')" />
111
+ <t t-set =" plm_activity_id" t-value =" activity.env.ref('plm.mail_activity_plm_activity')" />
112
+ <t t-if =" activity.activity_type_id in [change_request_id, plm_activity_id]" >
113
+ <tr >
114
+ <td t-att-class =" 'text-danger' if activity.plm_state == 'exception' else 'text-success' if activity.plm_state == 'done' else 'text-warning' if activity.plm_state == 'draft' else 'text-muted' if activity.plm_state == 'cancel' else 'text-info' if activity.plm_state == 'eco' else ''"
115
+ style =" padding-left: 4rem;" name =" td_activity_name" >
116
+ <div style =" width: 33rem;" >
117
+ <t t-out =" activity.note" />
118
+ </div >
119
+ </td >
120
+ <td ></td >
121
+ <td ></td >
122
+ <td ></td >
123
+ <td t-att-class =" 'text-danger' if activity.plm_state == 'exception' else 'text-success' if activity.plm_state == 'done' else 'text-warning' if activity.plm_state == 'draft' else 'text-muted' if activity.plm_state == 'cancel' else 'text-info' if activity.plm_state == 'eco' else ''"
124
+ name =" td_activity_state" >
125
+ <t t-out =" {
126
+ 'draft': 'Draft',
127
+ 'in_progress': 'In Progress',
128
+ 'eco': 'Change Order',
129
+ 'done': 'Done',
130
+ 'cancel': 'Cancel',
131
+ 'exception': 'Exception'
132
+ }.get(activity.plm_state, 'Unknown')" />
133
+ </td >
134
+ <td ></td >
135
+ <td ></td >
136
+ <td ></td >
137
+ <td ></td >
138
+ </tr >
139
+ </t >
140
+ </t >
141
+ </t >
142
+ </t >
143
+ </tbody >
144
+ </table >
145
+ </div >
146
+ </div >
147
+ </template >
148
+
149
+ <record id =" bom_activity_product_procduct_report_action" model =" ir.actions.report" >
150
+ <field name =" name" >BoM Activity Overview</field >
151
+ <field name =" model" >product.product</field >
152
+ <field name =" report_type" >qweb-pdf</field >
153
+ <field name =" report_name" >activity_validation.report_product_product_bom_activity</field >
154
+ <field name =" report_file" >activity_validation.report_product_product_bom_activity</field >
155
+ <field name =" print_report_name" >'BOM_Activity_Hierarchy_' + object.name</field >
156
+ <field name =" paperformat_id" ref =" paperformat_product_bom_report" />
157
+ <field name =" binding_model_id" ref =" product.model_product_product" />
158
+ <field name =" binding_type" >report</field >
159
+ </record >
160
+ </odoo >
0 commit comments