Skip to main content
back to blog

building a warehouse picking management api at alfamart

building a warehouse picking management api at alfamart

one of the projects i worked on at alfamart supply & distribution was a flask rest api for warehouse picking management, part of the same program that replaced legacy visual basic and oracle systems with flask and postgresql. i built it with a team. this is a case study on what i built, what the team built, and why i am careful about the number people usually reach for when they describe how much of a codebase is theirs.

what the system does

the picking management system serves two clients: a mobile app for warehouse pickers who scan items and confirm quantities, and a desktop app for supervisors who monitor real-time picking progress across zones. the backend handles picking sessions, barcode validation, plu lookups, gateway synchronization with multiple distribution centers, and supervisor dashboard data.

the codebase is approximately 16,000 lines of python, organized with flask blueprints separating the mobile api under /api/mobile and the desktop supervisor dashboard under /api/web. it was built by a team, and by commit count i am the largest contributor. that number carries a caveat that i give in full at the end of this post, because commit count is a weak proxy for how work is actually divided.

what i actually built

being precise about contribution matters here. this was a team effort on a migration, not a solo build, so rather than quoting a percentage i would rather name the parts i can point at directly. the three areas where i did substantive work were barcode and plu endpoint development, gateway integration refactoring, and the password hashing improvement.

barcode and plu endpoints

i developed several api endpoints for item management in the mobile picking flow. the most used were barcode validation, which checks whether a scanned barcode corresponds to a valid item in the current picking session, and plu lookup, which retrieves item details by plu code. these endpoints are called on every scan, so they needed to be fast and return consistent error responses that the mobile app could handle gracefully.

# simplified plu lookup endpoint
@mobile_bp.route('/api/mobile/plu/<barcode>', methods=['GET'])
@login_required
def get_plu_by_barcode(barcode):
    conn = get_db_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(
                "SELECT plu, nama_barang, satuan FROM master_barang WHERE barcode = %s",
                (barcode,)
            )
            row = cur.fetchone()
            if not row:
                return jsonify({'error': 'barcode not found'}), 404
            return jsonify({'plu': row[0], 'nama': row[1], 'satuan': row[2]})
    finally:
        conn.close()

gateway integration

the system needed to synchronize master data and transactions between multiple distribution centers through a centralized gateway api. i refactored several modules to use this gateway pattern instead of direct database connections. the gateway uses bearer token authentication and returns data that the backend then writes to the local postgresql database using psycopg2's execute_batch for batch inserts.

the gateway integration handles 15+ endpoints covering item master data, supplier data, and transaction records. error handling for network failures was important here because the gateway is an external dependency: if it is unavailable, the local system should degrade gracefully rather than crash.

password hashing

when i joined, user passwords were stored as plaintext. i implemented bcrypt hashing to replace the plaintext storage. this was a targeted improvement to the authentication flow, not a full security audit. the session management and concurrent login prevention logic was already in place; i only changed how passwords were stored and verified.

the postgresql connection pool

the system uses a threaded connection pool with a minimum of 5 and maximum of 100 connections. this is necessary because multiple pickers work simultaneously across different zones, and each request needs a database connection. the pool is initialized at application startup and connections are returned to the pool after each request. without pooling, each request would open and close a new connection, which is expensive and would not scale to concurrent warehouse operations.

what i learned from working in a shared codebase

building something with other people is a different skill from building it alone. you have to read code you did not write, understand decisions you were not in the room for, and make changes that fit the patterns the team already agreed on rather than the patterns you would have picked by yourself. on a migration that pressure is sharper, because the shape of the old visual basic system keeps constraining what the new one is allowed to do. that is closer to how most professional software work actually happens than any project i had built before this.

the things i would improve if i had more time: the codebase is covered by unit tests written by a teammate, which mattered more than i expected when i was refactoring the gateway modules, because it meant i could change shared code without guessing what i had broken. what i would add on top of that is integration testing for the gateway synchronization path, since that is where failures cross a system boundary and unit tests cannot see them. the security middleware for rate limiting and input sanitization exists in the codebase but is not activated. enabling it would be a straightforward improvement. the session timeout of five minutes is also too short for warehouse workers who move between zones; activity-based renewal or a longer timeout would reduce friction.

honest positioning

this was a team project, and i want to be careful about how i describe my share of it. by commit count i am the largest contributor to this repository. i am stating the limitation of that number before anyone else has to: my habit is to commit one file at a time, which i picked up after losing work to a revert once, so my commit count is inflated relative to teammates who batch several files into a single commit. anyone comparing raw commit counts here would overestimate me. what i can say without a caveat is which parts i built, and those are the barcode and plu endpoints, the gateway integration refactor, and the bcrypt migration that replaced plaintext password storage. the rest was built with teammates. the value of this project for me is not a percentage. it is that i worked in a real migration with a complex codebase, professional tooling including docker and gcp ci/cd, and business requirements that came from actual warehouse operations.