summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIT Fixcomart <it@fixcomart.co.id>2025-11-11 10:50:15 +0000
committerIT Fixcomart <it@fixcomart.co.id>2025-11-11 10:50:15 +0000
commit70e0338e0423a56203043fa2a0211f1e8f6bcf1a (patch)
treebb40da5603d30b9856149c48e8ddb75b25aee47f
parent704f27afd94787260543a2b6fed2ecfa13e786cb (diff)
parent4c69c892f7b8ef7ec0877023f3f9544c8e9eb42c (diff)
Merged in cr_delivery_sj (pull request #459)
Cr delivery sj
-rw-r--r--indoteknik_api/controllers/api_v1/stock_picking.py79
-rw-r--r--indoteknik_custom/models/stock_picking.py42
-rwxr-xr-xindoteknik_custom/security/ir.model.access.csv1
-rw-r--r--indoteknik_custom/views/stock_picking.xml10
4 files changed, 101 insertions, 31 deletions
diff --git a/indoteknik_api/controllers/api_v1/stock_picking.py b/indoteknik_api/controllers/api_v1/stock_picking.py
index fe82e665..c19812f5 100644
--- a/indoteknik_api/controllers/api_v1/stock_picking.py
+++ b/indoteknik_api/controllers/api_v1/stock_picking.py
@@ -124,35 +124,86 @@ class StockPicking(controller.Controller):
@http.route(prefix + 'stock-picking/<scanid>/documentation', auth='public', methods=['PUT', 'OPTIONS'], csrf=False)
@controller.Controller.must_authorized()
def write_partner_stock_picking_documentation(self, scanid, **kw):
- sj_document = kw.get('sj_document') if 'sj_document' in kw else None
paket_document = kw.get('paket_document') if 'paket_document' in kw else None
dispatch_document = kw.get('dispatch_document') if 'dispatch_document' in kw else None
- self_pu= kw.get('self_pu') if 'self_pu' in kw else None
+ self_pu = kw.get('self_pu') if 'self_pu' in kw else None
# ===== Cari picking by id / picking_code =====
- picking_data = False
+ picking = False
if scanid.isdigit() and int(scanid) < 2147483646:
- picking_data = request.env['stock.picking'].search([('id', '=', int(scanid))], limit=0)
+ picking = request.env['stock.picking'].search([('id', '=', int(scanid))], limit=0)
+ if not picking:
+ picking = request.env['stock.picking'].search([('picking_code', '=', scanid)], limit=0)
+ if not picking:
+ return self.response(code=403, description='picking not found')
- if not picking_data:
- picking_data = request.env['stock.picking'].search([('picking_code', '=', scanid)], limit=0)
+ # ===== Ambil MULTIPLE SJ dari form: sj_documentations=...&sj_documentations=... =====
+ form = request.httprequest.form or {}
+ sj_list = form.getlist('sj_documentations') # list of base64 strings
- if not picking_data:
- return self.response(code=403, description='picking not found')
+ # fallback: kalau FE kirim single dengan nama yang sama (bukan list)
+ if not sj_list and 'sj_documentations' in kw and kw.get('sj_documentations'):
+ sj_list = [kw.get('sj_documentations')]
params = {}
- if sj_document:
- params['sj_documentation'] = sj_document
- if self_pu:
- params['driver_arrival_date'] = datetime.utcnow()
if paket_document:
params['paket_documentation'] = paket_document
params['driver_arrival_date'] = datetime.utcnow()
if dispatch_document:
params['dispatch_documentation'] = dispatch_document
+ if sj_list and self_pu:
+ params['driver_arrival_date'] = datetime.utcnow()
- picking_data.write(params)
- return self.response({'name': picking_data.name})
+ if params:
+ picking.write(params)
+
+ if sj_list:
+ Child = request.env['stock.picking.sj.document'].sudo()
+ seq = (picking.sj_documentations[:1].sequence or 10) if picking.sj_documentations else 10
+ for b64 in sj_list:
+ if not b64:
+ continue
+ Child.create({
+ 'picking_id': picking.id,
+ 'sequence': seq,
+ 'image': b64,
+ })
+ seq += 10
+
+ return self.response({'name': picking.name})
+
+ # @http.route(prefix + 'stock-picking/<scanid>/documentation', auth='public', methods=['PUT', 'OPTIONS'], csrf=False)
+ # @controller.Controller.must_authorized()
+ # def write_partner_stock_picking_documentation(self, scanid, **kw):
+ # sj_document = kw.get('sj_document') if 'sj_document' in kw else None
+ # paket_document = kw.get('paket_document') if 'paket_document' in kw else None
+ # dispatch_document = kw.get('dispatch_document') if 'dispatch_document' in kw else None
+ # self_pu= kw.get('self_pu') if 'self_pu' in kw else None
+ #
+ # # ===== Cari picking by id / picking_code =====
+ # picking_data = False
+ # if scanid.isdigit() and int(scanid) < 2147483646:
+ # picking_data = request.env['stock.picking'].search([('id', '=', int(scanid))], limit=0)
+ #
+ # if not picking_data:
+ # picking_data = request.env['stock.picking'].search([('picking_code', '=', scanid)], limit=0)
+ #
+ # if not picking_data:
+ # return self.response(code=403, description='picking not found')
+ #
+ # params = {}
+ # if sj_document:
+ # params['sj_documentation'] = sj_document
+ # if self_pu:
+ # params['driver_arrival_date'] = datetime.utcnow()
+ # if paket_document:
+ # params['paket_documentation'] = paket_document
+ # params['driver_arrival_date'] = datetime.utcnow()
+ # if dispatch_document:
+ # params['dispatch_documentation'] = dispatch_document
+ #
+ # picking_data.write(params)
+ # return self.response({'name': picking_data.name})
@http.route(prefix + 'webhook/biteship', type='json', auth='public', methods=['POST'], csrf=False)
diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py
index eb9d8eda..49001974 100644
--- a/indoteknik_custom/models/stock_picking.py
+++ b/indoteknik_custom/models/stock_picking.py
@@ -89,6 +89,7 @@ class StockPicking(models.Model):
readonly=True,
related="id",
)
+ sj_documentations = fields.One2many('stock.picking.sj.document','picking_id', string='Dokumentasi SJ (Multi)')
sj_documentation = fields.Binary(string="Dokumentasi Surat Jalan")
paket_documentation = fields.Binary(string="Dokumentasi Paket")
dispatch_documentation = fields.Binary(string="Dokumentasi Dispatch")
@@ -473,7 +474,6 @@ class StockPicking(models.Model):
except ValueError:
return False
-
def action_get_kgx_pod(self, shipment=False):
self.ensure_one()
@@ -1225,7 +1225,8 @@ class StockPicking(models.Model):
self.sale_id.date_doc_kirim = self.date_doc_kirim
def action_assign(self):
- if self.env.context.get('default_picking_type_id') and ('BU/INPUT' not in self.name or 'BU/PUT' not in self.name):
+ if self.env.context.get('default_picking_type_id') and (
+ 'BU/INPUT' not in self.name or 'BU/PUT' not in self.name):
pickings_to_assign = self.filtered(
lambda p: not (p.sale_id and p.sale_id.hold_outgoing)
)
@@ -1241,18 +1242,15 @@ class StockPicking(models.Model):
return res
-
def ask_approval(self):
# if self.env.user.is_accounting:
# if self.env.user.is_accounting and self.location_id.id == 57 or self.location_id == 57 and self.approval_status in ['pengajuan1', ''] and 'BU/IU' in self.name and self.approval_status == 'pengajuan1':
# raise UserError("Bisa langsung set ke approval logistik")
if self.env.user.is_accounting and self.approval_status == "pengajuan2" and 'BU/IU' in self.name:
raise UserError("Tidak perlu ask approval sudah approval logistik")
- if self.env.user.is_logistic_approver and self.location_id.id == 57 or self.location_id== 57 and self.approval_status == 'pengajuan2' and 'BU/IU' in self.name:
+ if self.env.user.is_logistic_approver and self.location_id.id == 57 or self.location_id == 57 and self.approval_status == 'pengajuan2' and 'BU/IU' in self.name:
raise UserError("Bisa langsung Validate")
-
-
# for calendar distribute only
# if self.is_internal_use:
# stock_move_lines = self.env['stock.move.line'].search([
@@ -1275,7 +1273,6 @@ class StockPicking(models.Model):
raise UserError("Qty tidak boleh 0")
pick.approval_status = 'pengajuan1'
-
def ask_receipt_approval(self):
if self.env.user.is_logistic_approver:
raise UserError('Bisa langsung validate tanpa Ask Receipt')
@@ -1443,7 +1440,7 @@ class StockPicking(models.Model):
and self.create_date > threshold_datetime
and not self.so_lama):
raise UserError(_("Tidak ada scan koli! Harap periksa kembali."))
-
+
if 'BU/OUT/' in self.name:
self.driver_departure_date = datetime.datetime.utcnow()
@@ -1488,13 +1485,16 @@ class StockPicking(models.Model):
# if self.is_internal_use and not self.env.user.is_logistic_approver and self.location_id.id == 57 and self.approval_status == 'pengajuan2':
# raise UserError("Harus di Approve oleh Logistik")
- if self.is_internal_use and self.approval_status in ['pengajuan1', '', False] and 'BU/IU' in self.name and self.is_bu_iu == True:
+ if self.is_internal_use and self.approval_status in ['pengajuan1', '',
+ False] and 'BU/IU' in self.name and self.is_bu_iu == True:
raise UserError("Tidak Bisa Validate, set approval status ke approval logistik terlebih dahhulu")
- if self.is_internal_use and not self.env.user.is_logistic_approver and self.approval_status in ['pengajuan2'] and self.is_bu_iu == True and 'BU/IU' in self.name:
+ if self.is_internal_use and not self.env.user.is_logistic_approver and self.approval_status in [
+ 'pengajuan2'] and self.is_bu_iu == True and 'BU/IU' in self.name:
raise UserError("Harus di Approve oleh Logistik")
- if self.is_internal_use and not self.env.user.is_accounting and self.approval_status in ['pengajuan1', '', False] and self.is_bu_iu == False:
+ if self.is_internal_use and not self.env.user.is_accounting and self.approval_status in ['pengajuan1', '',
+ False] and self.is_bu_iu == False:
raise UserError("Harus di Approve oleh Accounting")
if self.picking_type_id.id == 28 and not self.env.user.is_logistic_approver:
@@ -1520,7 +1520,6 @@ class StockPicking(models.Model):
current_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
self.date_reserved = current_time
-
# Validate Qty Demand Can't higher than Qty Product
if self.location_dest_id.id == 58 and 'BU/INPUT/' in self.name:
for move in self.move_ids_without_package:
@@ -1934,7 +1933,8 @@ class StockPicking(models.Model):
'name': move_line.product_id.name,
'code': move_line.product_id.default_code,
'qty': move_line.qty_done,
- 'image': self.env['ir.attachment'].api_image('product.template', 'image_128', move_line.product_id.product_tmpl_id.id),
+ 'image': self.env['ir.attachment'].api_image('product.template', 'image_128',
+ move_line.product_id.product_tmpl_id.id),
})
response = {
@@ -2300,7 +2300,6 @@ class CheckProduct(models.Model):
_order = 'picking_id, id'
_inherit = ['barcodes.barcode_events_mixin']
-
picking_id = fields.Many2one(
'stock.picking',
string='Picking Reference',
@@ -2753,8 +2752,6 @@ class ScanKoli(models.Model):
out_move.qty_done += qty_to_assign
qty_koli -= qty_to_assign
-
-
def _reset_qty_done_if_no_scan(self, picking_id):
product_bu_pick = self.env['stock.move.line'].search([('picking_id', '=', picking_id)])
@@ -2813,4 +2810,15 @@ class WarningModalWizard(models.TransientModel):
def action_continue(self):
if self.picking_id:
return self.picking_id.with_context(skip_koli_check=True).button_validate()
- return {'type': 'ir.actions.act_window_close'} \ No newline at end of file
+ return {'type': 'ir.actions.act_window_close'}
+
+
+class StockPickingSjDocument(models.Model):
+ _name = 'stock.picking.sj.document'
+ _description = 'Dokumentasi Surat Jalan (Multi)'
+ _order = 'sequence, id'
+ _rec_name = 'id'
+
+ picking_id = fields.Many2one('stock.picking', required=True, ondelete='cascade')
+ image = fields.Binary('Gambar', required=True, attachment=True)
+ sequence = fields.Integer('Urutan', default=10) \ No newline at end of file
diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv
index c01271d3..dadc2c82 100755
--- a/indoteknik_custom/security/ir.model.access.csv
+++ b/indoteknik_custom/security/ir.model.access.csv
@@ -210,3 +210,4 @@ access_unpaid_invoice_view,access.unpaid.invoice.view,model_unpaid_invoice_view,
access_surat_piutang_user,surat.piutang user,model_surat_piutang,,1,1,1,1
access_surat_piutang_line_user,surat.piutang.line user,model_surat_piutang_line,,1,1,1,1
access_sj_tele,access.sj.tele,model_sj_tele,base.group_system,1,1,1,1
+access_stock_picking_sj_document,stock.picking.sj.document,model_stock_picking_sj_document,base.group_system,1,1,1,1
diff --git a/indoteknik_custom/views/stock_picking.xml b/indoteknik_custom/views/stock_picking.xml
index 8e1e9d3e..4779c5d3 100644
--- a/indoteknik_custom/views/stock_picking.xml
+++ b/indoteknik_custom/views/stock_picking.xml
@@ -250,6 +250,16 @@
attrs="{'invisible': [('select_shipping_option_so', '=', 'biteship')]}"/>
<field name="driver_id"/>
<field name='sj_return_date'/>
+ <field name="sj_documentations" context="{'default_picking_id': active_id}">
+ <tree editable="bottom">
+ <field name="image" widget="image" options="{'size':[128,128]}"/>
+ </tree>
+ <form>
+ <group>
+ <field name="image" widget="image" options="{'size':[512,512]}"/>
+ </group>
+ </form>
+ </field>
<field name="sj_documentation" widget="image"/>
<field name="paket_documentation" widget="image"/>
<field name="dispatch_documentation" widget="image"/>