1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
|
from odoo import fields, models, api, _
from odoo.exceptions import AccessError, UserError, ValidationError
from datetime import datetime, timedelta
import logging
from pytz import timezone
_logger = logging.getLogger(__name__)
class PurchaseOrder(models.Model):
_inherit = 'purchase.order'
sale_order_id = fields.Many2one('sale.order', string='Sale Order')
procurement_status = fields.Char(string='Procurement Status', compute='get_procurement_status', readonly=True)
po_status = fields.Selection([
('terproses', 'Terproses'),
('sebagian', 'Sebagian Diproses'),
('menunggu', 'Menunggu Diproses'),
])
approval_status = fields.Selection([
('pengajuan1', 'Approval Manager'), #siapa? darren - 11
('pengajuan2', 'Approval Pimpinan'), #akbar - 7 temporary not used
('approved', 'Approved'),
], string='Approval Status', readonly=True, copy=False, index=True, tracking=3)
delivery_amount = fields.Float('Delivery Amount', compute='compute_delivery_amount')
total_margin = fields.Float(
'Margin', compute='compute_total_margin',
help="Total Margin in Sales Order Header")
total_percent_margin = fields.Float(
'Margin%', compute='compute_total_margin',
help="Total % Margin in Sales Order Header")
total_so_margin = fields.Float(
'SO Margin', compute='compute_total_margin',
help="Total Margin in Sales Order Header")
total_so_percent_margin = fields.Float(
'SO Margin%', compute='compute_total_margin',
help="Total % Margin in Sales Order Header")
amount_total_without_service = fields.Float('AmtTotalWithoutService', compute='compute_amt_total_without_service')
summary_qty_po = fields.Float('Total Qty', compute='_compute_summary_qty')
summary_qty_receipt = fields.Float('Summary Qty Receipt', compute='_compute_summary_qty')
count_line_product = fields.Float('Total Item', compute='compute_count_line_product')
note_description = fields.Char(string='Note', help='bisa diisi sebagai informasi indent barang tertentu atau apapun')
def add_product_to_pricelist(self):
for line in self.order_line:
current_time = fields.Datetime.now(timezone('Asia/Jakarta')).strftime('%Y-%m-%d %H:%M:%S')
purchase_pricelist = self.env['purchase.pricelist'].search([
('product_id', '=', line.product_id.id),
('vendor_id', '=', line.order_id.partner_id.id)
])
purchase_pricelist = purchase_pricelist.with_context(update_by='system')
if not purchase_pricelist:
purchase_pricelist.create([{
'vendor_id': line.order_id.partner_id.id,
'product_id': line.product_id.id,
'product_price': 0.00,
'system_price': line.price_unit,
'system_last_update': current_time,
}])
return True
for pricelist in purchase_pricelist:
pricelist.write({
'system_last_update': current_time,
'system_price': line.price_unit
})
def _compute_date_planned(self):
for order in self:
if order.date_approve:
current_time = order.date_approve
delta_time = current_time + timedelta(days=2)
delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S')
order.date_planned = delta_time
else:
order.date_planned = False
def action_create_invoice(self):
res = super(PurchaseOrder, self).action_create_invoice()
if not self.env.user.is_accounting:
raise UserError('Hanya Accounting yang bisa membuat Bill')
return res
def calculate_line_no(self):
line_no = 0
for line in self.order_line:
if line.product_id.type == 'product':
line_no += 1
line.line_no = line_no
# _logger.info('Calculate PO Line No %s' % line.id)
def calculate_po_status_beginning(self):
purchases = self.env['purchase.order'].search([
('po_status', '=', False),
'|',
('state', '=', 'purchase'),
('state', '=', 'done')
])
for order in purchases:
sum_qty_received = sum_qty_po = 0
for po_line in order.order_line:
sum_qty_po += po_line.product_uom_qty
sum_qty_received += po_line.qty_received
if order.summary_qty_po == order.summary_qty_receipt:
order.po_status = 'terproses'
elif order.summary_qty_po > order.summary_qty_receipt > 0:
order.po_status = 'sebagian'
else:
order.po_status = 'menunggu'
_logger.info("Calculate PO Status %s" % order.id)
def calculate_po_status(self):
purchases = self.env['purchase.order'].search([
('po_status', '!=', 'terproses'),
# ('id', '=', 213),
])
for order in purchases:
sum_qty_received = sum_qty_po = 0
have_outstanding_pick = False
for pick in order.picking_ids:
if pick.state == 'draft' or pick.state == 'assigned' or pick.state == 'confirmed' or pick.state == 'waiting':
have_outstanding_pick = True
for po_line in order.order_line:
sum_qty_po += po_line.product_uom_qty
sum_qty_received += po_line.qty_received
if have_outstanding_pick:
# if order.summary_qty_po == order.summary_qty_receipt:
# order.po_status = 'terproses'
if order.summary_qty_po > order.summary_qty_receipt > 0:
order.po_status = 'sebagian'
else:
order.po_status = 'menunggu'
else:
order.po_status = 'terproses'
_logger.info("Calculate PO Status %s" % order.id)
def _compute_summary_qty(self):
for order in self:
sum_qty_po = sum_qty_receipt = 0
for line in order.order_line:
sum_qty_po += line.product_uom_qty
sum_qty_receipt += line.qty_received
order.summary_qty_po = sum_qty_po
order.summary_qty_receipt = sum_qty_receipt
def get_procurement_status(self):
for purchase_order in self:
# product_uom_qty = sum_qty_received = 0
#
# for order_line in purchase_order.order_line:
# product_uom_qty += order_line.product_uom_qty
# sum_qty_received += order_line.qty_received
if purchase_order.summary_qty_po == purchase_order.summary_qty_receipt:
status = 'Terproses'
elif purchase_order.summary_qty_po > purchase_order.summary_qty_receipt > 0:
status = 'Sebagian Diproses'
else:
status = 'Menunggu Diproses'
purchase_order.procurement_status = status
def sale_order_sync(self):
if not self.sale_order_id:
return
purchase_orders = self.search(['&', ('sale_order_id', '=', self.sale_order_id.id), ('id', '!=', self.id)])
products_exception = []
for purchase_order in purchase_orders:
for order_line in purchase_order.order_line:
products_exception.append(order_line.product_id.id)
self.order_line.unlink()
for order_line in self.sale_order_id.order_line:
if order_line.product_id.id and order_line.product_id.id not in products_exception:
qty_available = order_line.product_id.qty_onhand_bandengan + order_line.product_id.qty_incoming_bandengan - order_line.product_id.outgoing_qty
suggest = 'harus beli'
if qty_available > order_line.product_qty:
suggest = 'masih cukup'
values = {
'order_id': self.id,
'product_id': order_line.product_id.id,
'name': order_line.product_id.display_name,
'product_qty': order_line.product_qty,
'qty_available_store': qty_available,
'suggest': suggest,
}
self.order_line.create(values)
def compute_count_line_product(self):
for order in self:
count = 0
for line in order.order_line:
if line.product_id.type == 'product':
count += 1
if count == 0:
order.count_line_product = 1
else:
order.count_line_product = count
def compute_delivery_amount(self):
for order in self:
amount = 0
for line in order.order_line:
if line.product_id.type == 'service':
amount += line.price_total
order.delivery_amount = amount
def button_confirm(self):
res = super(PurchaseOrder, self).button_confirm()
if self.total_percent_margin < self.total_so_percent_margin and not self.env.user.is_purchasing_manager and not self.env.user.is_leader:
raise UserError("Beda Margin dengan Sales, harus approval Manager")
if not self.sale_order_id and not self.env.user.is_purchasing_manager and not self.env.user.is_leader:
raise UserError("Tidak ada link dengan SO, harus approval Manager")
send_email = False
for line in self.order_line:
if not line.product_id.purchase_ok:
raise UserError("Terdapat barang yang tidak bisa diproses")
if line.product_id:
self.add_product_to_pricelist()
if line.price_unit != line.price_vendor:
send_email = True
break
if send_email:
self._send_mail()
self.approval_status = 'approved'
self.po_status = 'menunggu'
self.calculate_line_no()
# override date planned added with two days
current_time = datetime.now()
delta_time = current_time + timedelta(days=2)
delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S')
self.date_planned = delta_time
return res
def _send_mail(self):
template_id = self.env.ref('indoteknik_custom.mail_template_po_sync_price').id
template = self.env['mail.template'].browse(template_id)
template.send_mail(self.id, force_send=True)
def po_approve(self):
if self.env.user.is_leader or self.env.user.is_purchasing_manager:
raise UserError("Bisa langsung Confirm")
elif self.total_percent_margin == self.total_so_percent_margin and self.sale_order_id:
raise UserError("Bisa langsung Confirm")
else:
self.approval_status = 'pengajuan1'
def re_calculate(self):
for line in self.order_line:
sale_order_line = self.env['sale.order.line'].search([
('product_id', '=', line.product_id.id),
('order_id', '=', line.order_id.sale_order_id.id)
], limit=1, order='price_reduce_taxexcl')
for so_line in sale_order_line:
unit_price = line.price_unit
so_line.purchase_price = unit_price
def button_cancel(self):
res = super(PurchaseOrder, self).button_cancel()
self.approval_status = False
return res
def compute_total_margin(self):
sum_so_margin = sum_sales_price = sum_margin = 0
for line in self.order_line:
sale_order_line = self.env['sale.order.line'].search(
[('product_id', '=', line.product_id.id),
('order_id', '=', line.order_id.sale_order_id.id)], limit=1, order='price_reduce_taxexcl')
sum_so_margin += sale_order_line.item_margin
sales_price = sale_order_line.price_reduce_taxexcl * sale_order_line.product_uom_qty
if sale_order_line.order_id.shipping_cost_covered == 'indoteknik':
sales_price -= sale_order_line.delivery_amt_line
if sale_order_line.order_id.fee_third_party > 0:
sales_price -= sale_order_line.fee_third_party_line
sum_sales_price += sales_price
purchase_price = line.price_subtotal
if line.order_id.delivery_amount > 0:
purchase_price += line.delivery_amt_line
real_item_margin = sales_price - purchase_price
sum_margin += real_item_margin
if sum_so_margin != 0 and sum_sales_price != 0 and sum_margin != 0:
self.total_so_margin = sum_so_margin
self.total_so_percent_margin = round((sum_so_margin / sum_sales_price), 2) * 100
self.total_margin = sum_margin
self.total_percent_margin = round((sum_margin / sum_sales_price), 2) * 100
else:
self.total_margin = 0
self.total_percent_margin = 0
self.total_so_margin = 0
self.total_so_percent_margin = 0
def compute_amt_total_without_service(self):
for order in self:
sum_price_total = 0
for line in order.order_line:
if line.product_id.type == 'product':
sum_price_total += line.price_total
order.amount_total_without_service = sum_price_total
|