Merge lp:~dorian-kemps/unifield-server/US-3372 into lp:unifield-server

Proposed by jftempo
Status: Merged
Merged at revision: 4501
Proposed branch: lp:~dorian-kemps/unifield-server/US-3372
Merge into: lp:unifield-server
Diff against target: 536 lines (+228/-200)
2 files modified
bin/addons/sale/report/sale_loan_stock_moves_report.py (+127/-125)
bin/addons/sale/report/sale_loan_stock_moves_report_xls.mako (+101/-75)
To merge this branch: bzr merge lp:~dorian-kemps/unifield-server/US-3372
Reviewer Review Type Date Requested Status
UniField Reviewer Team Pending
Review via email: mp+330423@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bin/addons/sale/report/sale_loan_stock_moves_report.py'
--- bin/addons/sale/report/sale_loan_stock_moves_report.py 2017-08-25 16:02:26 +0000
+++ bin/addons/sale/report/sale_loan_stock_moves_report.py 2017-09-13 12:13:20 +0000
@@ -31,24 +31,26 @@
31 super(sale_loan_stock_moves_report_parser, self).__init__(cr, uid, name, context=context)31 super(sale_loan_stock_moves_report_parser, self).__init__(cr, uid, name, context=context)
32 self.cr = cr32 self.cr = cr
33 self.uid = uid33 self.uid = uid
34 self.user_company = self._get_user_company()
34 self.localcontext.update({35 self.localcontext.update({
35 'time': time,36 'time': time,
36 'getMoves': self._get_moves,37 'getMoves': self._get_moves,
37 'isQtyOut': self._is_qty_out,38 'isQtyOut': self._is_qty_out,
38 'getQty': self._get_qty,39 'getQty': self._get_qty,
39 'getInstance': self._get_instance,40 'getUserCompany': self._get_user_company,
41 'getFirstSplitOnUnderscore': self._get_first_split_on_underscore,
42 'computeCurrency': self._compute_currency,
40 })43 })
4144
42 def _is_qty_out(self, move):45 def _is_qty_out(self, move):
43 '''46 '''
44 Check if the move is an in or an out47 Check if the move is an in or an out
45 '''48 '''
46 out = False
4749
48 if (move.location_id.usage == 'internal') and (move.location_dest_id and move.location_dest_id.usage in ('customer', 'supplier')):50 if (move.location_id.usage == 'internal') and (move.location_dest_id and move.location_dest_id.usage in ('customer', 'supplier')):
49 out = True51 return True
5052
51 return out53 return False
5254
53 def _get_qty(self, move):55 def _get_qty(self, move):
54 '''56 '''
@@ -62,141 +64,141 @@
6264
63 return qty65 return qty
6466
65 def _get_move_obj(self, cr, uid, obj_obj, move):
66 '''
67 Return the move's order type object
68 '''
69 obj_id = False
70 obj = False
71 acronym_type = False
72
73 for split_origin in move.origin.split(":"):
74 if obj_obj == self.pool.get('sale.order'):
75 acronym_type = 'FO'
76 elif obj_obj == self.pool.get('purchase.order'):
77 acronym_type = 'PO'
78
79 if acronym_type and acronym_type in split_origin:
80 obj_name = str(split_origin.split("/")[-1].split("-")[0])
81 obj_id = obj_obj.search(cr, uid, [('name', 'like', obj_name + '-')])
82 if not obj_id:
83 obj_id = obj_obj.search(cr, uid, [('name', 'like', obj_name)])
84
85 if obj_id:
86 obj = obj_obj.browse(cr, uid, obj_id[0])
87 break
88
89 return obj
90
91 def _get_moves(self, report):67 def _get_moves(self, report):
92 '''68 '''
93 Return the moves for the report and set their qty balance69 Return the moves for the report and set their qty balance
94 '''70 '''
95 so_obj = self.pool.get('sale.order')71 so_obj = self.pool.get('sale.order')
96 po_obj = self.pool.get('purchase.order')72 po_obj = self.pool.get('purchase.order')
97 result = []
98 sm_list = []73 sm_list = []
74 # TODO: we must search on counterpart if filter is used on wizard
99 for move in report.sm_ids:75 for move in report.sm_ids:
100 sm_list.append(self.pool.get('stock.move').browse(self.cr, self.uid, move))76 sm_list.append(self.pool.get('stock.move').browse(self.cr, self.uid, move))
10177
102 sm_list = sorted(sm_list, key=lambda sm: (sm['product_id']['default_code'], sm['origin'].split(":")[-1], sm['create_date']))78 sm_list = sorted(sm_list, key=lambda sm: sm['create_date'])
103 balance = 079 move_by_fo_po_prod = {}
104 # dict used to check if the loan flow is done80 keys_order = []
105 dict_check_done = {}81
106 for index, move in enumerate(sm_list, start=0):82 get_so_from_po_id = {}
107 move.balance = balance83 get_po_from_so_id = {}
84
85 for move in sm_list:
108 if self._is_qty_out(move):86 if self._is_qty_out(move):
109 balance -= self._get_qty(move)87 qty = -1 * self._get_qty(move)
110 else:88 else:
111 balance += self._get_qty(move)89 qty = self._get_qty(move)
11290
113 # check if the flow exists in the dict91 dom = []
114 move.status = 'Open'92 status = 'Open'
115 move_ref = str(move.origin.split(":")[-1].split("/")[-1].split("-")[0])93 if move.purchase_line_id:
116 if not dict_check_done.get(move_ref, []):94 po_found = move.purchase_line_id.order_id
117 if 'FO' in move.origin and 'PO' in move.origin:95 if po_found.id not in get_so_from_po_id:
118 so_state = self._get_move_obj(self.cr, self.uid, so_obj, move).state96 if po_found.loan_id:
119 po_state = self._get_move_obj(self.cr, self.uid, po_obj, move).state97 ids = [po_found.loan_id.id]
120 if so_state == 'done' and po_state == 'done':98 elif po_found.origin[-2:] in ['-1', '-2', '-3']:
121 dict_check_done[move_ref] = 'Closed'99 ids = so_obj.search(self.cr, self.uid, [('name', '=', po_found.origin)])
122 else:100 if not ids:
123 dict_check_done[move_ref] = 'Open'101 ids = so_obj.search(self.cr, self.uid, [('name', '=', po_found.origin[0:-2])])
124 elif 'FO' in move.origin and not 'PO' in move.origin:102 else:
125 so_found = self._get_move_obj(self.cr, self.uid, so_obj, move)103 ids = so_obj.search(self.cr, self.uid, [('name', '=', po_found.origin)])
126 so_state = so_found.state104 if not ids:
127 po_ids = po_obj.search(self.cr, self.uid, [('origin', '=', so_found.name)])105 dom = ['%s-%s' % (po_found.origin, i) for i in [1, 2, 3]]
128 if len(po_ids) > 0:106 ids = so_obj.search(self.cr, self.uid, [('name', 'in', dom)])
129 po_state = po_obj.browse(self.cr, self.uid, po_ids[0]).state107 if ids:
130 if so_state == 'done' and po_state == 'done':108 so = so_obj.browse(self.cr, self.uid, ids[0])
131 dict_check_done[move_ref] = 'Closed'109 if so.split_type_sale_order:
132 else:110 ids = so_obj.search(self.cr, self.uid, [('name', '=', '%s-2' % so.name)])
133 dict_check_done[move_ref] = 'Open'111 if ids:
134 else:112 so = so_obj.browse(self.cr, self.uid, ids[0])
135 dict_check_done[move_ref] = 'Open'113 get_so_from_po_id[po_found.id] = so
136 elif not 'FO' in move.origin and 'PO' in move.origin:114
137 po_found = self._get_move_obj(self.cr, self.uid, po_obj, move)115 so_found = get_so_from_po_id.get(po_found.id)
138 po_state = po_found.state116 if so_found and so_found.state == po_found.state == 'done':
139 so_ids = so_obj.search(self.cr, self.uid, [('name', '=', po_found.origin)])117 status = 'Closed'
140 if len(so_ids) > 0:118 elif move.sale_line_id:
141 so_state = po_obj.browse(self.cr, self.uid, so_ids[0]).state119 so_found = move.sale_line_id.order_id
142 if so_state == 'done' and po_state == 'done':120 if so_found.id not in get_po_from_so_id:
143 dict_check_done[move_ref] = 'Closed'121 if so_found.loan_id:
144 else:122 ids = [so_found.loan_id.id]
145 dict_check_done[move_ref] = 'Open'123 elif so_found.name[-2:] in ['-1', '-2', '-3']:
146 else:124 ids = po_obj.search(self.cr, self.uid, [('origin', '=', so_found.name)])
147 dict_check_done[move_ref] = 'Open'125 if not ids:
148 # set the state according to the flow status126 ids = po_obj.search(self.cr, self.uid, [('origin', '=', so_found.name[0:-2])])
149 setattr(move, 'status', dict_check_done[move_ref])127 else:
150128 ids = po_obj.search(self.cr, self.uid, [('origin', '=', so_found.name)])
151 # if the move is the last in the list129 if ids:
152 if move is sm_list[-1]:130 po_found = po_obj.browse(self.cr, self.uid, ids[0])
153 setattr(move, 'balance', balance)131 if po_found.state == 'split':
154 # remove closed flows132 ids = po_obj.search(self.cr, self.uid, [('name', '=', '%s-2' % po_found.name)])
155 if report.remove_completed:133 po_found = po_obj.browse(self.cr, self.uid, ids[0])
156 if move.status == 'Open':134 get_po_from_so_id[so_found.id] = po_found
157 result.append(move)135
158 else:136 po_found = get_po_from_so_id.get(so_found.id)
159 result.append(move)137 if po_found and so_found.state == po_found.state == 'done':
160 balance = 0138 status = 'Closed'
161 else:139
162 # if the move's origin is different than the next one140 if status != 'Closed' or not report.remove_completed:
163 if move.origin.split(":")[-1] not in sm_list[index+1].origin.split(":")[-1] and \141 setattr(move, 'status', status)
164 sm_list[index + 1].origin.split(":")[-1] not in move.origin.split(":")[-1]:142 setattr(move, 'balance', 0)
165 setattr(move, 'balance', balance)143
166 # remove closed flows144 key = (
167 if report.remove_completed:145 so_found and so_found.id or 'NF%s' % po_found.id,
168 if move.status == 'Open':146 po_found and po_found.id or 'NF%s' % so_found.id,
169 result.append(move)147 move.product_id.id
170 else:148 )
171 result.append(move)149 if key not in move_by_fo_po_prod:
172 balance = 0150 keys_order.append(key)
173 else:151 move_by_fo_po_prod[key] = {'balance': 0, 'moves': []}
174 # if the move's product is different than the next one152 move_by_fo_po_prod[key]['balance'] += qty
175 if move.product_id.id != sm_list[index+1].product_id.id:153 move_by_fo_po_prod[key]['moves'].append(move)
176 setattr(move, 'balance', balance)154
177 # remove closed flows155 result = []
178 if report.remove_completed:156 for key in keys_order:
179 if move.status == 'Open':157 move_by_fo_po_prod[key]['moves'][-1].balance = move_by_fo_po_prod[key]['balance']
180 result.append(move)158 result.append(move_by_fo_po_prod[key]['moves'])
181 else:
182 result.append(move)
183 balance = 0
184 else:
185 setattr(move, 'balance', 0)
186 # remove closed flows
187 if report.remove_completed:
188 if move.status == 'Open':
189 result.append(move)
190 else:
191 result.append(move)
192159
193 return result160 return result
194161
195 def _get_instance(self):162 def _get_user_company(self):
196 '''163 '''
197 Return user's current instance164 Return user's current company
198 '''165 '''
199 return self.pool.get('res.users').browse(self.cr, self.uid, self.uid).company_id.instance_id.name166 return self.pool.get('res.users').browse(self.cr, self.uid, self.uid).company_id
167
168 def _get_first_split_on_underscore(self, name):
169 '''
170 Return the first data from a table with the string split to '_'
171 '''
172 res = name
173 if res:
174 res = name.rsplit('_', 1)[0]
175
176 return res
177
178 def _compute_currency(self, move):
179 '''
180 Compute an amount of a given currency to the instance's currency
181 '''
182 currency_obj = self.pool.get('res.currency')
183
184 if not move.price_currency_id:
185 if move.price_unit is None:
186 return round(move.product_id.standard_price, 2)
187 if move.type == 'in':
188 from_currency_id = move.partner_id.property_product_pricelist_purchase.currency_id.id
189 else:
190 from_currency_id = move.partner_id.property_product_pricelist.currency_id.id
191 else:
192 from_currency_id = move.price_currency_id.id
193
194 context = {'date': move.date}
195 to_currency_id = self.user_company['currency_id'].id
196
197 if from_currency_id == to_currency_id:
198 return round(move.price_unit, 2)
199
200 return round(currency_obj.compute(self.cr, self.uid, from_currency_id, to_currency_id, move.price_unit, round=False, context=context), 2)
201
200202
201class sale_loan_stock_moves_report_xls(SpreadsheetReport):203class sale_loan_stock_moves_report_xls(SpreadsheetReport):
202 def __init__(self, name, table, rml=False, parser=report_sxw.rml_parse,204 def __init__(self, name, table, rml=False, parser=report_sxw.rml_parse,
203205
=== modified file 'bin/addons/sale/report/sale_loan_stock_moves_report_xls.mako'
--- bin/addons/sale/report/sale_loan_stock_moves_report_xls.mako 2017-08-16 08:32:04 +0000
+++ bin/addons/sale/report/sale_loan_stock_moves_report_xls.mako 2017-09-13 12:13:20 +0000
@@ -39,25 +39,48 @@
39 </Style>39 </Style>
4040
41 <!-- Lines -->41 <!-- Lines -->
42 <Style ss:ID="line_left">42 <Style ss:ID="line_left0">
43 <Alignment ss:Horizontal="Left" ss:Vertical="Bottom"/>43 <Alignment ss:Horizontal="Left" ss:Vertical="Bottom"/>
44 <Borders>44 <Borders>
45 <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>45 <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
46 <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>46 <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
47 <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>47 <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
48 <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>48 <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
49 </Borders>49 </Borders>
50 <Font ss:Size="10"/>50 <Font ss:Size="10"/>
51 </Style>51 </Style>
52 <Style ss:ID="line_right">52 <Style ss:ID="line_right0">
53 <Alignment ss:Horizontal="Right" ss:Vertical="Bottom"/>53 <Alignment ss:Horizontal="Right" ss:Vertical="Bottom"/>
54 <Borders>54 <Borders>
55 <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>55 <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
56 <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>56 <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
57 <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>57 <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
58 <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>58 <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
59 </Borders>59 </Borders>
60 <Font ss:Size="10"/>60 <Font ss:Size="10"/>
61 <NumberFormat ss:Format="#,##0.00"/>
62 </Style>
63 <Style ss:ID="line_left1">
64 <Alignment ss:Horizontal="Left" ss:Vertical="Bottom"/>
65 <Borders>
66 <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
67 <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
68 <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
69 <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
70 </Borders>
71 <Font ss:Size="10"/>
72 <Interior ss:Color="#dddddd" ss:Pattern="Solid"/>
73 </Style>
74 <Style ss:ID="line_right1">
75 <Alignment ss:Horizontal="Right" ss:Vertical="Bottom"/>
76 <Borders>
77 <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1"/>
78 <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1"/>
79 <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1"/>
80 <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
81 </Borders>
82 <Font ss:Size="10"/>
83 <Interior ss:Color="#dddddd" ss:Pattern="Solid"/>
61 <NumberFormat ss:Format="#,##0.00"/>84 <NumberFormat ss:Format="#,##0.00"/>
62 </Style>85 </Style>
63 <Style ss:ID="line_center">86 <Style ss:ID="line_center">
@@ -71,15 +94,26 @@
71 <Font ss:Size="10"/>94 <Font ss:Size="10"/>
72 <NumberFormat ss:Format="#,##0.00"/>95 <NumberFormat ss:Format="#,##0.00"/>
73 </Style>96 </Style>
74 <Style ss:ID="sShortDate">97 <Style ss:ID="sShortDate0">
75 <NumberFormat ss:Format="Short Date"/>98 <NumberFormat ss:Format="Short Date"/>
76 <Alignment ss:Vertical="Center" ss:WrapText="1"/>99 <Alignment ss:Vertical="Center" ss:WrapText="1"/>
77 <Borders>100 <Borders>
78 <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1" />101 <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1" />
79 <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1" />102 <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1" />
80 <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1" />103 <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1" />
81 <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1" />104 <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1" />
82 </Borders>105 </Borders>
106 </Style>
107 <Style ss:ID="sShortDate1">
108 <NumberFormat ss:Format="Short Date"/>
109 <Alignment ss:Vertical="Center" ss:WrapText="1"/>
110 <Borders>
111 <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1" />
112 <Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1" />
113 <Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1" />
114 <Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1" />
115 </Borders>
116 <Interior ss:Color="#dddddd" ss:Pattern="Solid"/>
83 </Style>117 </Style>
84 </Styles>118 </Styles>
85119
@@ -87,39 +121,39 @@
87 <ss:Worksheet ss:Name="Loan Report">121 <ss:Worksheet ss:Name="Loan Report">
88 <Table x:FullColumns="1" x:FullRows="1">122 <Table x:FullColumns="1" x:FullRows="1">
89 ## Product Code123 ## Product Code
90 <Column ss:AutoFitWidth="1" ss:Width="92.5" />124 <Column ss:AutoFitWidth="1" ss:Width="102.5" />
91 ## Product Description125 ## Product Description
92 <Column ss:AutoFitWidth="1" ss:Width="271.5" />126 <Column ss:AutoFitWidth="1" ss:Width="301.5" />
93 ## Order Type127 ## Order Type
94 <Column ss:AutoFitWidth="1" ss:Width="54.0" />128 <Column ss:AutoFitWidth="1" ss:Width="54.0" />
95 ## Movement Date129 ## Movement Date
96 <Column ss:AutoFitWidth="1" ss:Width="72.25" />130 <Column ss:AutoFitWidth="1" ss:Width="72.25" />
97 ## Move Ref.131 ## Move Ref.
98 <Column ss:AutoFitWidth="1" ss:Width="135.75" />132 <Column ss:AutoFitWidth="1" ss:Width="105.75" />
99 ## Partner133 ## Partner
100 <Column ss:AutoFitWidth="1" ss:Width="135.75" />134 <Column ss:AutoFitWidth="1" ss:Width="135.75" />
101 ## Partner Type135 ## Partner Type
102 <Column ss:AutoFitWidth="1" ss:Width="72.0" />136 <Column ss:AutoFitWidth="1" ss:Width="65.5" />
103 ## Instance137 ## Instance
104 <Column ss:AutoFitWidth="1" ss:Width="112.25" />138 <Column ss:AutoFitWidth="1" ss:Width="172.25" />
105 ## Qty In139 ## Qty In
106 <Column ss:AutoFitWidth="1" ss:Width="54.25" />140 <Column ss:AutoFitWidth="1" ss:Width="74.25" />
107 ## Qty Out141 ## Qty Out
108 <Column ss:AutoFitWidth="1" ss:Width="54.25" />142 <Column ss:AutoFitWidth="1" ss:Width="74.25" />
109 ## Qty Balance143 ## Qty Balance
110 <Column ss:AutoFitWidth="1" ss:Width="54.25" />144 <Column ss:AutoFitWidth="1" ss:Width="69.25" />
111 ## PO/FO Ref.145 ## PO/FO Ref.
112 <Column ss:AutoFitWidth="1" ss:Width="302.0" />146 <Column ss:AutoFitWidth="1" ss:Width="282.0" />
113 ## Origin Ref.147 ## Origin Ref.
114 <Column ss:AutoFitWidth="1" ss:Width="202.0" />148 <Column ss:AutoFitWidth="1" ss:Width="152.0" />
115 ## Unit Price149 ## Unit Price
116 <Column ss:AutoFitWidth="1" ss:Width="57.25" />150 <Column ss:AutoFitWidth="1" ss:Width="57.25" />
117 ## Currency151 ## Currency
118 <Column ss:AutoFitWidth="1" ss:Width="65.75" />152 <Column ss:AutoFitWidth="1" ss:Width="45.75" />
119 ## Total Value153 ## Total Value
120 <Column ss:AutoFitWidth="1" ss:Width="67.25" />154 <Column ss:AutoFitWidth="1" ss:Width="62.25" />
121 ## Status155 ## Status
122 <Column ss:AutoFitWidth="1" ss:Width="67.25" />156 <Column ss:AutoFitWidth="1" ss:Width="42.25" />
123157
124 <%158 <%
125 headers_list = [159 headers_list = [
@@ -149,51 +183,43 @@
149 % endfor183 % endfor
150 </Row>184 </Row>
151185
152 % for o in getMoves(r):186 <% i = 0 %>
187 % for flow in getMoves(r):
188 <% i = 1 - i %>
189 % for o in flow:
153 <Row ss:Height="14.25">190 <Row ss:Height="14.25">
154 <Cell ss:StyleID="line_left"><Data ss:Type="String">${o.product_id.default_code|x}</Data></Cell>191 <Cell ss:StyleID="line_left${i}"><Data ss:Type="String">${o.product_id.default_code|x}</Data></Cell>
155 <Cell ss:StyleID="line_left"><Data ss:Type="String">${o.product_id.name|x}</Data></Cell>192 <Cell ss:StyleID="line_left${i}"><Data ss:Type="String">${o.product_id.name|x}</Data></Cell>
156 <Cell ss:StyleID="line_left"><Data ss:Type="String">${o.reason_type_id.name|x}</Data></Cell>193 <Cell ss:StyleID="line_left${i}"><Data ss:Type="String">${o.reason_type_id.name|x}</Data></Cell>
157 %if o.date and isDateTime(o.date):194 %if o.date and isDateTime(o.date):
158 <Cell ss:StyleID="sShortDate"><Data ss:Type="DateTime">${o.date[:10]|n}T${o.date[-8:]|n}.000</Data></Cell>195 <Cell ss:StyleID="sShortDate${i}"><Data ss:Type="DateTime">${o.date[:10]|n}T${o.date[-8:]|n}.000</Data></Cell>
159 % else:196 % else:
160 <Cell ss:StyleID="line_left"><Data ss:Type="String"></Data></Cell>197 <Cell ss:StyleID="line_left${i}"><Data ss:Type="String"></Data></Cell>
161 % endif198 % endif
162 <Cell ss:StyleID="line_left"><Data ss:Type="String">${o.picking_id.name or ''|x}</Data></Cell>199 <Cell ss:StyleID="line_left${i}"><Data ss:Type="String">${o.picking_id.name or ''|x}</Data></Cell>
163 <Cell ss:StyleID="line_left"><Data ss:Type="String">${o.partner_id.name or ''|x}</Data></Cell>200 <Cell ss:StyleID="line_left${i}"><Data ss:Type="String">${o.partner_id.name or ''|x}</Data></Cell>
164 <Cell ss:StyleID="line_left"><Data ss:Type="String">${o.partner_id.partner_type or ''|x}</Data></Cell>201 <Cell ss:StyleID="line_left${i}"><Data ss:Type="String">${o.partner_id.partner_type or ''|x}</Data></Cell>
165 <Cell ss:StyleID="line_right"><Data ss:Type="String">${getInstance()|x}</Data></Cell>202 <Cell ss:StyleID="line_left${i}"><Data ss:Type="String">${getUserCompany()['instance_id'].name|x}</Data></Cell>
166 % if isQtyOut(o):203 % if isQtyOut(o):
167 <Cell ss:StyleID="line_right"><Data ss:Type="String"></Data></Cell>204 <Cell ss:StyleID="line_right${i}"><Data ss:Type="String"></Data></Cell>
168 <Cell ss:StyleID="line_right"><Data ss:Type="Number">${getQty(o)|x}</Data></Cell>205 <Cell ss:StyleID="line_right${i}"><Data ss:Type="Number">${getQty(o)|x}</Data></Cell>
169 % else:206 % else:
170 <Cell ss:StyleID="line_right"><Data ss:Type="Number">${getQty(o)|x}</Data></Cell>207 <Cell ss:StyleID="line_right${i}"><Data ss:Type="Number">${getQty(o)|x}</Data></Cell>
171 <Cell ss:StyleID="line_right"><Data ss:Type="String"></Data></Cell>208 <Cell ss:StyleID="line_right${i}"><Data ss:Type="String"></Data></Cell>
172 % endif209 % endif
173 % if o.balance:210 % if o.balance:
174 <Cell ss:StyleID="line_right"><Data ss:Type="String">${o.balance|x}</Data></Cell>211 <Cell ss:StyleID="line_right${i}"><Data ss:Type="Number">${o.balance|x}</Data></Cell>
175 % else:212 % else:
176 <Cell ss:StyleID="line_right"><Data ss:Type="String"></Data></Cell>213 <Cell ss:StyleID="line_right${i}"><Data ss:Type="String"></Data></Cell>
177 %endif214 %endif
178 <Cell ss:StyleID="line_left"><Data ss:Type="String">${o.origin|x}</Data></Cell>215 <Cell ss:StyleID="line_left${i}"><Data ss:Type="String">${o.origin|x}</Data></Cell>
179 <Cell ss:StyleID="line_left"><Data ss:Type="String">${o.purchase_line_id.sync_order_line_db_id or o.sale_line_id.sync_order_line_db_id or ''|x}</Data></Cell>216 <Cell ss:StyleID="line_left${i}"><Data ss:Type="String">${getFirstSplitOnUnderscore(o.purchase_line_id.sync_order_line_db_id) or getFirstSplitOnUnderscore(o.sale_line_id.sync_order_line_db_id) or ''|x}</Data></Cell>
180 % if o.price_unit:217 <Cell ss:StyleID="line_right${i}"><Data ss:Type="Number">${computeCurrency(o)|x}</Data></Cell>
181 <Cell ss:StyleID="line_right"><Data ss:Type="Number">${round(o.price_unit, 3)|x}</Data></Cell>218 <Cell ss:StyleID="line_left${i}"><Data ss:Type="String">${getUserCompany()['currency_id'].name|x}</Data></Cell>
182 % else:219 <Cell ss:StyleID="line_right${i}"><Data ss:Type="Number">${computeCurrency(o) * getQty(o)|x}</Data></Cell>
183 <Cell ss:StyleID="line_right"><Data ss:Type="Number">${round(o.product_id.standard_price, 3)|x}</Data></Cell>220 <Cell ss:StyleID="line_left${i}"><Data ss:Type="String">${o.status|x}</Data></Cell>
184 % endif
185 % if o.price_currency_id.name:
186 <Cell ss:StyleID="line_left"><Data ss:Type="String">${o.price_currency_id.name|x}</Data></Cell>
187 % else:
188 <Cell ss:StyleID="line_left"><Data ss:Type="String">${o.product_id.currency_id.name or ''|x}</Data></Cell>
189 % endif
190 % if o.price_unit:
191 <Cell ss:StyleID="line_right"><Data ss:Type="Number">${round(o.price_unit, 3) * getQty(o)|x}</Data></Cell>
192 % else:
193 <Cell ss:StyleID="line_right"><Data ss:Type="Number">${round(o.product_id.standard_price, 3) * getQty(o)|x}</Data></Cell>
194 % endif
195 <Cell ss:StyleID="line_left"><Data ss:Type="String">${o.status|x}</Data></Cell>
196 </Row>221 </Row>
222 % endfor
197 % endfor223 % endfor
198224
199 </Table>225 </Table>

Subscribers

People subscribed via source and target branches