def sync_product_stock(domain, endpoint, facility, checkpoint, date, limit=100, offset=0): has_next = True next_url = "" while has_next: supply_point = facility case = SupplyPointCase.view('hqcase/by_domain_external_id', key=[domain, str(supply_point)], reduce=False, include_docs=True, limit=1).first() meta, product_stocks = endpoint.get_productstocks( next_url_params=next_url, limit=limit, offset=offset, filters=dict(supply_point=supply_point, last_modified__gte=date) ) save_stock_data_checkpoint(checkpoint, 'product_stock', meta.get('limit') or limit, meta.get('offset') or offset, date, facility, True) for product_stock in product_stocks: if case: product = Product.get_by_code(domain, product_stock.product) try: stock_state = StockState.objects.get(section_id='stock', case_id=case._id, product_id=product._id) stock_state.last_modified_date = product_stock.last_modified stock_state.stock_on_hand = product_stock.quantity or 0 except StockState.DoesNotExist: stock_state = StockState(section_id='stock', case_id=case._id, product_id=product._id, stock_on_hand=product_stock.quantity or 0, last_modified_date=product_stock.last_modified, sql_product=SQLProduct.objects.get(product_id=product._id)) if product_stock.auto_monthly_consumption: stock_state.daily_consumption = product_stock.auto_monthly_consumption / DAYS_IN_MONTH else: stock_state.daily_consumption = None stock_state.save() if not meta.get('next', False): has_next = False else: next_url = meta['next'].split('?')[1]
def new_stock_state(self, ref, transaction): return StockState( case_id=ref.case_id, section_id=ref.section_id, product_id=ref.entry_id, sql_location=self.get_location(ref.case_id), last_modified_date=transaction.report.server_date, last_modified_form_id=transaction.report.form_id, stock_on_hand=transaction.stock_on_hand, )
def get_stock_state_for_transaction(transaction): from corehq.apps.commtrack.models import StockState from corehq.apps.locations.models import SQLLocation from corehq.apps.products.models import SQLProduct # todo: in the worst case, this function makes # - three calls to couch (for the case, domain, and commtrack config) # - four postgres queries (transacitons, product, location, and state) # - one postgres write (to save the state) # and that doesn't even include the consumption calc, which can do a whole # bunch more work and hit the database. sql_product = SQLProduct.objects.get(product_id=transaction.product_id) try: domain_name = transaction.__domain except AttributeError: domain_name = sql_product.domain try: sql_location = SQLLocation.objects.get(supply_point_id=transaction.case_id) except SQLLocation.DoesNotExist: sql_location = None try: state = StockState.include_archived.get( section_id=transaction.section_id, case_id=transaction.case_id, product_id=transaction.product_id, ) except StockState.DoesNotExist: state = StockState( section_id=transaction.section_id, case_id=transaction.case_id, product_id=transaction.product_id, sql_product=sql_product, sql_location=sql_location, ) # we may not be saving the latest transaction so make sure we use that # todo: this should change to server date latest_transaction = StockTransaction.latest( case_id=transaction.case_id, section_id=transaction.section_id, product_id=transaction.product_id ) if latest_transaction != transaction: logging.warning( 'Just fired signal for a stale stock transaction. Domain: {}, instance: {},latest was {}'.format( domain_name, transaction, latest_transaction ) ) transaction = latest_transaction state.last_modified_date = transaction.report.server_date state.last_modified_form_id = transaction.report.form_id state.stock_on_hand = transaction.stock_on_hand # so you don't have to look it up again in the signal receivers if domain_name: state.__domain = domain_name return state
def get_product_stock(domain, endpoint): for facility in FACILITIES: has_next = True next_url = "" while has_next: meta, product_stocks = endpoint.get_productstocks(next_url_params=next_url, filters=dict(supply_point=facility)) for product_stock in product_stocks: case = SupplyPointCase.view('hqcase/by_domain_external_id', key=[domain, str(product_stock.supply_point_id)], reduce=False, include_docs=True, limit=1).first() product = Product.get_by_code(domain, product_stock.product_code) try: stock_state = StockState.objects.get(section_id='stock', case_id=case._id, product_id=product._id) except StockState.DoesNotExist: stock_state = StockState(section_id='stock', case_id=case._id, product_id=product._id, stock_on_hand=product_stock.quantity or 0, last_modified_date=product_stock.last_modified, sql_product=SQLProduct.objects.get(product_id=product._id)) if product_stock.auto_monthly_consumption: stock_state.daily_consumption = product_stock.auto_monthly_consumption / DAYS_IN_MONTH else: stock_state.daily_consumption = None stock_state.save() if not meta.get('next', False): has_next = False else: next_url = meta['next'].split('?')[1]
def test_domain_mapping(self): # make sure there's a fake case setup for this with self.assertRaises(DocDomainMapping.DoesNotExist): DocDomainMapping.objects.get(doc_id=self.sp._id) StockState( section_id='stock', case_id=self.sp._id, product_id=self.products[0]._id, last_modified_date=datetime.now(), ).save() self.assertEqual( self.domain.name, DocDomainMapping.objects.get(doc_id=self.sp._id).domain_name)
def stock_data(): from corehq.apps.commtrack.models import StockState from corehq.apps.commtrack.tests.util import make_product from corehq.apps.products.models import SQLProduct from casexml.apps.case.mock import CaseFactory product = make_product('domain', 'Sample Product 1', 'pp', None) case = CaseFactory('domain').create_case() stock_state = [ StockState( section_id=str(i), case_id=case.case_id, product_id=product._id, last_modified_date=datetime.utcnow(), sql_product=SQLProduct.objects.get(product_id=product._id), ) for i in range(3) ]
def get_stock_state_json(sql_ledger): """Build stock state JSON from latest transaction Returns empty dict if stock transactions do not exist. """ # similar to StockTransaction.latest(), but more efficient transactions = list(StockTransaction.get_ordered_transactions_for_stock( sql_ledger.case_id, sql_ledger.section_id, sql_ledger.product_id, ).select_related("report")[:1]) if not transactions: return {} transaction = transactions[0] return StockState( case_id=sql_ledger.case_id, section_id=sql_ledger.section_id, product_id=sql_ledger.product_id, sql_location=SQLLocation.objects.get_or_None(supply_point_id=sql_ledger.case_id), last_modified_date=transaction.report.server_date, last_modified_form_id=transaction.report.form_id, stock_on_hand=transaction.stock_on_hand, ).to_json()